blob: 0303d94340a05071bf0c084c5b106619624f9bd7 [file] [log] [blame]
Chia-I Wuf1405182017-11-27 11:29:21 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#undef LOG_TAG
18#define LOG_TAG "BufferLayerConsumer"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20//#define LOG_NDEBUG 0
21
22#include "BufferLayerConsumer.h"
23
Chia-I Wuc75c44d2017-11-27 14:32:57 -080024#include "Layer.h"
25
Chia-I Wuf1405182017-11-27 11:29:21 -080026#include <inttypes.h>
27
28#include <EGL/egl.h>
29#include <EGL/eglext.h>
30#include <GLES2/gl2.h>
31#include <GLES2/gl2ext.h>
32#include <cutils/compiler.h>
33
34#include <hardware/hardware.h>
35
36#include <math/mat4.h>
37
38#include <gui/BufferItem.h>
39#include <gui/GLConsumer.h>
40#include <gui/ISurfaceComposer.h>
41#include <gui/SurfaceComposerClient.h>
42
43#include <private/gui/ComposerService.h>
44#include <private/gui/SyncFeatures.h>
45
46#include <utils/Log.h>
47#include <utils/String8.h>
48#include <utils/Trace.h>
49
50extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
51#define CROP_EXT_STR "EGL_ANDROID_image_crop"
52#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
53#define EGL_PROTECTED_CONTENT_EXT 0x32C0
54
55namespace android {
56
57// Macros for including the BufferLayerConsumer name in log messages
58#define BLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
59#define BLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
60//#define BLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
61#define BLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
62#define BLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
63
Chia-I Wuf1405182017-11-27 11:29:21 -080064static const mat4 mtxIdentity;
65
Chia-I Wuf1405182017-11-27 11:29:21 -080066static bool hasEglAndroidImageCropImpl() {
67 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
68 const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
69 size_t cropExtLen = strlen(CROP_EXT_STR);
70 size_t extsLen = strlen(exts);
71 bool equal = !strcmp(CROP_EXT_STR, exts);
72 bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen + 1);
73 bool atEnd = (cropExtLen + 1) < extsLen &&
74 !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen + 1));
75 bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
76 return equal || atStart || atEnd || inMiddle;
77}
78
79static bool hasEglAndroidImageCrop() {
80 // Only compute whether the extension is present once the first time this
81 // function is called.
82 static bool hasIt = hasEglAndroidImageCropImpl();
83 return hasIt;
84}
85
86static bool hasEglProtectedContentImpl() {
87 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
88 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
89 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
90 size_t extsLen = strlen(exts);
91 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
92 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen + 1);
93 bool atEnd = (cropExtLen + 1) < extsLen &&
94 !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen + 1));
95 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
96 return equal || atStart || atEnd || inMiddle;
97}
98
99static bool hasEglProtectedContent() {
100 // Only compute whether the extension is present once the first time this
101 // function is called.
102 static bool hasIt = hasEglProtectedContentImpl();
103 return hasIt;
104}
105
106static bool isEglImageCroppable(const Rect& crop) {
107 return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
108}
109
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800110BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
111 Layer* layer)
Chia-I Wubd854bf2017-11-27 13:41:26 -0800112 : ConsumerBase(bq, false),
Chia-I Wuf1405182017-11-27 11:29:21 -0800113 mCurrentCrop(Rect::EMPTY_RECT),
114 mCurrentTransform(0),
115 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
116 mCurrentFence(Fence::NO_FENCE),
117 mCurrentTimestamp(0),
118 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
119 mCurrentFrameNumber(0),
120 mDefaultWidth(1),
121 mDefaultHeight(1),
122 mFilteringEnabled(true),
123 mTexName(tex),
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800124 mLayer(layer),
Chia-I Wuf1405182017-11-27 11:29:21 -0800125 mEglDisplay(EGL_NO_DISPLAY),
126 mEglContext(EGL_NO_CONTEXT),
Chia-I Wuc91077c2017-11-27 13:32:04 -0800127 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800128 BLC_LOGV("BufferLayerConsumer");
129
130 memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
131
132 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
133}
134
135status_t BufferLayerConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) {
136 Mutex::Autolock lock(mMutex);
137 if (mAbandoned) {
138 BLC_LOGE("setDefaultBufferSize: BufferLayerConsumer is abandoned!");
139 return NO_INIT;
140 }
141 mDefaultWidth = w;
142 mDefaultHeight = h;
143 return mConsumer->setDefaultBufferSize(w, h);
144}
145
Chia-I Wufd257f82017-11-27 14:51:06 -0800146void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedListener>& listener) {
147 setFrameAvailableListener(listener);
148 Mutex::Autolock lock(mMutex);
149 mContentsChangedListener = listener;
150}
151
Chia-I Wuf1405182017-11-27 11:29:21 -0800152status_t BufferLayerConsumer::updateTexImage() {
153 ATRACE_CALL();
154 BLC_LOGV("updateTexImage");
155 Mutex::Autolock lock(mMutex);
156
157 if (mAbandoned) {
158 BLC_LOGE("updateTexImage: BufferLayerConsumer is abandoned!");
159 return NO_INIT;
160 }
161
162 // Make sure the EGL state is the same as in previous calls.
163 status_t err = checkAndUpdateEglStateLocked();
164 if (err != NO_ERROR) {
165 return err;
166 }
167
168 BufferItem item;
169
170 // Acquire the next buffer.
171 // In asynchronous mode the list is guaranteed to be one buffer
172 // deep, while in synchronous mode we use the oldest buffer.
173 err = acquireBufferLocked(&item, 0);
174 if (err != NO_ERROR) {
175 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
176 // We always bind the texture even if we don't update its contents.
177 BLC_LOGV("updateTexImage: no buffers were available");
Chia-I Wubd854bf2017-11-27 13:41:26 -0800178 glBindTexture(sTexTarget, mTexName);
Chia-I Wuf1405182017-11-27 11:29:21 -0800179 err = NO_ERROR;
180 } else {
181 BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
182 }
183 return err;
184 }
185
186 // Release the previous buffer.
187 err = updateAndReleaseLocked(item);
188 if (err != NO_ERROR) {
189 // We always bind the texture.
Chia-I Wubd854bf2017-11-27 13:41:26 -0800190 glBindTexture(sTexTarget, mTexName);
Chia-I Wuf1405182017-11-27 11:29:21 -0800191 return err;
192 }
193
194 // Bind the new buffer to the GL texture, and wait until it's ready.
195 return bindTextureImageLocked();
196}
197
Chia-I Wuf1405182017-11-27 11:29:21 -0800198status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
199 uint64_t maxFrameNumber) {
200 status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
201 if (err != NO_ERROR) {
202 return err;
203 }
204
205 // If item->mGraphicBuffer is not null, this buffer has not been acquired
206 // before, so any prior EglImage created is using a stale buffer. This
207 // replaces any old EglImage with a new one (using the new buffer).
208 if (item->mGraphicBuffer != NULL) {
209 int slot = item->mSlot;
210 mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
211 }
212
213 return NO_ERROR;
214}
215
Chia-I Wuf1405182017-11-27 11:29:21 -0800216status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
217 PendingRelease* pendingRelease) {
218 status_t err = NO_ERROR;
219
220 int slot = item.mSlot;
221
Chia-I Wuf1405182017-11-27 11:29:21 -0800222 // Confirm state.
223 err = checkAndUpdateEglStateLocked();
224 if (err != NO_ERROR) {
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800225 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
Chia-I Wuf1405182017-11-27 11:29:21 -0800226 return err;
227 }
228
229 // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
230 // if nessessary, for the gralloc buffer currently in the slot in
231 // ConsumerBase.
232 // We may have to do this even when item.mGraphicBuffer == NULL (which
233 // means the buffer was previously acquired).
234 err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
235 if (err != NO_ERROR) {
236 BLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay,
237 slot);
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800238 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
Chia-I Wuf1405182017-11-27 11:29:21 -0800239 return UNKNOWN_ERROR;
240 }
241
242 // Do whatever sync ops we need to do before releasing the old slot.
243 if (slot != mCurrentTexture) {
244 err = syncForReleaseLocked(mEglDisplay);
245 if (err != NO_ERROR) {
246 // Release the buffer we just acquired. It's not safe to
247 // release the old buffer, so instead we just drop the new frame.
248 // As we are still under lock since acquireBuffer, it is safe to
249 // release by slot.
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800250 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
Chia-I Wuf1405182017-11-27 11:29:21 -0800251 return err;
252 }
253 }
254
255 BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
256 mCurrentTextureImage != NULL ? mCurrentTextureImage->graphicBufferHandle() : 0, slot,
257 mSlots[slot].mGraphicBuffer->handle);
258
259 // Hang onto the pointer so that it isn't freed in the call to
260 // releaseBufferLocked() if we're in shared buffer mode and both buffers are
261 // the same.
262 sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
263
264 // release old buffer
265 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
266 if (pendingRelease == nullptr) {
267 status_t status =
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800268 releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
Chia-I Wuf1405182017-11-27 11:29:21 -0800269 if (status < NO_ERROR) {
270 BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
271 status);
272 err = status;
273 // keep going, with error raised [?]
274 }
275 } else {
276 pendingRelease->currentTexture = mCurrentTexture;
277 pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
Chia-I Wuf1405182017-11-27 11:29:21 -0800278 pendingRelease->isPending = true;
279 }
280 }
281
282 // Update the BufferLayerConsumer state.
283 mCurrentTexture = slot;
284 mCurrentTextureImage = nextTextureImage;
285 mCurrentCrop = item.mCrop;
286 mCurrentTransform = item.mTransform;
287 mCurrentScalingMode = item.mScalingMode;
288 mCurrentTimestamp = item.mTimestamp;
289 mCurrentDataSpace = item.mDataSpace;
290 mCurrentFence = item.mFence;
291 mCurrentFenceTime = item.mFenceTime;
292 mCurrentFrameNumber = item.mFrameNumber;
293
294 computeCurrentTransformMatrixLocked();
295
296 return err;
297}
298
299status_t BufferLayerConsumer::bindTextureImageLocked() {
300 if (mEglDisplay == EGL_NO_DISPLAY) {
301 ALOGE("bindTextureImage: invalid display");
302 return INVALID_OPERATION;
303 }
304
305 GLenum error;
306 while ((error = glGetError()) != GL_NO_ERROR) {
307 BLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
308 }
309
Chia-I Wubd854bf2017-11-27 13:41:26 -0800310 glBindTexture(sTexTarget, mTexName);
Chia-I Wuf1405182017-11-27 11:29:21 -0800311 if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == NULL) {
312 BLC_LOGE("bindTextureImage: no currently-bound texture");
313 return NO_INIT;
314 }
315
316 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, mCurrentCrop);
317 if (err != NO_ERROR) {
318 BLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay,
319 mCurrentTexture);
320 return UNKNOWN_ERROR;
321 }
Chia-I Wubd854bf2017-11-27 13:41:26 -0800322 mCurrentTextureImage->bindToTextureTarget(sTexTarget);
Chia-I Wuf1405182017-11-27 11:29:21 -0800323
Chia-I Wuf1405182017-11-27 11:29:21 -0800324 // Wait for the new buffer to be ready.
325 return doGLFenceWaitLocked();
326}
327
Chia-I Wuc91077c2017-11-27 13:32:04 -0800328status_t BufferLayerConsumer::checkAndUpdateEglStateLocked() {
Chia-I Wuf1405182017-11-27 11:29:21 -0800329 EGLDisplay dpy = eglGetCurrentDisplay();
330 EGLContext ctx = eglGetCurrentContext();
331
Chia-I Wuc91077c2017-11-27 13:32:04 -0800332 // if this is the first time we're called, mEglDisplay/mEglContext have
333 // never been set, so don't error out (below).
334 if (mEglDisplay == EGL_NO_DISPLAY) {
335 mEglDisplay = dpy;
336 }
337 if (mEglContext == EGL_NO_CONTEXT) {
338 mEglContext = ctx;
Chia-I Wuf1405182017-11-27 11:29:21 -0800339 }
340
341 if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
342 BLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
343 return INVALID_OPERATION;
344 }
345
346 if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
347 BLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
348 return INVALID_OPERATION;
349 }
350
Chia-I Wuf1405182017-11-27 11:29:21 -0800351 return NO_ERROR;
352}
353
354void BufferLayerConsumer::setReleaseFence(const sp<Fence>& fence) {
355 if (fence->isValid() && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
356 status_t err =
357 addReleaseFence(mCurrentTexture, mCurrentTextureImage->graphicBuffer(), fence);
358 if (err != OK) {
359 BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
360 }
361 }
362}
363
Chia-I Wuf1405182017-11-27 11:29:21 -0800364status_t BufferLayerConsumer::syncForReleaseLocked(EGLDisplay dpy) {
365 BLC_LOGV("syncForReleaseLocked");
366
367 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
368 if (SyncFeatures::getInstance().useNativeFenceSync()) {
369 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
370 if (sync == EGL_NO_SYNC_KHR) {
371 BLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError());
372 return UNKNOWN_ERROR;
373 }
374 glFlush();
375 int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
376 eglDestroySyncKHR(dpy, sync);
377 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
378 BLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
379 "fd: %#x",
380 eglGetError());
381 return UNKNOWN_ERROR;
382 }
383 sp<Fence> fence(new Fence(fenceFd));
384 status_t err = addReleaseFenceLocked(mCurrentTexture,
385 mCurrentTextureImage->graphicBuffer(), fence);
386 if (err != OK) {
387 BLC_LOGE("syncForReleaseLocked: error adding release fence: "
388 "%s (%d)",
389 strerror(-err), err);
390 return err;
391 }
Chia-I Wuf1405182017-11-27 11:29:21 -0800392 }
393 }
394
395 return OK;
396}
397
Chia-I Wuf1405182017-11-27 11:29:21 -0800398void BufferLayerConsumer::getTransformMatrix(float mtx[16]) {
399 Mutex::Autolock lock(mMutex);
400 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
401}
402
403void BufferLayerConsumer::setFilteringEnabled(bool enabled) {
404 Mutex::Autolock lock(mMutex);
405 if (mAbandoned) {
406 BLC_LOGE("setFilteringEnabled: BufferLayerConsumer is abandoned!");
407 return;
408 }
409 bool needsRecompute = mFilteringEnabled != enabled;
410 mFilteringEnabled = enabled;
411
412 if (needsRecompute && mCurrentTextureImage == NULL) {
413 BLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
414 }
415
416 if (needsRecompute && mCurrentTextureImage != NULL) {
417 computeCurrentTransformMatrixLocked();
418 }
419}
420
421void BufferLayerConsumer::computeCurrentTransformMatrixLocked() {
422 BLC_LOGV("computeCurrentTransformMatrixLocked");
423 sp<GraphicBuffer> buf =
424 (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer();
425 if (buf == nullptr) {
426 BLC_LOGD("computeCurrentTransformMatrixLocked: "
427 "mCurrentTextureImage is NULL");
428 }
Chia-I Wu243b74a2017-11-27 14:24:14 -0800429 GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf,
430 isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT
431 : mCurrentCrop,
432 mCurrentTransform, mFilteringEnabled);
Chia-I Wuf1405182017-11-27 11:29:21 -0800433}
434
Chia-I Wuf1405182017-11-27 11:29:21 -0800435nsecs_t BufferLayerConsumer::getTimestamp() {
436 BLC_LOGV("getTimestamp");
437 Mutex::Autolock lock(mMutex);
438 return mCurrentTimestamp;
439}
440
441android_dataspace BufferLayerConsumer::getCurrentDataSpace() {
442 BLC_LOGV("getCurrentDataSpace");
443 Mutex::Autolock lock(mMutex);
444 return mCurrentDataSpace;
445}
446
447uint64_t BufferLayerConsumer::getFrameNumber() {
448 BLC_LOGV("getFrameNumber");
449 Mutex::Autolock lock(mMutex);
450 return mCurrentFrameNumber;
451}
452
453sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot) const {
454 Mutex::Autolock lock(mMutex);
455
456 if (outSlot != nullptr) {
457 *outSlot = mCurrentTexture;
458 }
459
460 return (mCurrentTextureImage == nullptr) ? NULL : mCurrentTextureImage->graphicBuffer();
461}
462
463Rect BufferLayerConsumer::getCurrentCrop() const {
464 Mutex::Autolock lock(mMutex);
465 return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
Chia-I Wue1e11872017-12-01 09:21:59 -0800466 ? GLConsumer::scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
Chia-I Wuf1405182017-11-27 11:29:21 -0800467 : mCurrentCrop;
468}
469
470uint32_t BufferLayerConsumer::getCurrentTransform() const {
471 Mutex::Autolock lock(mMutex);
472 return mCurrentTransform;
473}
474
475uint32_t BufferLayerConsumer::getCurrentScalingMode() const {
476 Mutex::Autolock lock(mMutex);
477 return mCurrentScalingMode;
478}
479
480sp<Fence> BufferLayerConsumer::getCurrentFence() const {
481 Mutex::Autolock lock(mMutex);
482 return mCurrentFence;
483}
484
485std::shared_ptr<FenceTime> BufferLayerConsumer::getCurrentFenceTime() const {
486 Mutex::Autolock lock(mMutex);
487 return mCurrentFenceTime;
488}
489
490status_t BufferLayerConsumer::doGLFenceWaitLocked() const {
491 EGLDisplay dpy = eglGetCurrentDisplay();
492 EGLContext ctx = eglGetCurrentContext();
493
494 if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
495 BLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
496 return INVALID_OPERATION;
497 }
498
499 if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
500 BLC_LOGE("doGLFenceWait: invalid current EGLContext");
501 return INVALID_OPERATION;
502 }
503
504 if (mCurrentFence->isValid()) {
505 if (SyncFeatures::getInstance().useWaitSync()) {
506 // Create an EGLSyncKHR from the current fence.
507 int fenceFd = mCurrentFence->dup();
508 if (fenceFd == -1) {
509 BLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
510 return -errno;
511 }
512 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
513 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
514 if (sync == EGL_NO_SYNC_KHR) {
515 close(fenceFd);
516 BLC_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError());
517 return UNKNOWN_ERROR;
518 }
519
520 // XXX: The spec draft is inconsistent as to whether this should
521 // return an EGLint or void. Ignore the return value for now, as
522 // it's not strictly needed.
523 eglWaitSyncKHR(dpy, sync, 0);
524 EGLint eglErr = eglGetError();
525 eglDestroySyncKHR(dpy, sync);
526 if (eglErr != EGL_SUCCESS) {
527 BLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr);
528 return UNKNOWN_ERROR;
529 }
530 } else {
531 status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doGLFenceWaitLocked");
532 if (err != NO_ERROR) {
533 BLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
534 return err;
535 }
536 }
537 }
538
539 return NO_ERROR;
540}
541
542void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
543 BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
544 if (slotIndex == mCurrentTexture) {
545 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
546 }
547 mEglSlots[slotIndex].mEglImage.clear();
548 ConsumerBase::freeBufferLocked(slotIndex);
549}
550
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800551void BufferLayerConsumer::onDisconnect() {
552 sp<Layer> l = mLayer.promote();
553 if (l.get()) {
554 l->onDisconnect();
555 }
556}
557
Chia-I Wufd257f82017-11-27 14:51:06 -0800558void BufferLayerConsumer::onSidebandStreamChanged() {
559 FrameAvailableListener* unsafeFrameAvailableListener = nullptr;
560 {
561 Mutex::Autolock lock(mFrameAvailableMutex);
562 unsafeFrameAvailableListener = mFrameAvailableListener.unsafe_get();
563 }
564 sp<ContentsChangedListener> listener;
565 { // scope for the lock
566 Mutex::Autolock lock(mMutex);
567 ALOG_ASSERT(unsafeFrameAvailableListener == mContentsChangedListener.unsafe_get());
568 listener = mContentsChangedListener.promote();
569 }
570
571 if (listener != NULL) {
572 listener->onSidebandStreamChanged();
573 }
574}
575
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800576void BufferLayerConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
577 FrameEventHistoryDelta* outDelta) {
578 sp<Layer> l = mLayer.promote();
579 if (l.get()) {
580 l->addAndGetFrameTimestamps(newTimestamps, outDelta);
581 }
582}
583
Chia-I Wuf1405182017-11-27 11:29:21 -0800584void BufferLayerConsumer::abandonLocked() {
585 BLC_LOGV("abandonLocked");
586 mCurrentTextureImage.clear();
587 ConsumerBase::abandonLocked();
588}
589
590status_t BufferLayerConsumer::setConsumerUsageBits(uint64_t usage) {
591 return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
592}
593
594void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const {
595 result.appendFormat("%smTexName=%d mCurrentTexture=%d\n"
596 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
597 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
598 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
599 mCurrentTransform);
600
601 ConsumerBase::dumpLocked(result, prefix);
602}
603
604BufferLayerConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer)
605 : mGraphicBuffer(graphicBuffer),
606 mEglImage(EGL_NO_IMAGE_KHR),
607 mEglDisplay(EGL_NO_DISPLAY),
608 mCropRect(Rect::EMPTY_RECT) {}
609
610BufferLayerConsumer::EglImage::~EglImage() {
611 if (mEglImage != EGL_NO_IMAGE_KHR) {
612 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
613 ALOGE("~EglImage: eglDestroyImageKHR failed");
614 }
615 eglTerminate(mEglDisplay);
616 }
617}
618
Chia-I Wuc91077c2017-11-27 13:32:04 -0800619status_t BufferLayerConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
620 const Rect& cropRect) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800621 // If there's an image and it's no longer valid, destroy it.
622 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
623 bool displayInvalid = mEglDisplay != eglDisplay;
624 bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
Chia-I Wuc91077c2017-11-27 13:32:04 -0800625 if (haveImage && (displayInvalid || cropInvalid)) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800626 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
627 ALOGE("createIfNeeded: eglDestroyImageKHR failed");
628 }
629 eglTerminate(mEglDisplay);
630 mEglImage = EGL_NO_IMAGE_KHR;
631 mEglDisplay = EGL_NO_DISPLAY;
632 }
633
634 // If there's no image, create one.
635 if (mEglImage == EGL_NO_IMAGE_KHR) {
636 mEglDisplay = eglDisplay;
637 mCropRect = cropRect;
638 mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
639 }
640
641 // Fail if we can't create a valid image.
642 if (mEglImage == EGL_NO_IMAGE_KHR) {
643 mEglDisplay = EGL_NO_DISPLAY;
644 mCropRect.makeInvalid();
645 const sp<GraphicBuffer>& buffer = mGraphicBuffer;
646 ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
647 buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
648 buffer->getPixelFormat());
649 return UNKNOWN_ERROR;
650 }
651
652 return OK;
653}
654
655void BufferLayerConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
656 glEGLImageTargetTexture2DOES(texTarget, static_cast<GLeglImageOES>(mEglImage));
657}
658
659EGLImageKHR BufferLayerConsumer::EglImage::createImage(EGLDisplay dpy,
660 const sp<GraphicBuffer>& graphicBuffer,
661 const Rect& crop) {
662 EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
663 const bool createProtectedImage =
664 (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) && hasEglProtectedContent();
665 EGLint attrs[] = {
666 EGL_IMAGE_PRESERVED_KHR,
667 EGL_TRUE,
668 EGL_IMAGE_CROP_LEFT_ANDROID,
669 crop.left,
670 EGL_IMAGE_CROP_TOP_ANDROID,
671 crop.top,
672 EGL_IMAGE_CROP_RIGHT_ANDROID,
673 crop.right,
674 EGL_IMAGE_CROP_BOTTOM_ANDROID,
675 crop.bottom,
676 createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
677 createProtectedImage ? EGL_TRUE : EGL_NONE,
678 EGL_NONE,
679 };
680 if (!crop.isValid()) {
681 // No crop rect to set, so leave the crop out of the attrib array. Make
682 // sure to propagate the protected content attrs if they are set.
683 attrs[2] = attrs[10];
684 attrs[3] = attrs[11];
685 attrs[4] = EGL_NONE;
686 } else if (!isEglImageCroppable(crop)) {
687 // The crop rect is not at the origin, so we can't set the crop on the
688 // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
689 // extension. In the future we can add a layered extension that
690 // removes this restriction if there is hardware that can support it.
691 attrs[2] = attrs[10];
692 attrs[3] = attrs[11];
693 attrs[4] = EGL_NONE;
694 }
695 eglInitialize(dpy, 0, 0);
696 EGLImageKHR image =
697 eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
698 if (image == EGL_NO_IMAGE_KHR) {
699 EGLint error = eglGetError();
700 ALOGE("error creating EGLImage: %#x", error);
701 eglTerminate(dpy);
702 }
703 return image;
704}
705
706}; // namespace android