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 <EGL/egl.h>
25 #include <EGL/eglext.h>
26 #include <GLES2/gl2.h>
27 #include <GLES2/gl2ext.h>
28 #include <cutils/compiler.h>
29
30 #include <hardware/hardware.h>
31
32 #include <gui/BufferItem.h>
33 #include <gui/GLConsumer.h>
34 #include <gui/ISurfaceComposer.h>
35 #include <gui/SurfaceComposerClient.h>
36
37 #include <private/gui/ComposerService.h>
38 #include <private/gui/SyncFeatures.h>
39
40 #include <utils/Log.h>
41 #include <utils/String8.h>
42 #include <utils/Trace.h>
43
44 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
45 #define CROP_EXT_STR "EGL_ANDROID_image_crop"
46 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
47 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
48
49 namespace android {
50
51 // Macros for including the GLConsumer name in log messages
52 #define GLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
53 #define GLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
54 //#define GLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
55 #define GLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
56 #define GLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
57
58 static const struct {
59 uint32_t width, height;
60 char const* bits;
61 } kDebugData = { 15, 12,
62 "_______________"
63 "_______________"
64 "_____XX_XX_____"
65 "__X_X_____X_X__"
66 "__X_XXXXXXX_X__"
67 "__XXXXXXXXXXX__"
68 "___XX_XXX_XX___"
69 "____XXXXXXX____"
70 "_____X___X_____"
71 "____X_____X____"
72 "_______________"
73 "_______________"
74 };
75
76 // Transform matrices
77 static float mtxIdentity[16] = {
78 1, 0, 0, 0,
79 0, 1, 0, 0,
80 0, 0, 1, 0,
81 0, 0, 0, 1,
82 };
83 static float mtxFlipH[16] = {
84 -1, 0, 0, 0,
85 0, 1, 0, 0,
86 0, 0, 1, 0,
87 1, 0, 0, 1,
88 };
89 static float mtxFlipV[16] = {
90 1, 0, 0, 0,
91 0, -1, 0, 0,
92 0, 0, 1, 0,
93 0, 1, 0, 1,
94 };
95 static float mtxRot90[16] = {
96 0, 1, 0, 0,
97 -1, 0, 0, 0,
98 0, 0, 1, 0,
99 1, 0, 0, 1,
100 };
101
102 static void mtxMul(float out[16], const float a[16], const float b[16]);
103
104 Mutex GLConsumer::sStaticInitLock;
105 sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
106
hasEglAndroidImageCropImpl()107 static bool hasEglAndroidImageCropImpl() {
108 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
109 const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
110 size_t cropExtLen = strlen(CROP_EXT_STR);
111 size_t extsLen = strlen(exts);
112 bool equal = !strcmp(CROP_EXT_STR, exts);
113 bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
114 bool atEnd = (cropExtLen+1) < extsLen &&
115 !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
116 bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
117 return equal || atStart || atEnd || inMiddle;
118 }
119
hasEglAndroidImageCrop()120 static bool hasEglAndroidImageCrop() {
121 // Only compute whether the extension is present once the first time this
122 // function is called.
123 static bool hasIt = hasEglAndroidImageCropImpl();
124 return hasIt;
125 }
126
hasEglProtectedContentImpl()127 static bool hasEglProtectedContentImpl() {
128 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
129 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
130 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
131 size_t extsLen = strlen(exts);
132 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
133 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
134 bool atEnd = (cropExtLen+1) < extsLen &&
135 !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
136 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
137 return equal || atStart || atEnd || inMiddle;
138 }
139
hasEglProtectedContent()140 static bool hasEglProtectedContent() {
141 // Only compute whether the extension is present once the first time this
142 // function is called.
143 static bool hasIt = hasEglProtectedContentImpl();
144 return hasIt;
145 }
146
isEglImageCroppable(const Rect & crop)147 static bool isEglImageCroppable(const Rect& crop) {
148 return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
149 }
150
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)151 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
152 uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
153 ConsumerBase(bq, isControlledByApp),
154 mCurrentCrop(Rect::EMPTY_RECT),
155 mCurrentTransform(0),
156 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
157 mCurrentFence(Fence::NO_FENCE),
158 mCurrentTimestamp(0),
159 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
160 mCurrentFrameNumber(0),
161 mDefaultWidth(1),
162 mDefaultHeight(1),
163 mFilteringEnabled(true),
164 mTexName(tex),
165 mUseFenceSync(useFenceSync),
166 mTexTarget(texTarget),
167 mEglDisplay(EGL_NO_DISPLAY),
168 mEglContext(EGL_NO_CONTEXT),
169 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
170 mAttached(true)
171 {
172 GLC_LOGV("GLConsumer");
173
174 memcpy(mCurrentTransformMatrix, mtxIdentity,
175 sizeof(mCurrentTransformMatrix));
176
177 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
178 }
179
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)180 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
181 bool useFenceSync, bool isControlledByApp) :
182 ConsumerBase(bq, isControlledByApp),
183 mCurrentCrop(Rect::EMPTY_RECT),
184 mCurrentTransform(0),
185 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
186 mCurrentFence(Fence::NO_FENCE),
187 mCurrentTimestamp(0),
188 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
189 mCurrentFrameNumber(0),
190 mDefaultWidth(1),
191 mDefaultHeight(1),
192 mFilteringEnabled(true),
193 mTexName(0),
194 mUseFenceSync(useFenceSync),
195 mTexTarget(texTarget),
196 mEglDisplay(EGL_NO_DISPLAY),
197 mEglContext(EGL_NO_CONTEXT),
198 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
199 mAttached(false)
200 {
201 GLC_LOGV("GLConsumer");
202
203 memcpy(mCurrentTransformMatrix, mtxIdentity,
204 sizeof(mCurrentTransformMatrix));
205
206 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
207 }
208
setDefaultBufferSize(uint32_t w,uint32_t h)209 status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
210 {
211 Mutex::Autolock lock(mMutex);
212 if (mAbandoned) {
213 GLC_LOGE("setDefaultBufferSize: GLConsumer is abandoned!");
214 return NO_INIT;
215 }
216 mDefaultWidth = w;
217 mDefaultHeight = h;
218 return mConsumer->setDefaultBufferSize(w, h);
219 }
220
updateTexImage()221 status_t GLConsumer::updateTexImage() {
222 ATRACE_CALL();
223 GLC_LOGV("updateTexImage");
224 Mutex::Autolock lock(mMutex);
225
226 if (mAbandoned) {
227 GLC_LOGE("updateTexImage: GLConsumer is abandoned!");
228 return NO_INIT;
229 }
230
231 // Make sure the EGL state is the same as in previous calls.
232 status_t err = checkAndUpdateEglStateLocked();
233 if (err != NO_ERROR) {
234 return err;
235 }
236
237 BufferItem item;
238
239 // Acquire the next buffer.
240 // In asynchronous mode the list is guaranteed to be one buffer
241 // deep, while in synchronous mode we use the oldest buffer.
242 err = acquireBufferLocked(&item, 0);
243 if (err != NO_ERROR) {
244 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
245 // We always bind the texture even if we don't update its contents.
246 GLC_LOGV("updateTexImage: no buffers were available");
247 glBindTexture(mTexTarget, mTexName);
248 err = NO_ERROR;
249 } else {
250 GLC_LOGE("updateTexImage: acquire failed: %s (%d)",
251 strerror(-err), err);
252 }
253 return err;
254 }
255
256 // Release the previous buffer.
257 err = updateAndReleaseLocked(item);
258 if (err != NO_ERROR) {
259 // We always bind the texture.
260 glBindTexture(mTexTarget, mTexName);
261 return err;
262 }
263
264 // Bind the new buffer to the GL texture, and wait until it's ready.
265 return bindTextureImageLocked();
266 }
267
268
releaseTexImage()269 status_t GLConsumer::releaseTexImage() {
270 ATRACE_CALL();
271 GLC_LOGV("releaseTexImage");
272 Mutex::Autolock lock(mMutex);
273
274 if (mAbandoned) {
275 GLC_LOGE("releaseTexImage: GLConsumer is abandoned!");
276 return NO_INIT;
277 }
278
279 // Make sure the EGL state is the same as in previous calls.
280 status_t err = NO_ERROR;
281
282 if (mAttached) {
283 err = checkAndUpdateEglStateLocked(true);
284 if (err != NO_ERROR) {
285 return err;
286 }
287 } else {
288 // if we're detached, no need to validate EGL's state -- we won't use it.
289 }
290
291 // Update the GLConsumer state.
292 int buf = mCurrentTexture;
293 if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
294
295 GLC_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
296
297 if (mAttached) {
298 // Do whatever sync ops we need to do before releasing the slot.
299 err = syncForReleaseLocked(mEglDisplay);
300 if (err != NO_ERROR) {
301 GLC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
302 return err;
303 }
304 } else {
305 // if we're detached, we just use the fence that was created in detachFromContext()
306 // so... basically, nothing more to do here.
307 }
308
309 err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
310 if (err < NO_ERROR) {
311 GLC_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
312 strerror(-err), err);
313 return err;
314 }
315
316 if (mReleasedTexImage == NULL) {
317 mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
318 }
319
320 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
321 mCurrentTextureImage = mReleasedTexImage;
322 mCurrentCrop.makeInvalid();
323 mCurrentTransform = 0;
324 mCurrentTimestamp = 0;
325 mCurrentDataSpace = HAL_DATASPACE_UNKNOWN;
326 mCurrentFence = Fence::NO_FENCE;
327 mCurrentFenceTime = FenceTime::NO_FENCE;
328
329 if (mAttached) {
330 // This binds a dummy buffer (mReleasedTexImage).
331 status_t result = bindTextureImageLocked();
332 if (result != NO_ERROR) {
333 return result;
334 }
335 } else {
336 // detached, don't touch the texture (and we may not even have an
337 // EGLDisplay here.
338 }
339 }
340
341 return NO_ERROR;
342 }
343
getDebugTexImageBuffer()344 sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
345 Mutex::Autolock _l(sStaticInitLock);
346 if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
347 // The first time, create the debug texture in case the application
348 // continues to use it.
349 sp<GraphicBuffer> buffer = new GraphicBuffer(
350 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
351 GraphicBuffer::USAGE_SW_WRITE_RARELY,
352 "[GLConsumer debug texture]");
353 uint32_t* bits;
354 buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
355 uint32_t stride = buffer->getStride();
356 uint32_t height = buffer->getHeight();
357 memset(bits, 0, stride * height * 4);
358 for (uint32_t y = 0; y < kDebugData.height; y++) {
359 for (uint32_t x = 0; x < kDebugData.width; x++) {
360 bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ?
361 0xFF000000 : 0xFFFFFFFF;
362 }
363 bits += stride;
364 }
365 buffer->unlock();
366 sReleasedTexImageBuffer = buffer;
367 }
368 return sReleasedTexImageBuffer;
369 }
370
acquireBufferLocked(BufferItem * item,nsecs_t presentWhen,uint64_t maxFrameNumber)371 status_t GLConsumer::acquireBufferLocked(BufferItem *item,
372 nsecs_t presentWhen, uint64_t maxFrameNumber) {
373 status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
374 maxFrameNumber);
375 if (err != NO_ERROR) {
376 return err;
377 }
378
379 // If item->mGraphicBuffer is not null, this buffer has not been acquired
380 // before, so any prior EglImage created is using a stale buffer. This
381 // replaces any old EglImage with a new one (using the new buffer).
382 if (item->mGraphicBuffer != NULL) {
383 int slot = item->mSlot;
384 mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
385 }
386
387 return NO_ERROR;
388 }
389
releaseBufferLocked(int buf,sp<GraphicBuffer> graphicBuffer,EGLDisplay display,EGLSyncKHR eglFence)390 status_t GLConsumer::releaseBufferLocked(int buf,
391 sp<GraphicBuffer> graphicBuffer,
392 EGLDisplay display, EGLSyncKHR eglFence) {
393 // release the buffer if it hasn't already been discarded by the
394 // BufferQueue. This can happen, for example, when the producer of this
395 // buffer has reallocated the original buffer slot after this buffer
396 // was acquired.
397 status_t err = ConsumerBase::releaseBufferLocked(
398 buf, graphicBuffer, display, eglFence);
399 mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
400 return err;
401 }
402
updateAndReleaseLocked(const BufferItem & item,PendingRelease * pendingRelease)403 status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
404 PendingRelease* pendingRelease)
405 {
406 status_t err = NO_ERROR;
407
408 int slot = item.mSlot;
409
410 if (!mAttached) {
411 GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
412 "ES context");
413 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
414 mEglDisplay, EGL_NO_SYNC_KHR);
415 return INVALID_OPERATION;
416 }
417
418 // Confirm state.
419 err = checkAndUpdateEglStateLocked();
420 if (err != NO_ERROR) {
421 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
422 mEglDisplay, EGL_NO_SYNC_KHR);
423 return err;
424 }
425
426 // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
427 // if nessessary, for the gralloc buffer currently in the slot in
428 // ConsumerBase.
429 // We may have to do this even when item.mGraphicBuffer == NULL (which
430 // means the buffer was previously acquired).
431 err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
432 if (err != NO_ERROR) {
433 GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
434 mEglDisplay, slot);
435 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
436 mEglDisplay, EGL_NO_SYNC_KHR);
437 return UNKNOWN_ERROR;
438 }
439
440 // Do whatever sync ops we need to do before releasing the old slot.
441 if (slot != mCurrentTexture) {
442 err = syncForReleaseLocked(mEglDisplay);
443 if (err != NO_ERROR) {
444 // Release the buffer we just acquired. It's not safe to
445 // release the old buffer, so instead we just drop the new frame.
446 // As we are still under lock since acquireBuffer, it is safe to
447 // release by slot.
448 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
449 mEglDisplay, EGL_NO_SYNC_KHR);
450 return err;
451 }
452 }
453
454 GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
455 mCurrentTexture, mCurrentTextureImage != NULL ?
456 mCurrentTextureImage->graphicBufferHandle() : 0,
457 slot, mSlots[slot].mGraphicBuffer->handle);
458
459 // Hang onto the pointer so that it isn't freed in the call to
460 // releaseBufferLocked() if we're in shared buffer mode and both buffers are
461 // the same.
462 sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
463
464 // release old buffer
465 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
466 if (pendingRelease == nullptr) {
467 status_t status = releaseBufferLocked(
468 mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
469 mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
470 if (status < NO_ERROR) {
471 GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
472 strerror(-status), status);
473 err = status;
474 // keep going, with error raised [?]
475 }
476 } else {
477 pendingRelease->currentTexture = mCurrentTexture;
478 pendingRelease->graphicBuffer =
479 mCurrentTextureImage->graphicBuffer();
480 pendingRelease->display = mEglDisplay;
481 pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
482 pendingRelease->isPending = true;
483 }
484 }
485
486 // Update the GLConsumer state.
487 mCurrentTexture = slot;
488 mCurrentTextureImage = nextTextureImage;
489 mCurrentCrop = item.mCrop;
490 mCurrentTransform = item.mTransform;
491 mCurrentScalingMode = item.mScalingMode;
492 mCurrentTimestamp = item.mTimestamp;
493 mCurrentDataSpace = item.mDataSpace;
494 mCurrentFence = item.mFence;
495 mCurrentFenceTime = item.mFenceTime;
496 mCurrentFrameNumber = item.mFrameNumber;
497
498 computeCurrentTransformMatrixLocked();
499
500 return err;
501 }
502
bindTextureImageLocked()503 status_t GLConsumer::bindTextureImageLocked() {
504 if (mEglDisplay == EGL_NO_DISPLAY) {
505 ALOGE("bindTextureImage: invalid display");
506 return INVALID_OPERATION;
507 }
508
509 GLenum error;
510 while ((error = glGetError()) != GL_NO_ERROR) {
511 GLC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
512 }
513
514 glBindTexture(mTexTarget, mTexName);
515 if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
516 mCurrentTextureImage == NULL) {
517 GLC_LOGE("bindTextureImage: no currently-bound texture");
518 return NO_INIT;
519 }
520
521 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
522 mCurrentCrop);
523 if (err != NO_ERROR) {
524 GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
525 mEglDisplay, mCurrentTexture);
526 return UNKNOWN_ERROR;
527 }
528 mCurrentTextureImage->bindToTextureTarget(mTexTarget);
529
530 // In the rare case that the display is terminated and then initialized
531 // again, we can't detect that the display changed (it didn't), but the
532 // image is invalid. In this case, repeat the exact same steps while
533 // forcing the creation of a new image.
534 if ((error = glGetError()) != GL_NO_ERROR) {
535 glBindTexture(mTexTarget, mTexName);
536 status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay,
537 mCurrentCrop,
538 true);
539 if (result != NO_ERROR) {
540 GLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
541 mEglDisplay, mCurrentTexture);
542 return UNKNOWN_ERROR;
543 }
544 mCurrentTextureImage->bindToTextureTarget(mTexTarget);
545 if ((error = glGetError()) != GL_NO_ERROR) {
546 GLC_LOGE("bindTextureImage: error binding external image: %#04x", error);
547 return UNKNOWN_ERROR;
548 }
549 }
550
551 // Wait for the new buffer to be ready.
552 return doGLFenceWaitLocked();
553 }
554
checkAndUpdateEglStateLocked(bool contextCheck)555 status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
556 EGLDisplay dpy = eglGetCurrentDisplay();
557 EGLContext ctx = eglGetCurrentContext();
558
559 if (!contextCheck) {
560 // if this is the first time we're called, mEglDisplay/mEglContext have
561 // never been set, so don't error out (below).
562 if (mEglDisplay == EGL_NO_DISPLAY) {
563 mEglDisplay = dpy;
564 }
565 if (mEglContext == EGL_NO_CONTEXT) {
566 mEglContext = ctx;
567 }
568 }
569
570 if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
571 GLC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
572 return INVALID_OPERATION;
573 }
574
575 if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
576 GLC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
577 return INVALID_OPERATION;
578 }
579
580 mEglDisplay = dpy;
581 mEglContext = ctx;
582 return NO_ERROR;
583 }
584
setReleaseFence(const sp<Fence> & fence)585 void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
586 if (fence->isValid() &&
587 mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
588 status_t err = addReleaseFence(mCurrentTexture,
589 mCurrentTextureImage->graphicBuffer(), fence);
590 if (err != OK) {
591 GLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
592 strerror(-err), err);
593 }
594 }
595 }
596
detachFromContext()597 status_t GLConsumer::detachFromContext() {
598 ATRACE_CALL();
599 GLC_LOGV("detachFromContext");
600 Mutex::Autolock lock(mMutex);
601
602 if (mAbandoned) {
603 GLC_LOGE("detachFromContext: abandoned GLConsumer");
604 return NO_INIT;
605 }
606
607 if (!mAttached) {
608 GLC_LOGE("detachFromContext: GLConsumer is not attached to a "
609 "context");
610 return INVALID_OPERATION;
611 }
612
613 EGLDisplay dpy = eglGetCurrentDisplay();
614 EGLContext ctx = eglGetCurrentContext();
615
616 if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
617 GLC_LOGE("detachFromContext: invalid current EGLDisplay");
618 return INVALID_OPERATION;
619 }
620
621 if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
622 GLC_LOGE("detachFromContext: invalid current EGLContext");
623 return INVALID_OPERATION;
624 }
625
626 if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
627 status_t err = syncForReleaseLocked(dpy);
628 if (err != OK) {
629 return err;
630 }
631
632 glDeleteTextures(1, &mTexName);
633 }
634
635 mEglDisplay = EGL_NO_DISPLAY;
636 mEglContext = EGL_NO_CONTEXT;
637 mAttached = false;
638
639 return OK;
640 }
641
attachToContext(uint32_t tex)642 status_t GLConsumer::attachToContext(uint32_t tex) {
643 ATRACE_CALL();
644 GLC_LOGV("attachToContext");
645 Mutex::Autolock lock(mMutex);
646
647 if (mAbandoned) {
648 GLC_LOGE("attachToContext: abandoned GLConsumer");
649 return NO_INIT;
650 }
651
652 if (mAttached) {
653 GLC_LOGE("attachToContext: GLConsumer is already attached to a "
654 "context");
655 return INVALID_OPERATION;
656 }
657
658 EGLDisplay dpy = eglGetCurrentDisplay();
659 EGLContext ctx = eglGetCurrentContext();
660
661 if (dpy == EGL_NO_DISPLAY) {
662 GLC_LOGE("attachToContext: invalid current EGLDisplay");
663 return INVALID_OPERATION;
664 }
665
666 if (ctx == EGL_NO_CONTEXT) {
667 GLC_LOGE("attachToContext: invalid current EGLContext");
668 return INVALID_OPERATION;
669 }
670
671 // We need to bind the texture regardless of whether there's a current
672 // buffer.
673 glBindTexture(mTexTarget, GLuint(tex));
674
675 mEglDisplay = dpy;
676 mEglContext = ctx;
677 mTexName = tex;
678 mAttached = true;
679
680 if (mCurrentTextureImage != NULL) {
681 // This may wait for a buffer a second time. This is likely required if
682 // this is a different context, since otherwise the wait could be skipped
683 // by bouncing through another context. For the same context the extra
684 // wait is redundant.
685 status_t err = bindTextureImageLocked();
686 if (err != NO_ERROR) {
687 return err;
688 }
689 }
690
691 return OK;
692 }
693
694
syncForReleaseLocked(EGLDisplay dpy)695 status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
696 GLC_LOGV("syncForReleaseLocked");
697
698 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
699 if (SyncFeatures::getInstance().useNativeFenceSync()) {
700 EGLSyncKHR sync = eglCreateSyncKHR(dpy,
701 EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
702 if (sync == EGL_NO_SYNC_KHR) {
703 GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
704 eglGetError());
705 return UNKNOWN_ERROR;
706 }
707 glFlush();
708 int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
709 eglDestroySyncKHR(dpy, sync);
710 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
711 GLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
712 "fd: %#x", eglGetError());
713 return UNKNOWN_ERROR;
714 }
715 sp<Fence> fence(new Fence(fenceFd));
716 status_t err = addReleaseFenceLocked(mCurrentTexture,
717 mCurrentTextureImage->graphicBuffer(), fence);
718 if (err != OK) {
719 GLC_LOGE("syncForReleaseLocked: error adding release fence: "
720 "%s (%d)", strerror(-err), err);
721 return err;
722 }
723 } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
724 EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
725 if (fence != EGL_NO_SYNC_KHR) {
726 // There is already a fence for the current slot. We need to
727 // wait on that before replacing it with another fence to
728 // ensure that all outstanding buffer accesses have completed
729 // before the producer accesses it.
730 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
731 if (result == EGL_FALSE) {
732 GLC_LOGE("syncForReleaseLocked: error waiting for previous "
733 "fence: %#x", eglGetError());
734 return UNKNOWN_ERROR;
735 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
736 GLC_LOGE("syncForReleaseLocked: timeout waiting for previous "
737 "fence");
738 return TIMED_OUT;
739 }
740 eglDestroySyncKHR(dpy, fence);
741 }
742
743 // Create a fence for the outstanding accesses in the current
744 // OpenGL ES context.
745 fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
746 if (fence == EGL_NO_SYNC_KHR) {
747 GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
748 eglGetError());
749 return UNKNOWN_ERROR;
750 }
751 glFlush();
752 mEglSlots[mCurrentTexture].mEglFence = fence;
753 }
754 }
755
756 return OK;
757 }
758
isExternalFormat(PixelFormat format)759 bool GLConsumer::isExternalFormat(PixelFormat format)
760 {
761 switch (format) {
762 // supported YUV formats
763 case HAL_PIXEL_FORMAT_YV12:
764 // Legacy/deprecated YUV formats
765 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
766 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
767 case HAL_PIXEL_FORMAT_YCbCr_422_I:
768 return true;
769 }
770
771 // Any OEM format needs to be considered
772 if (format>=0x100 && format<=0x1FF)
773 return true;
774
775 return false;
776 }
777
getCurrentTextureTarget() const778 uint32_t GLConsumer::getCurrentTextureTarget() const {
779 return mTexTarget;
780 }
781
getTransformMatrix(float mtx[16])782 void GLConsumer::getTransformMatrix(float mtx[16]) {
783 Mutex::Autolock lock(mMutex);
784 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
785 }
786
setFilteringEnabled(bool enabled)787 void GLConsumer::setFilteringEnabled(bool enabled) {
788 Mutex::Autolock lock(mMutex);
789 if (mAbandoned) {
790 GLC_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
791 return;
792 }
793 bool needsRecompute = mFilteringEnabled != enabled;
794 mFilteringEnabled = enabled;
795
796 if (needsRecompute && mCurrentTextureImage==NULL) {
797 GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
798 }
799
800 if (needsRecompute && mCurrentTextureImage != NULL) {
801 computeCurrentTransformMatrixLocked();
802 }
803 }
804
computeCurrentTransformMatrixLocked()805 void GLConsumer::computeCurrentTransformMatrixLocked() {
806 GLC_LOGV("computeCurrentTransformMatrixLocked");
807 sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
808 nullptr : mCurrentTextureImage->graphicBuffer();
809 if (buf == nullptr) {
810 GLC_LOGD("computeCurrentTransformMatrixLocked: "
811 "mCurrentTextureImage is NULL");
812 }
813 computeTransformMatrix(mCurrentTransformMatrix, buf,
814 isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop,
815 mCurrentTransform, mFilteringEnabled);
816 }
817
computeTransformMatrix(float outTransform[16],const sp<GraphicBuffer> & buf,const Rect & cropRect,uint32_t transform,bool filtering)818 void GLConsumer::computeTransformMatrix(float outTransform[16],
819 const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
820 bool filtering) {
821
822 float xform[16];
823 for (int i = 0; i < 16; i++) {
824 xform[i] = mtxIdentity[i];
825 }
826 if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
827 float result[16];
828 mtxMul(result, xform, mtxFlipH);
829 for (int i = 0; i < 16; i++) {
830 xform[i] = result[i];
831 }
832 }
833 if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
834 float result[16];
835 mtxMul(result, xform, mtxFlipV);
836 for (int i = 0; i < 16; i++) {
837 xform[i] = result[i];
838 }
839 }
840 if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
841 float result[16];
842 mtxMul(result, xform, mtxRot90);
843 for (int i = 0; i < 16; i++) {
844 xform[i] = result[i];
845 }
846 }
847
848 float mtxBeforeFlipV[16];
849 if (!cropRect.isEmpty()) {
850 float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
851 float bufferWidth = buf->getWidth();
852 float bufferHeight = buf->getHeight();
853 float shrinkAmount = 0.0f;
854 if (filtering) {
855 // In order to prevent bilinear sampling beyond the edge of the
856 // crop rectangle we may need to shrink it by 2 texels in each
857 // dimension. Normally this would just need to take 1/2 a texel
858 // off each end, but because the chroma channels of YUV420 images
859 // are subsampled we may need to shrink the crop region by a whole
860 // texel on each side.
861 switch (buf->getPixelFormat()) {
862 case PIXEL_FORMAT_RGBA_8888:
863 case PIXEL_FORMAT_RGBX_8888:
864 case PIXEL_FORMAT_RGBA_FP16:
865 case PIXEL_FORMAT_RGBA_1010102:
866 case PIXEL_FORMAT_RGB_888:
867 case PIXEL_FORMAT_RGB_565:
868 case PIXEL_FORMAT_BGRA_8888:
869 // We know there's no subsampling of any channels, so we
870 // only need to shrink by a half a pixel.
871 shrinkAmount = 0.5;
872 break;
873
874 default:
875 // If we don't recognize the format, we must assume the
876 // worst case (that we care about), which is YUV420.
877 shrinkAmount = 1.0;
878 break;
879 }
880 }
881
882 // Only shrink the dimensions that are not the size of the buffer.
883 if (cropRect.width() < bufferWidth) {
884 tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
885 sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
886 bufferWidth;
887 }
888 if (cropRect.height() < bufferHeight) {
889 ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
890 bufferHeight;
891 sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
892 bufferHeight;
893 }
894 float crop[16] = {
895 sx, 0, 0, 0,
896 0, sy, 0, 0,
897 0, 0, 1, 0,
898 tx, ty, 0, 1,
899 };
900
901 mtxMul(mtxBeforeFlipV, crop, xform);
902 } else {
903 for (int i = 0; i < 16; i++) {
904 mtxBeforeFlipV[i] = xform[i];
905 }
906 }
907
908 // SurfaceFlinger expects the top of its window textures to be at a Y
909 // coordinate of 0, so GLConsumer must behave the same way. We don't
910 // want to expose this to applications, however, so we must add an
911 // additional vertical flip to the transform after all the other transforms.
912 mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
913 }
914
getTimestamp()915 nsecs_t GLConsumer::getTimestamp() {
916 GLC_LOGV("getTimestamp");
917 Mutex::Autolock lock(mMutex);
918 return mCurrentTimestamp;
919 }
920
getCurrentDataSpace()921 android_dataspace GLConsumer::getCurrentDataSpace() {
922 GLC_LOGV("getCurrentDataSpace");
923 Mutex::Autolock lock(mMutex);
924 return mCurrentDataSpace;
925 }
926
getFrameNumber()927 uint64_t GLConsumer::getFrameNumber() {
928 GLC_LOGV("getFrameNumber");
929 Mutex::Autolock lock(mMutex);
930 return mCurrentFrameNumber;
931 }
932
getCurrentBuffer(int * outSlot) const933 sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const {
934 Mutex::Autolock lock(mMutex);
935
936 if (outSlot != nullptr) {
937 *outSlot = mCurrentTexture;
938 }
939
940 return (mCurrentTextureImage == nullptr) ?
941 NULL : mCurrentTextureImage->graphicBuffer();
942 }
943
getCurrentCrop() const944 Rect GLConsumer::getCurrentCrop() const {
945 Mutex::Autolock lock(mMutex);
946
947 Rect outCrop = mCurrentCrop;
948 if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
949 uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
950 uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
951
952 if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
953 newWidth = newHeight * mDefaultWidth / mDefaultHeight;
954 GLC_LOGV("too wide: newWidth = %d", newWidth);
955 } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
956 newHeight = newWidth * mDefaultHeight / mDefaultWidth;
957 GLC_LOGV("too tall: newHeight = %d", newHeight);
958 }
959
960 uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
961 uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
962
963 // The crop is too wide
964 if (newWidth < currentWidth) {
965 uint32_t dw = currentWidth - newWidth;
966 auto halfdw = dw / 2;
967 outCrop.left += halfdw;
968 // Not halfdw because it would subtract 1 too few when dw is odd
969 outCrop.right -= (dw - halfdw);
970 // The crop is too tall
971 } else if (newHeight < currentHeight) {
972 uint32_t dh = currentHeight - newHeight;
973 auto halfdh = dh / 2;
974 outCrop.top += halfdh;
975 // Not halfdh because it would subtract 1 too few when dh is odd
976 outCrop.bottom -= (dh - halfdh);
977 }
978
979 GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
980 outCrop.left, outCrop.top,
981 outCrop.right,outCrop.bottom);
982 }
983
984 return outCrop;
985 }
986
getCurrentTransform() const987 uint32_t GLConsumer::getCurrentTransform() const {
988 Mutex::Autolock lock(mMutex);
989 return mCurrentTransform;
990 }
991
getCurrentScalingMode() const992 uint32_t GLConsumer::getCurrentScalingMode() const {
993 Mutex::Autolock lock(mMutex);
994 return mCurrentScalingMode;
995 }
996
getCurrentFence() const997 sp<Fence> GLConsumer::getCurrentFence() const {
998 Mutex::Autolock lock(mMutex);
999 return mCurrentFence;
1000 }
1001
getCurrentFenceTime() const1002 std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
1003 Mutex::Autolock lock(mMutex);
1004 return mCurrentFenceTime;
1005 }
1006
doGLFenceWait() const1007 status_t GLConsumer::doGLFenceWait() const {
1008 Mutex::Autolock lock(mMutex);
1009 return doGLFenceWaitLocked();
1010 }
1011
doGLFenceWaitLocked() const1012 status_t GLConsumer::doGLFenceWaitLocked() const {
1013
1014 EGLDisplay dpy = eglGetCurrentDisplay();
1015 EGLContext ctx = eglGetCurrentContext();
1016
1017 if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
1018 GLC_LOGE("doGLFenceWait: invalid current EGLDisplay");
1019 return INVALID_OPERATION;
1020 }
1021
1022 if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
1023 GLC_LOGE("doGLFenceWait: invalid current EGLContext");
1024 return INVALID_OPERATION;
1025 }
1026
1027 if (mCurrentFence->isValid()) {
1028 if (SyncFeatures::getInstance().useWaitSync()) {
1029 // Create an EGLSyncKHR from the current fence.
1030 int fenceFd = mCurrentFence->dup();
1031 if (fenceFd == -1) {
1032 GLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
1033 return -errno;
1034 }
1035 EGLint attribs[] = {
1036 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
1037 EGL_NONE
1038 };
1039 EGLSyncKHR sync = eglCreateSyncKHR(dpy,
1040 EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
1041 if (sync == EGL_NO_SYNC_KHR) {
1042 close(fenceFd);
1043 GLC_LOGE("doGLFenceWait: error creating EGL fence: %#x",
1044 eglGetError());
1045 return UNKNOWN_ERROR;
1046 }
1047
1048 // XXX: The spec draft is inconsistent as to whether this should
1049 // return an EGLint or void. Ignore the return value for now, as
1050 // it's not strictly needed.
1051 eglWaitSyncKHR(dpy, sync, 0);
1052 EGLint eglErr = eglGetError();
1053 eglDestroySyncKHR(dpy, sync);
1054 if (eglErr != EGL_SUCCESS) {
1055 GLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
1056 eglErr);
1057 return UNKNOWN_ERROR;
1058 }
1059 } else {
1060 status_t err = mCurrentFence->waitForever(
1061 "GLConsumer::doGLFenceWaitLocked");
1062 if (err != NO_ERROR) {
1063 GLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
1064 return err;
1065 }
1066 }
1067 }
1068
1069 return NO_ERROR;
1070 }
1071
freeBufferLocked(int slotIndex)1072 void GLConsumer::freeBufferLocked(int slotIndex) {
1073 GLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
1074 if (slotIndex == mCurrentTexture) {
1075 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
1076 }
1077 mEglSlots[slotIndex].mEglImage.clear();
1078 ConsumerBase::freeBufferLocked(slotIndex);
1079 }
1080
abandonLocked()1081 void GLConsumer::abandonLocked() {
1082 GLC_LOGV("abandonLocked");
1083 mCurrentTextureImage.clear();
1084 ConsumerBase::abandonLocked();
1085 }
1086
setName(const String8 & name)1087 void GLConsumer::setName(const String8& name) {
1088 Mutex::Autolock _l(mMutex);
1089 if (mAbandoned) {
1090 GLC_LOGE("setName: GLConsumer is abandoned!");
1091 return;
1092 }
1093 mName = name;
1094 mConsumer->setConsumerName(name);
1095 }
1096
setDefaultBufferFormat(PixelFormat defaultFormat)1097 status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
1098 Mutex::Autolock lock(mMutex);
1099 if (mAbandoned) {
1100 GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!");
1101 return NO_INIT;
1102 }
1103 return mConsumer->setDefaultBufferFormat(defaultFormat);
1104 }
1105
setDefaultBufferDataSpace(android_dataspace defaultDataSpace)1106 status_t GLConsumer::setDefaultBufferDataSpace(
1107 android_dataspace defaultDataSpace) {
1108 Mutex::Autolock lock(mMutex);
1109 if (mAbandoned) {
1110 GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!");
1111 return NO_INIT;
1112 }
1113 return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
1114 }
1115
setConsumerUsageBits(uint32_t usage)1116 status_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
1117 Mutex::Autolock lock(mMutex);
1118 if (mAbandoned) {
1119 GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
1120 return NO_INIT;
1121 }
1122 usage |= DEFAULT_USAGE_FLAGS;
1123 return mConsumer->setConsumerUsageBits(usage);
1124 }
1125
setTransformHint(uint32_t hint)1126 status_t GLConsumer::setTransformHint(uint32_t hint) {
1127 Mutex::Autolock lock(mMutex);
1128 if (mAbandoned) {
1129 GLC_LOGE("setTransformHint: GLConsumer is abandoned!");
1130 return NO_INIT;
1131 }
1132 return mConsumer->setTransformHint(hint);
1133 }
1134
setMaxAcquiredBufferCount(int maxAcquiredBuffers)1135 status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
1136 Mutex::Autolock lock(mMutex);
1137 if (mAbandoned) {
1138 GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!");
1139 return NO_INIT;
1140 }
1141 return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
1142 }
1143
dumpLocked(String8 & result,const char * prefix) const1144 void GLConsumer::dumpLocked(String8& result, const char* prefix) const
1145 {
1146 result.appendFormat(
1147 "%smTexName=%d mCurrentTexture=%d\n"
1148 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
1149 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
1150 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
1151 mCurrentTransform);
1152
1153 ConsumerBase::dumpLocked(result, prefix);
1154 }
1155
mtxMul(float out[16],const float a[16],const float b[16])1156 static void mtxMul(float out[16], const float a[16], const float b[16]) {
1157 out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1158 out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1159 out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1160 out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1161
1162 out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1163 out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1164 out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1165 out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1166
1167 out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1168 out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1169 out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1170 out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1171
1172 out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1173 out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1174 out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1175 out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1176 }
1177
EglImage(sp<GraphicBuffer> graphicBuffer)1178 GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
1179 mGraphicBuffer(graphicBuffer),
1180 mEglImage(EGL_NO_IMAGE_KHR),
1181 mEglDisplay(EGL_NO_DISPLAY),
1182 mCropRect(Rect::EMPTY_RECT) {
1183 }
1184
~EglImage()1185 GLConsumer::EglImage::~EglImage() {
1186 if (mEglImage != EGL_NO_IMAGE_KHR) {
1187 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
1188 ALOGE("~EglImage: eglDestroyImageKHR failed");
1189 }
1190 eglTerminate(mEglDisplay);
1191 }
1192 }
1193
createIfNeeded(EGLDisplay eglDisplay,const Rect & cropRect,bool forceCreation)1194 status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
1195 const Rect& cropRect,
1196 bool forceCreation) {
1197 // If there's an image and it's no longer valid, destroy it.
1198 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
1199 bool displayInvalid = mEglDisplay != eglDisplay;
1200 bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
1201 if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
1202 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
1203 ALOGE("createIfNeeded: eglDestroyImageKHR failed");
1204 }
1205 eglTerminate(mEglDisplay);
1206 mEglImage = EGL_NO_IMAGE_KHR;
1207 mEglDisplay = EGL_NO_DISPLAY;
1208 }
1209
1210 // If there's no image, create one.
1211 if (mEglImage == EGL_NO_IMAGE_KHR) {
1212 mEglDisplay = eglDisplay;
1213 mCropRect = cropRect;
1214 mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
1215 }
1216
1217 // Fail if we can't create a valid image.
1218 if (mEglImage == EGL_NO_IMAGE_KHR) {
1219 mEglDisplay = EGL_NO_DISPLAY;
1220 mCropRect.makeInvalid();
1221 const sp<GraphicBuffer>& buffer = mGraphicBuffer;
1222 ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d",
1223 buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
1224 buffer->getUsage(), buffer->getPixelFormat());
1225 return UNKNOWN_ERROR;
1226 }
1227
1228 return OK;
1229 }
1230
bindToTextureTarget(uint32_t texTarget)1231 void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
1232 glEGLImageTargetTexture2DOES(texTarget,
1233 static_cast<GLeglImageOES>(mEglImage));
1234 }
1235
createImage(EGLDisplay dpy,const sp<GraphicBuffer> & graphicBuffer,const Rect & crop)1236 EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
1237 const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
1238 EGLClientBuffer cbuf =
1239 static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
1240 const bool createProtectedImage =
1241 (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
1242 hasEglProtectedContent();
1243 EGLint attrs[] = {
1244 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
1245 EGL_IMAGE_CROP_LEFT_ANDROID, crop.left,
1246 EGL_IMAGE_CROP_TOP_ANDROID, crop.top,
1247 EGL_IMAGE_CROP_RIGHT_ANDROID, crop.right,
1248 EGL_IMAGE_CROP_BOTTOM_ANDROID, crop.bottom,
1249 createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
1250 createProtectedImage ? EGL_TRUE : EGL_NONE,
1251 EGL_NONE,
1252 };
1253 if (!crop.isValid()) {
1254 // No crop rect to set, so leave the crop out of the attrib array. Make
1255 // sure to propagate the protected content attrs if they are set.
1256 attrs[2] = attrs[10];
1257 attrs[3] = attrs[11];
1258 attrs[4] = EGL_NONE;
1259 } else if (!isEglImageCroppable(crop)) {
1260 // The crop rect is not at the origin, so we can't set the crop on the
1261 // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
1262 // extension. In the future we can add a layered extension that
1263 // removes this restriction if there is hardware that can support it.
1264 attrs[2] = attrs[10];
1265 attrs[3] = attrs[11];
1266 attrs[4] = EGL_NONE;
1267 }
1268 eglInitialize(dpy, 0, 0);
1269 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
1270 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
1271 if (image == EGL_NO_IMAGE_KHR) {
1272 EGLint error = eglGetError();
1273 ALOGE("error creating EGLImage: %#x", error);
1274 eglTerminate(dpy);
1275 }
1276 return image;
1277 }
1278
1279 }; // namespace android
1280