1 /*
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 #define LOG_TAG "GLConsumer"
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 //#define LOG_NDEBUG 0
20
21 #define GL_GLEXT_PROTOTYPES
22 #define EGL_EGLEXT_PROTOTYPES
23
24 #include <inttypes.h>
25
26 #include <EGL/egl.h>
27 #include <EGL/eglext.h>
28 #include <GLES2/gl2.h>
29 #include <GLES2/gl2ext.h>
30 #include <cutils/compiler.h>
31
32 #include <hardware/hardware.h>
33
34 #include <math/mat4.h>
35
36 #include <gui/BufferItem.h>
37 #include <gui/DebugEGLImageTracker.h>
38 #include <gui/GLConsumer.h>
39 #include <gui/ISurfaceComposer.h>
40 #include <gui/SurfaceComposerClient.h>
41
42 #include <private/gui/ComposerService.h>
43 #include <private/gui/SyncFeatures.h>
44
45 #include <utils/Log.h>
46 #include <utils/String8.h>
47 #include <utils/Trace.h>
48
49 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
50 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
51
52 namespace android {
53
54 // Macros for including the GLConsumer name in log messages
55 #define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
56 #define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
57 // #define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.c_str(), ##__VA_ARGS__)
58 #define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.c_str(), ##__VA_ARGS__)
59 #define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.c_str(), ##__VA_ARGS__)
60
61 static const struct {
62 uint32_t width, height;
63 char const* bits;
64 } kDebugData = { 15, 12,
65 "_______________"
66 "_______________"
67 "_____XX_XX_____"
68 "__X_X_____X_X__"
69 "__X_XXXXXXX_X__"
70 "__XXXXXXXXXXX__"
71 "___XX_XXX_XX___"
72 "____XXXXXXX____"
73 "_____X___X_____"
74 "____X_____X____"
75 "_______________"
76 "_______________"
77 };
78
79 static const mat4 mtxIdentity;
80
81 Mutex GLConsumer::sStaticInitLock;
82 sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
83
hasEglProtectedContentImpl()84 static bool hasEglProtectedContentImpl() {
85 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
86 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
87 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
88 size_t extsLen = strlen(exts);
89 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
90 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
91 bool atEnd = (cropExtLen+1) < extsLen &&
92 !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
93 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
94 return equal || atStart || atEnd || inMiddle;
95 }
96
hasEglProtectedContent()97 static bool hasEglProtectedContent() {
98 // Only compute whether the extension is present once the first time this
99 // function is called.
100 static bool hasIt = hasEglProtectedContentImpl();
101 return hasIt;
102 }
103
104 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
GLConsumer(uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)105 GLConsumer::GLConsumer(uint32_t tex, uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
106 : ConsumerBase(isControlledByApp, /* isConsumerSurfaceFlinger */ false),
107 mCurrentCrop(Rect::EMPTY_RECT),
108 mCurrentTransform(0),
109 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
110 mCurrentFence(Fence::NO_FENCE),
111 mCurrentTimestamp(0),
112 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
113 mCurrentFrameNumber(0),
114 mDefaultWidth(1),
115 mDefaultHeight(1),
116 mFilteringEnabled(true),
117 mTexName(tex),
118 mUseFenceSync(useFenceSync),
119 mTexTarget(texTarget),
120 mEglDisplay(EGL_NO_DISPLAY),
121 mEglContext(EGL_NO_CONTEXT),
122 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
123 mAttached(true) {
124 GLC_LOGV("GLConsumer");
125
126 memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
127
128 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
129 }
130 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
131
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)132 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
133 uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
134 ConsumerBase(bq, isControlledByApp),
135 mCurrentCrop(Rect::EMPTY_RECT),
136 mCurrentTransform(0),
137 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
138 mCurrentFence(Fence::NO_FENCE),
139 mCurrentTimestamp(0),
140 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
141 mCurrentFrameNumber(0),
142 mDefaultWidth(1),
143 mDefaultHeight(1),
144 mFilteringEnabled(true),
145 mTexName(tex),
146 mUseFenceSync(useFenceSync),
147 mTexTarget(texTarget),
148 mEglDisplay(EGL_NO_DISPLAY),
149 mEglContext(EGL_NO_CONTEXT),
150 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
151 mAttached(true)
152 {
153 GLC_LOGV("GLConsumer");
154
155 memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
156 sizeof(mCurrentTransformMatrix));
157
158 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
159 }
160
161 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
GLConsumer(uint32_t texTarget,bool useFenceSync,bool isControlledByApp)162 GLConsumer::GLConsumer(uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
163 : ConsumerBase(isControlledByApp, /* isConsumerSurfaceFlinger */ false),
164 mCurrentCrop(Rect::EMPTY_RECT),
165 mCurrentTransform(0),
166 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
167 mCurrentFence(Fence::NO_FENCE),
168 mCurrentTimestamp(0),
169 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
170 mCurrentFrameNumber(0),
171 mDefaultWidth(1),
172 mDefaultHeight(1),
173 mFilteringEnabled(true),
174 mTexName(0),
175 mUseFenceSync(useFenceSync),
176 mTexTarget(texTarget),
177 mEglDisplay(EGL_NO_DISPLAY),
178 mEglContext(EGL_NO_CONTEXT),
179 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
180 mAttached(false) {
181 GLC_LOGV("GLConsumer");
182
183 memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
184
185 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
186 }
187 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
188
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)189 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget, bool useFenceSync,
190 bool isControlledByApp)
191 : ConsumerBase(bq, isControlledByApp),
192 mCurrentCrop(Rect::EMPTY_RECT),
193 mCurrentTransform(0),
194 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
195 mCurrentFence(Fence::NO_FENCE),
196 mCurrentTimestamp(0),
197 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
198 mCurrentFrameNumber(0),
199 mDefaultWidth(1),
200 mDefaultHeight(1),
201 mFilteringEnabled(true),
202 mTexName(0),
203 mUseFenceSync(useFenceSync),
204 mTexTarget(texTarget),
205 mEglDisplay(EGL_NO_DISPLAY),
206 mEglContext(EGL_NO_CONTEXT),
207 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
208 mAttached(false) {
209 GLC_LOGV("GLConsumer");
210
211 memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
212 sizeof(mCurrentTransformMatrix));
213
214 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
215 }
216
setDefaultBufferSize(uint32_t w,uint32_t h)217 status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
218 {
219 Mutex::Autolock lock(mMutex);
220 if (mAbandoned) {
221 GLC_LOGE("setDefaultBufferSize: GLConsumer is abandoned!");
222 return NO_INIT;
223 }
224 mDefaultWidth = w;
225 mDefaultHeight = h;
226 return mConsumer->setDefaultBufferSize(w, h);
227 }
228
updateTexImage()229 status_t GLConsumer::updateTexImage() {
230 ATRACE_CALL();
231 GLC_LOGV("updateTexImage");
232 Mutex::Autolock lock(mMutex);
233
234 if (mAbandoned) {
235 GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
236 return NO_INIT;
237 }
238
239 // Make sure the EGL state is the same as in previous calls.
240 status_t err = checkAndUpdateEglStateLocked();
241 if (err != NO_ERROR) {
242 return err;
243 }
244
245 BufferItem item;
246
247 // Acquire the next buffer.
248 // In asynchronous mode the list is guaranteed to be one buffer
249 // deep, while in synchronous mode we use the oldest buffer.
250 err = acquireBufferLocked(&item, 0);
251 if (err != NO_ERROR) {
252 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
253 // We always bind the texture even if we don't update its contents.
254 GLC_LOGV("updateTexImage: no buffers were available");
255 glBindTexture(mTexTarget, mTexName);
256 err = NO_ERROR;
257 } else {
258 GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
259 strerror(-err), err);
260 }
261 return err;
262 }
263
264 // Release the previous buffer.
265 err = updateAndReleaseLocked(item);
266 if (err != NO_ERROR) {
267 // We always bind the texture.
268 glBindTexture(mTexTarget, mTexName);
269 return err;
270 }
271
272 // Bind the new buffer to the GL texture, and wait until it's ready.
273 return bindTextureImageLocked();
274 }
275
276
releaseTexImage()277 status_t GLConsumer::releaseTexImage() {
278 ATRACE_CALL();
279 GLC_LOGV("releaseTexImage");
280 Mutex::Autolock lock(mMutex);
281
282 if (mAbandoned) {
283 GLC_LOGE("releaseTexImage: GLConsumer is abandoned!");
284 return NO_INIT;
285 }
286
287 // Make sure the EGL state is the same as in previous calls.
288 status_t err = NO_ERROR;
289
290 if (mAttached) {
291 err = checkAndUpdateEglStateLocked(true);
292 if (err != NO_ERROR) {
293 return err;
294 }
295 } else {
296 // if we're detached, no need to validate EGL's state -- we won't use it.
297 }
298
299 // Update the GLConsumer state.
300 int buf = mCurrentTexture;
301 if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
302
303 GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
304
305 if (mAttached) {
306 // Do whatever sync ops we need to do before releasing the slot.
307 err = syncForReleaseLocked(mEglDisplay);
308 if (err != NO_ERROR) {
309 GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
310 return err;
311 }
312 } else {
313 // if we're detached, we just use the fence that was created in detachFromContext()
314 // so... basically, nothing more to do here.
315 }
316
317 err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer);
318 if (err < NO_ERROR) {
319 GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
320 strerror(-err), err);
321 return err;
322 }
323
324 if (mReleasedTexImage == nullptr) {
325 mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
326 }
327
328 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
329 mCurrentTextureImage = mReleasedTexImage;
330 mCurrentCrop.makeInvalid();
331 mCurrentTransform = 0;
332 mCurrentTimestamp = 0;
333 mCurrentDataSpace = HAL_DATASPACE_UNKNOWN;
334 mCurrentFence = Fence::NO_FENCE;
335 mCurrentFenceTime = FenceTime::NO_FENCE;
336
337 if (mAttached) {
338 // This binds a buffer placeholder (mReleasedTexImage).
339 status_t result = bindTextureImageLocked();
340 if (result != NO_ERROR) {
341 return result;
342 }
343 } else {
344 // detached, don't touch the texture (and we may not even have an
345 // EGLDisplay here.
346 }
347 }
348
349 return NO_ERROR;
350 }
351
getDebugTexImageBuffer()352 sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
353 Mutex::Autolock _l(sStaticInitLock);
354 if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
355 // The first time, create the debug texture in case the application
356 // continues to use it.
357 sp<GraphicBuffer> buffer = new GraphicBuffer(
358 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
359 DEFAULT_USAGE_FLAGS | GraphicBuffer::USAGE_SW_WRITE_RARELY,
360 "[GLConsumer debug texture]");
361 uint32_t* bits;
362 buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
363 uint32_t stride = buffer->getStride();
364 uint32_t height = buffer->getHeight();
365 memset(bits, 0, stride * height * 4);
366 for (uint32_t y = 0; y < kDebugData.height; y++) {
367 for (uint32_t x = 0; x < kDebugData.width; x++) {
368 bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
369 0xFF000000 : 0xFFFFFFFF;
370 }
371 bits += stride;
372 }
373 buffer->unlock();
374 sReleasedTexImageBuffer = buffer;
375 }
376 return sReleasedTexImageBuffer;
377 }
378
acquireBufferLocked(BufferItem * item,nsecs_t presentWhen,uint64_t maxFrameNumber)379 status_t GLConsumer::acquireBufferLocked(BufferItem *item,
380 nsecs_t presentWhen, uint64_t maxFrameNumber) {
381 status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
382 maxFrameNumber);
383 if (err != NO_ERROR) {
384 return err;
385 }
386
387 // If item->mGraphicBuffer is not null, this buffer has not been acquired
388 // before, so any prior EglImage created is using a stale buffer. This
389 // replaces any old EglImage with a new one (using the new buffer).
390 if (item->mGraphicBuffer != nullptr) {
391 int slot = item->mSlot;
392 mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
393 }
394
395 return NO_ERROR;
396 }
397
releaseBufferLocked(int buf,sp<GraphicBuffer> graphicBuffer,EGLDisplay display,EGLSyncKHR eglFence)398 status_t GLConsumer::releaseBufferLocked(int buf,
399 sp<GraphicBuffer> graphicBuffer,
400 EGLDisplay display, EGLSyncKHR eglFence) {
401 // release the buffer if it hasn't already been discarded by the
402 // BufferQueue. This can happen, for example, when the producer of this
403 // buffer has reallocated the original buffer slot after this buffer
404 // was acquired.
405 status_t err = ConsumerBase::releaseBufferLocked(
406 buf, graphicBuffer, display, eglFence);
407 mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
408 return err;
409 }
410
updateAndReleaseLocked(const BufferItem & item,PendingRelease * pendingRelease)411 status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
412 PendingRelease* pendingRelease)
413 {
414 status_t err = NO_ERROR;
415
416 int slot = item.mSlot;
417
418 if (!mAttached) {
419 GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
420 "ES context");
421 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
422 return INVALID_OPERATION;
423 }
424
425 // Confirm state.
426 err = checkAndUpdateEglStateLocked();
427 if (err != NO_ERROR) {
428 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
429 return err;
430 }
431
432 // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
433 // if nessessary, for the gralloc buffer currently in the slot in
434 // ConsumerBase.
435 // We may have to do this even when item.mGraphicBuffer == NULL (which
436 // means the buffer was previously acquired).
437 err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay);
438 if (err != NO_ERROR) {
439 GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
440 mEglDisplay, slot);
441 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
442 return UNKNOWN_ERROR;
443 }
444
445 // Do whatever sync ops we need to do before releasing the old slot.
446 if (slot != mCurrentTexture) {
447 err = syncForReleaseLocked(mEglDisplay);
448 if (err != NO_ERROR) {
449 // Release the buffer we just acquired. It's not safe to
450 // release the old buffer, so instead we just drop the new frame.
451 // As we are still under lock since acquireBuffer, it is safe to
452 // release by slot.
453 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
454 return err;
455 }
456 }
457
458 GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
459 mCurrentTexture, mCurrentTextureImage != nullptr ?
460 mCurrentTextureImage->graphicBufferHandle() : nullptr,
461 slot, mSlots[slot].mGraphicBuffer->handle);
462
463 // Hang onto the pointer so that it isn't freed in the call to
464 // releaseBufferLocked() if we're in shared buffer mode and both buffers are
465 // the same.
466 sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
467
468 // release old buffer
469 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
470 if (pendingRelease == nullptr) {
471 status_t status = releaseBufferLocked(
472 mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
473 mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
474 if (status < NO_ERROR) {
475 GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
476 strerror(-status), status);
477 err = status;
478 // keep going, with error raised [?]
479 }
480 } else {
481 pendingRelease->currentTexture = mCurrentTexture;
482 pendingRelease->graphicBuffer =
483 mCurrentTextureImage->graphicBuffer();
484 pendingRelease->display = mEglDisplay;
485 pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
486 pendingRelease->isPending = true;
487 }
488 }
489
490 // Update the GLConsumer state.
491 mCurrentTexture = slot;
492 mCurrentTextureImage = nextTextureImage;
493 mCurrentCrop = item.mCrop;
494 mCurrentTransform = item.mTransform;
495 mCurrentScalingMode = item.mScalingMode;
496 mCurrentTimestamp = item.mTimestamp;
497 mCurrentDataSpace = item.mDataSpace;
498 mCurrentFence = item.mFence;
499 mCurrentFenceTime = item.mFenceTime;
500 mCurrentFrameNumber = item.mFrameNumber;
501
502 computeCurrentTransformMatrixLocked();
503
504 return err;
505 }
506
bindTextureImageLocked()507 status_t GLConsumer::bindTextureImageLocked() {
508 if (mEglDisplay == EGL_NO_DISPLAY) {
509 ALOGE("bindTextureImage: invalid display");
510 return INVALID_OPERATION;
511 }
512
513 GLenum error;
514 while ((error = glGetError()) != GL_NO_ERROR) {
515 GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
516 }
517
518 glBindTexture(mTexTarget, mTexName);
519 if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
520 mCurrentTextureImage == nullptr) {
521 GLC_LOGE("bindTextureImage: no currently-bound texture");
522 return NO_INIT;
523 }
524
525 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay);
526 if (err != NO_ERROR) {
527 GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
528 mEglDisplay, mCurrentTexture);
529 return UNKNOWN_ERROR;
530 }
531 mCurrentTextureImage->bindToTextureTarget(mTexTarget);
532
533 // In the rare case that the display is terminated and then initialized
534 // again, we can't detect that the display changed (it didn't), but the
535 // image is invalid. In this case, repeat the exact same steps while
536 // forcing the creation of a new image.
537 if ((error = glGetError()) != GL_NO_ERROR) {
538 glBindTexture(mTexTarget, mTexName);
539 status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, true);
540 if (result != NO_ERROR) {
541 GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
542 mEglDisplay, mCurrentTexture);
543 return UNKNOWN_ERROR;
544 }
545 mCurrentTextureImage->bindToTextureTarget(mTexTarget);
546 if ((error = glGetError()) != GL_NO_ERROR) {
547 GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
548 return UNKNOWN_ERROR;
549 }
550 }
551
552 // Wait for the new buffer to be ready.
553 return doGLFenceWaitLocked();
554 }
555
checkAndUpdateEglStateLocked(bool contextCheck)556 status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
557 EGLDisplay dpy = eglGetCurrentDisplay();
558 EGLContext ctx = eglGetCurrentContext();
559
560 if (!contextCheck) {
561 // if this is the first time we're called, mEglDisplay/mEglContext have
562 // never been set, so don't error out (below).
563 if (mEglDisplay == EGL_NO_DISPLAY) {
564 mEglDisplay = dpy;
565 }
566 if (mEglContext == EGL_NO_CONTEXT) {
567 mEglContext = ctx;
568 }
569 }
570
571 if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
572 GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
573 return INVALID_OPERATION;
574 }
575
576 if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
577 GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
578 return INVALID_OPERATION;
579 }
580
581 mEglDisplay = dpy;
582 mEglContext = ctx;
583 return NO_ERROR;
584 }
585
setReleaseFence(const sp<Fence> & fence)586 void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
587 if (fence->isValid() &&
588 mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
589 status_t err = addReleaseFence(mCurrentTexture,
590 mCurrentTextureImage->graphicBuffer(), fence);
591 if (err != OK) {
592 GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
593 strerror(-err), err);
594 }
595 }
596 }
597
detachFromContext()598 status_t GLConsumer::detachFromContext() {
599 ATRACE_CALL();
600 GLC_LOGV("detachFromContext");
601 Mutex::Autolock lock(mMutex);
602
603 if (mAbandoned) {
604 GLC_LOGE("detachFromContext: abandoned GLConsumer");
605 return NO_INIT;
606 }
607
608 if (!mAttached) {
609 GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
610 "context");
611 return INVALID_OPERATION;
612 }
613
614 EGLDisplay dpy = eglGetCurrentDisplay();
615 EGLContext ctx = eglGetCurrentContext();
616
617 if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
618 GLC_LOGE("detachFromContext: invalid current EGLDisplay");
619 return INVALID_OPERATION;
620 }
621
622 if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
623 GLC_LOGE("detachFromContext: invalid current EGLContext");
624 return INVALID_OPERATION;
625 }
626
627 if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
628 status_t err = syncForReleaseLocked(dpy);
629 if (err != OK) {
630 return err;
631 }
632
633 glDeleteTextures(1, &mTexName);
634 }
635
636 mEglDisplay = EGL_NO_DISPLAY;
637 mEglContext = EGL_NO_CONTEXT;
638 mAttached = false;
639
640 return OK;
641 }
642
attachToContext(uint32_t tex)643 status_t GLConsumer::attachToContext(uint32_t tex) {
644 ATRACE_CALL();
645 GLC_LOGV("attachToContext");
646 Mutex::Autolock lock(mMutex);
647
648 if (mAbandoned) {
649 GLC_LOGE("attachToContext: abandoned GLConsumer");
650 return NO_INIT;
651 }
652
653 if (mAttached) {
654 GLC_LOGE("attachToContext: GLConsumer is already attached to a "
655 "context");
656 return INVALID_OPERATION;
657 }
658
659 EGLDisplay dpy = eglGetCurrentDisplay();
660 EGLContext ctx = eglGetCurrentContext();
661
662 if (dpy == EGL_NO_DISPLAY) {
663 GLC_LOGE("attachToContext: invalid current EGLDisplay");
664 return INVALID_OPERATION;
665 }
666
667 if (ctx == EGL_NO_CONTEXT) {
668 GLC_LOGE("attachToContext: invalid current EGLContext");
669 return INVALID_OPERATION;
670 }
671
672 // We need to bind the texture regardless of whether there's a current
673 // buffer.
674 glBindTexture(mTexTarget, GLuint(tex));
675
676 mEglDisplay = dpy;
677 mEglContext = ctx;
678 mTexName = tex;
679 mAttached = true;
680
681 if (mCurrentTextureImage != nullptr) {
682 // This may wait for a buffer a second time. This is likely required if
683 // this is a different context, since otherwise the wait could be skipped
684 // by bouncing through another context. For the same context the extra
685 // wait is redundant.
686 status_t err = bindTextureImageLocked();
687 if (err != NO_ERROR) {
688 return err;
689 }
690 }
691
692 return OK;
693 }
694
695
syncForReleaseLocked(EGLDisplay dpy)696 status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
697 GLC_LOGV("syncForReleaseLocked");
698
699 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
700 if (SyncFeatures::getInstance().useNativeFenceSync()) {
701 EGLSyncKHR sync = eglCreateSyncKHR(dpy,
702 EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
703 if (sync == EGL_NO_SYNC_KHR) {
704 GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
705 eglGetError());
706 return UNKNOWN_ERROR;
707 }
708 glFlush();
709 int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
710 eglDestroySyncKHR(dpy, sync);
711 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
712 GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
713 "fd: %#x", eglGetError());
714 return UNKNOWN_ERROR;
715 }
716 sp<Fence> fence(new Fence(fenceFd));
717 status_t err = addReleaseFenceLocked(mCurrentTexture,
718 mCurrentTextureImage->graphicBuffer(), fence);
719 if (err != OK) {
720 GLC_LOGE("syncForReleaseLocked: error adding release fence: "
721 "%s (%d)", strerror(-err), err);
722 return err;
723 }
724 } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
725 EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
726 if (fence != EGL_NO_SYNC_KHR) {
727 // There is already a fence for the current slot. We need to
728 // wait on that before replacing it with another fence to
729 // ensure that all outstanding buffer accesses have completed
730 // before the producer accesses it.
731 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
732 if (result == EGL_FALSE) {
733 GLC_LOGE("syncForReleaseLocked: error waiting for previous "
734 "fence: %#x", eglGetError());
735 return UNKNOWN_ERROR;
736 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
737 GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
738 "fence");
739 return TIMED_OUT;
740 }
741 eglDestroySyncKHR(dpy, fence);
742 }
743
744 // Create a fence for the outstanding accesses in the current
745 // OpenGL ES context.
746 fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
747 if (fence == EGL_NO_SYNC_KHR) {
748 GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
749 eglGetError());
750 return UNKNOWN_ERROR;
751 }
752 glFlush();
753 mEglSlots[mCurrentTexture].mEglFence = fence;
754 }
755 }
756
757 return OK;
758 }
759
getCurrentTextureTarget() const760 uint32_t GLConsumer::getCurrentTextureTarget() const {
761 return mTexTarget;
762 }
763
getTransformMatrix(float mtx[16])764 void GLConsumer::getTransformMatrix(float mtx[16]) {
765 Mutex::Autolock lock(mMutex);
766 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
767 }
768
setFilteringEnabled(bool enabled)769 void GLConsumer::setFilteringEnabled(bool enabled) {
770 Mutex::Autolock lock(mMutex);
771 if (mAbandoned) {
772 GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
773 return;
774 }
775 bool needsRecompute = mFilteringEnabled != enabled;
776 mFilteringEnabled = enabled;
777
778 if (needsRecompute && mCurrentTextureImage==nullptr) {
779 GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
780 }
781
782 if (needsRecompute && mCurrentTextureImage != nullptr) {
783 computeCurrentTransformMatrixLocked();
784 }
785 }
786
computeCurrentTransformMatrixLocked()787 void GLConsumer::computeCurrentTransformMatrixLocked() {
788 GLC_LOGV("computeCurrentTransformMatrixLocked");
789 sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
790 nullptr : mCurrentTextureImage->graphicBuffer();
791 if (buf == nullptr) {
792 GLC_LOGD("computeCurrentTransformMatrixLocked: "
793 "mCurrentTextureImage is NULL");
794 }
795 computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop,
796 mCurrentTransform, mFilteringEnabled);
797 }
798
scaleDownCrop(const Rect & crop,uint32_t bufferWidth,uint32_t bufferHeight)799 Rect GLConsumer::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
800 Rect outCrop = crop;
801
802 uint32_t newWidth = static_cast<uint32_t>(crop.width());
803 uint32_t newHeight = static_cast<uint32_t>(crop.height());
804
805 if (newWidth * bufferHeight > newHeight * bufferWidth) {
806 newWidth = newHeight * bufferWidth / bufferHeight;
807 ALOGV("too wide: newWidth = %d", newWidth);
808 } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
809 newHeight = newWidth * bufferHeight / bufferWidth;
810 ALOGV("too tall: newHeight = %d", newHeight);
811 }
812
813 uint32_t currentWidth = static_cast<uint32_t>(crop.width());
814 uint32_t currentHeight = static_cast<uint32_t>(crop.height());
815
816 // The crop is too wide
817 if (newWidth < currentWidth) {
818 uint32_t dw = currentWidth - newWidth;
819 auto halfdw = dw / 2;
820 outCrop.left += halfdw;
821 // Not halfdw because it would subtract 1 too few when dw is odd
822 outCrop.right -= (dw - halfdw);
823 // The crop is too tall
824 } else if (newHeight < currentHeight) {
825 uint32_t dh = currentHeight - newHeight;
826 auto halfdh = dh / 2;
827 outCrop.top += halfdh;
828 // Not halfdh because it would subtract 1 too few when dh is odd
829 outCrop.bottom -= (dh - halfdh);
830 }
831
832 ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
833 outCrop.left, outCrop.top,
834 outCrop.right,outCrop.bottom);
835
836 return outCrop;
837 }
838
getTimestamp()839 nsecs_t GLConsumer::getTimestamp() {
840 GLC_LOGV("getTimestamp");
841 Mutex::Autolock lock(mMutex);
842 return mCurrentTimestamp;
843 }
844
getCurrentDataSpace()845 android_dataspace GLConsumer::getCurrentDataSpace() {
846 GLC_LOGV("getCurrentDataSpace");
847 Mutex::Autolock lock(mMutex);
848 return mCurrentDataSpace;
849 }
850
getFrameNumber()851 uint64_t GLConsumer::getFrameNumber() {
852 GLC_LOGV("getFrameNumber");
853 Mutex::Autolock lock(mMutex);
854 return mCurrentFrameNumber;
855 }
856
getCurrentBuffer(int * outSlot) const857 sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const {
858 Mutex::Autolock lock(mMutex);
859
860 if (outSlot != nullptr) {
861 *outSlot = mCurrentTexture;
862 }
863
864 return (mCurrentTextureImage == nullptr) ?
865 nullptr : mCurrentTextureImage->graphicBuffer();
866 }
867
getCurrentCrop() const868 Rect GLConsumer::getCurrentCrop() const {
869 Mutex::Autolock lock(mMutex);
870 return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
871 ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
872 : mCurrentCrop;
873 }
874
getCurrentTransform() const875 uint32_t GLConsumer::getCurrentTransform() const {
876 Mutex::Autolock lock(mMutex);
877 return mCurrentTransform;
878 }
879
getCurrentScalingMode() const880 uint32_t GLConsumer::getCurrentScalingMode() const {
881 Mutex::Autolock lock(mMutex);
882 return mCurrentScalingMode;
883 }
884
getCurrentFence() const885 sp<Fence> GLConsumer::getCurrentFence() const {
886 Mutex::Autolock lock(mMutex);
887 return mCurrentFence;
888 }
889
getCurrentFenceTime() const890 std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
891 Mutex::Autolock lock(mMutex);
892 return mCurrentFenceTime;
893 }
894
doGLFenceWaitLocked() const895 status_t GLConsumer::doGLFenceWaitLocked() const {
896
897 EGLDisplay dpy = eglGetCurrentDisplay();
898 EGLContext ctx = eglGetCurrentContext();
899
900 if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
901 GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
902 return INVALID_OPERATION;
903 }
904
905 if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
906 GLC_LOGE("doGLFenceWait: invalid current EGLContext");
907 return INVALID_OPERATION;
908 }
909
910 if (mCurrentFence->isValid()) {
911 if (SyncFeatures::getInstance().useWaitSync() &&
912 SyncFeatures::getInstance().useNativeFenceSync()) {
913 // Create an EGLSyncKHR from the current fence.
914 int fenceFd = mCurrentFence->dup();
915 if (fenceFd == -1) {
916 GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
917 return -errno;
918 }
919 EGLint attribs[] = {
920 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
921 EGL_NONE
922 };
923 EGLSyncKHR sync = eglCreateSyncKHR(dpy,
924 EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
925 if (sync == EGL_NO_SYNC_KHR) {
926 close(fenceFd);
927 GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
928 eglGetError());
929 return UNKNOWN_ERROR;
930 }
931
932 // XXX: The spec draft is inconsistent as to whether this should
933 // return an EGLint or void. Ignore the return value for now, as
934 // it's not strictly needed.
935 eglWaitSyncKHR(dpy, sync, 0);
936 EGLint eglErr = eglGetError();
937 eglDestroySyncKHR(dpy, sync);
938 if (eglErr != EGL_SUCCESS) {
939 GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
940 eglErr);
941 return UNKNOWN_ERROR;
942 }
943 } else {
944 status_t err = mCurrentFence->waitForever(
945 "GLConsumer::doGLFenceWaitLocked");
946 if (err != NO_ERROR) {
947 GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
948 return err;
949 }
950 }
951 }
952
953 return NO_ERROR;
954 }
955
freeBufferLocked(int slotIndex)956 void GLConsumer::freeBufferLocked(int slotIndex) {
957 GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
958 if (slotIndex == mCurrentTexture) {
959 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
960 }
961 mEglSlots[slotIndex].mEglImage.clear();
962 ConsumerBase::freeBufferLocked(slotIndex);
963 }
964
abandonLocked()965 void GLConsumer::abandonLocked() {
966 GLC_LOGV("abandonLocked");
967 mCurrentTextureImage.clear();
968 ConsumerBase::abandonLocked();
969 }
970
setConsumerUsageBits(uint64_t usage)971 status_t GLConsumer::setConsumerUsageBits(uint64_t usage) {
972 return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
973 }
974
dumpLocked(String8 & result,const char * prefix) const975 void GLConsumer::dumpLocked(String8& result, const char* prefix) const
976 {
977 result.appendFormat(
978 "%smTexName=%d mCurrentTexture=%d\n"
979 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
980 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
981 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
982 mCurrentTransform);
983
984 ConsumerBase::dumpLocked(result, prefix);
985 }
986
EglImage(sp<GraphicBuffer> graphicBuffer)987 GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
988 mGraphicBuffer(graphicBuffer),
989 mEglImage(EGL_NO_IMAGE_KHR),
990 mEglDisplay(EGL_NO_DISPLAY) {
991 }
992
~EglImage()993 GLConsumer::EglImage::~EglImage() {
994 if (mEglImage != EGL_NO_IMAGE_KHR) {
995 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
996 ALOGE("~EglImage: eglDestroyImageKHR failed");
997 }
998 DEBUG_EGL_IMAGE_TRACKER_DESTROY();
999 eglTerminate(mEglDisplay);
1000 }
1001 }
1002
createIfNeeded(EGLDisplay eglDisplay,bool forceCreation)1003 status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
1004 bool forceCreation) {
1005 // If there's an image and it's no longer valid, destroy it.
1006 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
1007 bool displayInvalid = mEglDisplay != eglDisplay;
1008 if (haveImage && (displayInvalid || forceCreation)) {
1009 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
1010 ALOGE("createIfNeeded: eglDestroyImageKHR failed");
1011 }
1012 DEBUG_EGL_IMAGE_TRACKER_DESTROY();
1013 eglTerminate(mEglDisplay);
1014 mEglImage = EGL_NO_IMAGE_KHR;
1015 mEglDisplay = EGL_NO_DISPLAY;
1016 }
1017
1018 // If there's no image, create one.
1019 if (mEglImage == EGL_NO_IMAGE_KHR) {
1020 mEglDisplay = eglDisplay;
1021 mEglImage = createImage(mEglDisplay, mGraphicBuffer);
1022 }
1023
1024 // Fail if we can't create a valid image.
1025 if (mEglImage == EGL_NO_IMAGE_KHR) {
1026 mEglDisplay = EGL_NO_DISPLAY;
1027 const sp<GraphicBuffer>& buffer = mGraphicBuffer;
1028 ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
1029 buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
1030 buffer->getUsage(), buffer->getPixelFormat());
1031 return UNKNOWN_ERROR;
1032 }
1033
1034 return OK;
1035 }
1036
bindToTextureTarget(uint32_t texTarget)1037 void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
1038 glEGLImageTargetTexture2DOES(texTarget,
1039 static_cast<GLeglImageOES>(mEglImage));
1040 }
1041
createImage(EGLDisplay dpy,const sp<GraphicBuffer> & graphicBuffer)1042 EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
1043 const sp<GraphicBuffer>& graphicBuffer) {
1044 EGLClientBuffer cbuf =
1045 static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
1046 const bool createProtectedImage =
1047 (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
1048 hasEglProtectedContent();
1049 EGLint attrs[] = {
1050 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
1051 createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
1052 createProtectedImage ? EGL_TRUE : EGL_NONE,
1053 EGL_NONE,
1054 };
1055 eglInitialize(dpy, nullptr, nullptr);
1056 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
1057 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
1058 if (image == EGL_NO_IMAGE_KHR) {
1059 EGLint error = eglGetError();
1060 ALOGE("error creating EGLImage: %#x", error);
1061 eglTerminate(dpy);
1062 } else {
1063 DEBUG_EGL_IMAGE_TRACKER_CREATE();
1064 }
1065
1066 return image;
1067 }
1068
1069 }; // namespace android
1070