blob: ae3c96c48e3d89a5af6cadedf014c14beaa9bf14 [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
146status_t BufferLayerConsumer::updateTexImage() {
147 ATRACE_CALL();
148 BLC_LOGV("updateTexImage");
149 Mutex::Autolock lock(mMutex);
150
151 if (mAbandoned) {
152 BLC_LOGE("updateTexImage: BufferLayerConsumer is abandoned!");
153 return NO_INIT;
154 }
155
156 // Make sure the EGL state is the same as in previous calls.
157 status_t err = checkAndUpdateEglStateLocked();
158 if (err != NO_ERROR) {
159 return err;
160 }
161
162 BufferItem item;
163
164 // Acquire the next buffer.
165 // In asynchronous mode the list is guaranteed to be one buffer
166 // deep, while in synchronous mode we use the oldest buffer.
167 err = acquireBufferLocked(&item, 0);
168 if (err != NO_ERROR) {
169 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
170 // We always bind the texture even if we don't update its contents.
171 BLC_LOGV("updateTexImage: no buffers were available");
Chia-I Wubd854bf2017-11-27 13:41:26 -0800172 glBindTexture(sTexTarget, mTexName);
Chia-I Wuf1405182017-11-27 11:29:21 -0800173 err = NO_ERROR;
174 } else {
175 BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
176 }
177 return err;
178 }
179
180 // Release the previous buffer.
181 err = updateAndReleaseLocked(item);
182 if (err != NO_ERROR) {
183 // We always bind the texture.
Chia-I Wubd854bf2017-11-27 13:41:26 -0800184 glBindTexture(sTexTarget, mTexName);
Chia-I Wuf1405182017-11-27 11:29:21 -0800185 return err;
186 }
187
188 // Bind the new buffer to the GL texture, and wait until it's ready.
189 return bindTextureImageLocked();
190}
191
Chia-I Wuf1405182017-11-27 11:29:21 -0800192status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
193 uint64_t maxFrameNumber) {
194 status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
195 if (err != NO_ERROR) {
196 return err;
197 }
198
199 // If item->mGraphicBuffer is not null, this buffer has not been acquired
200 // before, so any prior EglImage created is using a stale buffer. This
201 // replaces any old EglImage with a new one (using the new buffer).
202 if (item->mGraphicBuffer != NULL) {
203 int slot = item->mSlot;
204 mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
205 }
206
207 return NO_ERROR;
208}
209
Chia-I Wuf1405182017-11-27 11:29:21 -0800210status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
211 PendingRelease* pendingRelease) {
212 status_t err = NO_ERROR;
213
214 int slot = item.mSlot;
215
Chia-I Wuf1405182017-11-27 11:29:21 -0800216 // Confirm state.
217 err = checkAndUpdateEglStateLocked();
218 if (err != NO_ERROR) {
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800219 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
Chia-I Wuf1405182017-11-27 11:29:21 -0800220 return err;
221 }
222
223 // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
224 // if nessessary, for the gralloc buffer currently in the slot in
225 // ConsumerBase.
226 // We may have to do this even when item.mGraphicBuffer == NULL (which
227 // means the buffer was previously acquired).
228 err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
229 if (err != NO_ERROR) {
230 BLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay,
231 slot);
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800232 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
Chia-I Wuf1405182017-11-27 11:29:21 -0800233 return UNKNOWN_ERROR;
234 }
235
236 // Do whatever sync ops we need to do before releasing the old slot.
237 if (slot != mCurrentTexture) {
238 err = syncForReleaseLocked(mEglDisplay);
239 if (err != NO_ERROR) {
240 // Release the buffer we just acquired. It's not safe to
241 // release the old buffer, so instead we just drop the new frame.
242 // As we are still under lock since acquireBuffer, it is safe to
243 // release by slot.
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800244 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
Chia-I Wuf1405182017-11-27 11:29:21 -0800245 return err;
246 }
247 }
248
249 BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
250 mCurrentTextureImage != NULL ? mCurrentTextureImage->graphicBufferHandle() : 0, slot,
251 mSlots[slot].mGraphicBuffer->handle);
252
253 // Hang onto the pointer so that it isn't freed in the call to
254 // releaseBufferLocked() if we're in shared buffer mode and both buffers are
255 // the same.
256 sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
257
258 // release old buffer
259 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
260 if (pendingRelease == nullptr) {
261 status_t status =
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800262 releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
Chia-I Wuf1405182017-11-27 11:29:21 -0800263 if (status < NO_ERROR) {
264 BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
265 status);
266 err = status;
267 // keep going, with error raised [?]
268 }
269 } else {
270 pendingRelease->currentTexture = mCurrentTexture;
271 pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
Chia-I Wuf1405182017-11-27 11:29:21 -0800272 pendingRelease->isPending = true;
273 }
274 }
275
276 // Update the BufferLayerConsumer state.
277 mCurrentTexture = slot;
278 mCurrentTextureImage = nextTextureImage;
279 mCurrentCrop = item.mCrop;
280 mCurrentTransform = item.mTransform;
281 mCurrentScalingMode = item.mScalingMode;
282 mCurrentTimestamp = item.mTimestamp;
283 mCurrentDataSpace = item.mDataSpace;
284 mCurrentFence = item.mFence;
285 mCurrentFenceTime = item.mFenceTime;
286 mCurrentFrameNumber = item.mFrameNumber;
287
288 computeCurrentTransformMatrixLocked();
289
290 return err;
291}
292
293status_t BufferLayerConsumer::bindTextureImageLocked() {
294 if (mEglDisplay == EGL_NO_DISPLAY) {
295 ALOGE("bindTextureImage: invalid display");
296 return INVALID_OPERATION;
297 }
298
299 GLenum error;
300 while ((error = glGetError()) != GL_NO_ERROR) {
301 BLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
302 }
303
Chia-I Wubd854bf2017-11-27 13:41:26 -0800304 glBindTexture(sTexTarget, mTexName);
Chia-I Wuf1405182017-11-27 11:29:21 -0800305 if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == NULL) {
306 BLC_LOGE("bindTextureImage: no currently-bound texture");
307 return NO_INIT;
308 }
309
310 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, mCurrentCrop);
311 if (err != NO_ERROR) {
312 BLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay,
313 mCurrentTexture);
314 return UNKNOWN_ERROR;
315 }
Chia-I Wubd854bf2017-11-27 13:41:26 -0800316 mCurrentTextureImage->bindToTextureTarget(sTexTarget);
Chia-I Wuf1405182017-11-27 11:29:21 -0800317
Chia-I Wuf1405182017-11-27 11:29:21 -0800318 // Wait for the new buffer to be ready.
319 return doGLFenceWaitLocked();
320}
321
Chia-I Wuc91077c2017-11-27 13:32:04 -0800322status_t BufferLayerConsumer::checkAndUpdateEglStateLocked() {
Chia-I Wuf1405182017-11-27 11:29:21 -0800323 EGLDisplay dpy = eglGetCurrentDisplay();
324 EGLContext ctx = eglGetCurrentContext();
325
Chia-I Wuc91077c2017-11-27 13:32:04 -0800326 // if this is the first time we're called, mEglDisplay/mEglContext have
327 // never been set, so don't error out (below).
328 if (mEglDisplay == EGL_NO_DISPLAY) {
329 mEglDisplay = dpy;
330 }
331 if (mEglContext == EGL_NO_CONTEXT) {
332 mEglContext = ctx;
Chia-I Wuf1405182017-11-27 11:29:21 -0800333 }
334
335 if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
336 BLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
337 return INVALID_OPERATION;
338 }
339
340 if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
341 BLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
342 return INVALID_OPERATION;
343 }
344
Chia-I Wuf1405182017-11-27 11:29:21 -0800345 return NO_ERROR;
346}
347
348void BufferLayerConsumer::setReleaseFence(const sp<Fence>& fence) {
349 if (fence->isValid() && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
350 status_t err =
351 addReleaseFence(mCurrentTexture, mCurrentTextureImage->graphicBuffer(), fence);
352 if (err != OK) {
353 BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
354 }
355 }
356}
357
Chia-I Wuf1405182017-11-27 11:29:21 -0800358status_t BufferLayerConsumer::syncForReleaseLocked(EGLDisplay dpy) {
359 BLC_LOGV("syncForReleaseLocked");
360
361 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
362 if (SyncFeatures::getInstance().useNativeFenceSync()) {
363 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
364 if (sync == EGL_NO_SYNC_KHR) {
365 BLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError());
366 return UNKNOWN_ERROR;
367 }
368 glFlush();
369 int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
370 eglDestroySyncKHR(dpy, sync);
371 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
372 BLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
373 "fd: %#x",
374 eglGetError());
375 return UNKNOWN_ERROR;
376 }
377 sp<Fence> fence(new Fence(fenceFd));
378 status_t err = addReleaseFenceLocked(mCurrentTexture,
379 mCurrentTextureImage->graphicBuffer(), fence);
380 if (err != OK) {
381 BLC_LOGE("syncForReleaseLocked: error adding release fence: "
382 "%s (%d)",
383 strerror(-err), err);
384 return err;
385 }
Chia-I Wuf1405182017-11-27 11:29:21 -0800386 }
387 }
388
389 return OK;
390}
391
Chia-I Wuf1405182017-11-27 11:29:21 -0800392void BufferLayerConsumer::getTransformMatrix(float mtx[16]) {
393 Mutex::Autolock lock(mMutex);
394 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
395}
396
397void BufferLayerConsumer::setFilteringEnabled(bool enabled) {
398 Mutex::Autolock lock(mMutex);
399 if (mAbandoned) {
400 BLC_LOGE("setFilteringEnabled: BufferLayerConsumer is abandoned!");
401 return;
402 }
403 bool needsRecompute = mFilteringEnabled != enabled;
404 mFilteringEnabled = enabled;
405
406 if (needsRecompute && mCurrentTextureImage == NULL) {
407 BLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
408 }
409
410 if (needsRecompute && mCurrentTextureImage != NULL) {
411 computeCurrentTransformMatrixLocked();
412 }
413}
414
415void BufferLayerConsumer::computeCurrentTransformMatrixLocked() {
416 BLC_LOGV("computeCurrentTransformMatrixLocked");
417 sp<GraphicBuffer> buf =
418 (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer();
419 if (buf == nullptr) {
420 BLC_LOGD("computeCurrentTransformMatrixLocked: "
421 "mCurrentTextureImage is NULL");
422 }
Chia-I Wu243b74a2017-11-27 14:24:14 -0800423 GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf,
424 isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT
425 : mCurrentCrop,
426 mCurrentTransform, mFilteringEnabled);
Chia-I Wuf1405182017-11-27 11:29:21 -0800427}
428
Chia-I Wuf1405182017-11-27 11:29:21 -0800429nsecs_t BufferLayerConsumer::getTimestamp() {
430 BLC_LOGV("getTimestamp");
431 Mutex::Autolock lock(mMutex);
432 return mCurrentTimestamp;
433}
434
435android_dataspace BufferLayerConsumer::getCurrentDataSpace() {
436 BLC_LOGV("getCurrentDataSpace");
437 Mutex::Autolock lock(mMutex);
438 return mCurrentDataSpace;
439}
440
441uint64_t BufferLayerConsumer::getFrameNumber() {
442 BLC_LOGV("getFrameNumber");
443 Mutex::Autolock lock(mMutex);
444 return mCurrentFrameNumber;
445}
446
447sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot) const {
448 Mutex::Autolock lock(mMutex);
449
450 if (outSlot != nullptr) {
451 *outSlot = mCurrentTexture;
452 }
453
454 return (mCurrentTextureImage == nullptr) ? NULL : mCurrentTextureImage->graphicBuffer();
455}
456
457Rect BufferLayerConsumer::getCurrentCrop() const {
458 Mutex::Autolock lock(mMutex);
459 return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
Chia-I Wue1e11872017-12-01 09:21:59 -0800460 ? GLConsumer::scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
Chia-I Wuf1405182017-11-27 11:29:21 -0800461 : mCurrentCrop;
462}
463
464uint32_t BufferLayerConsumer::getCurrentTransform() const {
465 Mutex::Autolock lock(mMutex);
466 return mCurrentTransform;
467}
468
469uint32_t BufferLayerConsumer::getCurrentScalingMode() const {
470 Mutex::Autolock lock(mMutex);
471 return mCurrentScalingMode;
472}
473
474sp<Fence> BufferLayerConsumer::getCurrentFence() const {
475 Mutex::Autolock lock(mMutex);
476 return mCurrentFence;
477}
478
479std::shared_ptr<FenceTime> BufferLayerConsumer::getCurrentFenceTime() const {
480 Mutex::Autolock lock(mMutex);
481 return mCurrentFenceTime;
482}
483
484status_t BufferLayerConsumer::doGLFenceWaitLocked() const {
485 EGLDisplay dpy = eglGetCurrentDisplay();
486 EGLContext ctx = eglGetCurrentContext();
487
488 if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
489 BLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
490 return INVALID_OPERATION;
491 }
492
493 if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
494 BLC_LOGE("doGLFenceWait: invalid current EGLContext");
495 return INVALID_OPERATION;
496 }
497
498 if (mCurrentFence->isValid()) {
499 if (SyncFeatures::getInstance().useWaitSync()) {
500 // Create an EGLSyncKHR from the current fence.
501 int fenceFd = mCurrentFence->dup();
502 if (fenceFd == -1) {
503 BLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
504 return -errno;
505 }
506 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
507 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
508 if (sync == EGL_NO_SYNC_KHR) {
509 close(fenceFd);
510 BLC_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError());
511 return UNKNOWN_ERROR;
512 }
513
514 // XXX: The spec draft is inconsistent as to whether this should
515 // return an EGLint or void. Ignore the return value for now, as
516 // it's not strictly needed.
517 eglWaitSyncKHR(dpy, sync, 0);
518 EGLint eglErr = eglGetError();
519 eglDestroySyncKHR(dpy, sync);
520 if (eglErr != EGL_SUCCESS) {
521 BLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr);
522 return UNKNOWN_ERROR;
523 }
524 } else {
525 status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doGLFenceWaitLocked");
526 if (err != NO_ERROR) {
527 BLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
528 return err;
529 }
530 }
531 }
532
533 return NO_ERROR;
534}
535
536void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
537 BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
538 if (slotIndex == mCurrentTexture) {
539 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
540 }
541 mEglSlots[slotIndex].mEglImage.clear();
542 ConsumerBase::freeBufferLocked(slotIndex);
543}
544
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800545void BufferLayerConsumer::onDisconnect() {
546 sp<Layer> l = mLayer.promote();
547 if (l.get()) {
548 l->onDisconnect();
549 }
550}
551
552void BufferLayerConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
553 FrameEventHistoryDelta* outDelta) {
554 sp<Layer> l = mLayer.promote();
555 if (l.get()) {
556 l->addAndGetFrameTimestamps(newTimestamps, outDelta);
557 }
558}
559
Chia-I Wuf1405182017-11-27 11:29:21 -0800560void BufferLayerConsumer::abandonLocked() {
561 BLC_LOGV("abandonLocked");
562 mCurrentTextureImage.clear();
563 ConsumerBase::abandonLocked();
564}
565
566status_t BufferLayerConsumer::setConsumerUsageBits(uint64_t usage) {
567 return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
568}
569
570void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const {
571 result.appendFormat("%smTexName=%d mCurrentTexture=%d\n"
572 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
573 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
574 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
575 mCurrentTransform);
576
577 ConsumerBase::dumpLocked(result, prefix);
578}
579
580BufferLayerConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer)
581 : mGraphicBuffer(graphicBuffer),
582 mEglImage(EGL_NO_IMAGE_KHR),
583 mEglDisplay(EGL_NO_DISPLAY),
584 mCropRect(Rect::EMPTY_RECT) {}
585
586BufferLayerConsumer::EglImage::~EglImage() {
587 if (mEglImage != EGL_NO_IMAGE_KHR) {
588 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
589 ALOGE("~EglImage: eglDestroyImageKHR failed");
590 }
591 eglTerminate(mEglDisplay);
592 }
593}
594
Chia-I Wuc91077c2017-11-27 13:32:04 -0800595status_t BufferLayerConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
596 const Rect& cropRect) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800597 // If there's an image and it's no longer valid, destroy it.
598 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
599 bool displayInvalid = mEglDisplay != eglDisplay;
600 bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
Chia-I Wuc91077c2017-11-27 13:32:04 -0800601 if (haveImage && (displayInvalid || cropInvalid)) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800602 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
603 ALOGE("createIfNeeded: eglDestroyImageKHR failed");
604 }
605 eglTerminate(mEglDisplay);
606 mEglImage = EGL_NO_IMAGE_KHR;
607 mEglDisplay = EGL_NO_DISPLAY;
608 }
609
610 // If there's no image, create one.
611 if (mEglImage == EGL_NO_IMAGE_KHR) {
612 mEglDisplay = eglDisplay;
613 mCropRect = cropRect;
614 mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
615 }
616
617 // Fail if we can't create a valid image.
618 if (mEglImage == EGL_NO_IMAGE_KHR) {
619 mEglDisplay = EGL_NO_DISPLAY;
620 mCropRect.makeInvalid();
621 const sp<GraphicBuffer>& buffer = mGraphicBuffer;
622 ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
623 buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
624 buffer->getPixelFormat());
625 return UNKNOWN_ERROR;
626 }
627
628 return OK;
629}
630
631void BufferLayerConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
632 glEGLImageTargetTexture2DOES(texTarget, static_cast<GLeglImageOES>(mEglImage));
633}
634
635EGLImageKHR BufferLayerConsumer::EglImage::createImage(EGLDisplay dpy,
636 const sp<GraphicBuffer>& graphicBuffer,
637 const Rect& crop) {
638 EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
639 const bool createProtectedImage =
640 (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) && hasEglProtectedContent();
641 EGLint attrs[] = {
642 EGL_IMAGE_PRESERVED_KHR,
643 EGL_TRUE,
644 EGL_IMAGE_CROP_LEFT_ANDROID,
645 crop.left,
646 EGL_IMAGE_CROP_TOP_ANDROID,
647 crop.top,
648 EGL_IMAGE_CROP_RIGHT_ANDROID,
649 crop.right,
650 EGL_IMAGE_CROP_BOTTOM_ANDROID,
651 crop.bottom,
652 createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
653 createProtectedImage ? EGL_TRUE : EGL_NONE,
654 EGL_NONE,
655 };
656 if (!crop.isValid()) {
657 // No crop rect to set, so leave the crop out of the attrib array. Make
658 // sure to propagate the protected content attrs if they are set.
659 attrs[2] = attrs[10];
660 attrs[3] = attrs[11];
661 attrs[4] = EGL_NONE;
662 } else if (!isEglImageCroppable(crop)) {
663 // The crop rect is not at the origin, so we can't set the crop on the
664 // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
665 // extension. In the future we can add a layered extension that
666 // removes this restriction if there is hardware that can support it.
667 attrs[2] = attrs[10];
668 attrs[3] = attrs[11];
669 attrs[4] = EGL_NONE;
670 }
671 eglInitialize(dpy, 0, 0);
672 EGLImageKHR image =
673 eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
674 if (image == EGL_NO_IMAGE_KHR) {
675 EGLint error = eglGetError();
676 ALOGE("error creating EGLImage: %#x", error);
677 eglTerminate(dpy);
678 }
679 return image;
680}
681
682}; // namespace android