• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/GLConsumer.h>
33 #include <gui/IGraphicBufferAlloc.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 
47 namespace android {
48 
49 // Macros for including the GLConsumer name in log messages
50 #define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
51 #define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
52 #define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
53 #define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
54 #define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
55 
56 static const struct {
57     size_t width, height;
58     char const* bits;
59 } kDebugData = { 15, 12,
60     "___________________________________XX_XX_______X_X_____X_X____X_XXXXXXX_X____XXXXXXXXXXX__"
61     "___XX_XXX_XX_______XXXXXXX_________X___X_________X_____X__________________________________"
62 };
63 
64 // Transform matrices
65 static float mtxIdentity[16] = {
66     1, 0, 0, 0,
67     0, 1, 0, 0,
68     0, 0, 1, 0,
69     0, 0, 0, 1,
70 };
71 static float mtxFlipH[16] = {
72     -1, 0, 0, 0,
73     0, 1, 0, 0,
74     0, 0, 1, 0,
75     1, 0, 0, 1,
76 };
77 static float mtxFlipV[16] = {
78     1, 0, 0, 0,
79     0, -1, 0, 0,
80     0, 0, 1, 0,
81     0, 1, 0, 1,
82 };
83 static float mtxRot90[16] = {
84     0, 1, 0, 0,
85     -1, 0, 0, 0,
86     0, 0, 1, 0,
87     1, 0, 0, 1,
88 };
89 
90 static void mtxMul(float out[16], const float a[16], const float b[16]);
91 
92 Mutex GLConsumer::sStaticInitLock;
93 sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
94 
hasEglAndroidImageCropImpl()95 static bool hasEglAndroidImageCropImpl() {
96     EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
97     const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
98     size_t cropExtLen = strlen(CROP_EXT_STR);
99     size_t extsLen = strlen(exts);
100     bool equal = !strcmp(CROP_EXT_STR, exts);
101     bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1);
102     bool atEnd = (cropExtLen+1) < extsLen &&
103             !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1));
104     bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
105     return equal || atStart || atEnd || inMiddle;
106 }
107 
hasEglAndroidImageCrop()108 static bool hasEglAndroidImageCrop() {
109     // Only compute whether the extension is present once the first time this
110     // function is called.
111     static bool hasIt = hasEglAndroidImageCropImpl();
112     return hasIt;
113 }
114 
isEglImageCroppable(const Rect & crop)115 static bool isEglImageCroppable(const Rect& crop) {
116     return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
117 }
118 
GLConsumer(const sp<IGraphicBufferConsumer> & bq,uint32_t tex,uint32_t texTarget,bool useFenceSync,bool isControlledByApp)119 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
120         uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
121     ConsumerBase(bq, isControlledByApp),
122     mCurrentTransform(0),
123     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
124     mCurrentFence(Fence::NO_FENCE),
125     mCurrentTimestamp(0),
126     mCurrentFrameNumber(0),
127     mDefaultWidth(1),
128     mDefaultHeight(1),
129     mFilteringEnabled(true),
130     mTexName(tex),
131     mUseFenceSync(useFenceSync),
132     mTexTarget(texTarget),
133     mEglDisplay(EGL_NO_DISPLAY),
134     mEglContext(EGL_NO_CONTEXT),
135     mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
136     mAttached(true)
137 {
138     ST_LOGV("GLConsumer");
139 
140     memcpy(mCurrentTransformMatrix, mtxIdentity,
141             sizeof(mCurrentTransformMatrix));
142 
143     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
144 }
145 
setDefaultMaxBufferCount(int bufferCount)146 status_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
147     Mutex::Autolock lock(mMutex);
148     return mConsumer->setDefaultMaxBufferCount(bufferCount);
149 }
150 
151 
setDefaultBufferSize(uint32_t w,uint32_t h)152 status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
153 {
154     Mutex::Autolock lock(mMutex);
155     mDefaultWidth = w;
156     mDefaultHeight = h;
157     return mConsumer->setDefaultBufferSize(w, h);
158 }
159 
updateTexImage()160 status_t GLConsumer::updateTexImage() {
161     ATRACE_CALL();
162     ST_LOGV("updateTexImage");
163     Mutex::Autolock lock(mMutex);
164 
165     if (mAbandoned) {
166         ST_LOGE("updateTexImage: GLConsumer is abandoned!");
167         return NO_INIT;
168     }
169 
170     // Make sure the EGL state is the same as in previous calls.
171     status_t err = checkAndUpdateEglStateLocked();
172     if (err != NO_ERROR) {
173         return err;
174     }
175 
176     BufferQueue::BufferItem item;
177 
178     // Acquire the next buffer.
179     // In asynchronous mode the list is guaranteed to be one buffer
180     // deep, while in synchronous mode we use the oldest buffer.
181     err = acquireBufferLocked(&item, 0);
182     if (err != NO_ERROR) {
183         if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
184             // We always bind the texture even if we don't update its contents.
185             ST_LOGV("updateTexImage: no buffers were available");
186             glBindTexture(mTexTarget, mTexName);
187             err = NO_ERROR;
188         } else {
189             ST_LOGE("updateTexImage: acquire failed: %s (%d)",
190                 strerror(-err), err);
191         }
192         return err;
193     }
194 
195     // Release the previous buffer.
196     err = updateAndReleaseLocked(item);
197     if (err != NO_ERROR) {
198         // We always bind the texture.
199         glBindTexture(mTexTarget, mTexName);
200         return err;
201     }
202 
203     // Bind the new buffer to the GL texture, and wait until it's ready.
204     return bindTextureImageLocked();
205 }
206 
207 
releaseTexImage()208 status_t GLConsumer::releaseTexImage() {
209     ATRACE_CALL();
210     ST_LOGV("releaseTexImage");
211     Mutex::Autolock lock(mMutex);
212 
213     if (mAbandoned) {
214         ST_LOGE("releaseTexImage: GLConsumer is abandoned!");
215         return NO_INIT;
216     }
217 
218     // Make sure the EGL state is the same as in previous calls.
219     status_t err = NO_ERROR;
220 
221     if (mAttached) {
222         err = checkAndUpdateEglStateLocked(true);
223         if (err != NO_ERROR) {
224             return err;
225         }
226     } else {
227         // if we're detached, no need to validate EGL's state -- we won't use it.
228     }
229 
230     // Update the GLConsumer state.
231     int buf = mCurrentTexture;
232     if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
233 
234         ST_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached);
235 
236         if (mAttached) {
237             // Do whatever sync ops we need to do before releasing the slot.
238             err = syncForReleaseLocked(mEglDisplay);
239             if (err != NO_ERROR) {
240                 ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
241                 return err;
242             }
243         } else {
244             // if we're detached, we just use the fence that was created in detachFromContext()
245             // so... basically, nothing more to do here.
246         }
247 
248         err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
249         if (err < NO_ERROR) {
250             ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)",
251                     strerror(-err), err);
252             return err;
253         }
254 
255         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
256         mCurrentTextureBuf = getDebugTexImageBuffer();
257         mCurrentCrop.makeInvalid();
258         mCurrentTransform = 0;
259         mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
260         mCurrentTimestamp = 0;
261         mCurrentFence = Fence::NO_FENCE;
262 
263         if (mAttached) {
264             // bind a dummy texture
265             glBindTexture(mTexTarget, mTexName);
266             bindUnslottedBufferLocked(mEglDisplay);
267         } else {
268             // detached, don't touch the texture (and we may not even have an
269             // EGLDisplay here.
270         }
271     }
272 
273     return NO_ERROR;
274 }
275 
getDebugTexImageBuffer()276 sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
277     Mutex::Autolock _l(sStaticInitLock);
278     if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
279         // The first time, create the debug texture in case the application
280         // continues to use it.
281         sp<GraphicBuffer> buffer = new GraphicBuffer(
282                 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
283                 GraphicBuffer::USAGE_SW_WRITE_RARELY);
284         uint32_t* bits;
285         buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
286         size_t w = buffer->getStride();
287         size_t h = buffer->getHeight();
288         memset(bits, 0, w*h*4);
289         for (size_t y=0 ; y<kDebugData.height ; y++) {
290             for (size_t x=0 ; x<kDebugData.width ; x++) {
291                 bits[x] = (kDebugData.bits[y*kDebugData.width+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF;
292             }
293             bits += w;
294         }
295         buffer->unlock();
296         sReleasedTexImageBuffer = buffer;
297     }
298     return sReleasedTexImageBuffer;
299 }
300 
acquireBufferLocked(BufferQueue::BufferItem * item,nsecs_t presentWhen)301 status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item,
302         nsecs_t presentWhen) {
303     status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
304     if (err != NO_ERROR) {
305         return err;
306     }
307 
308     int slot = item->mBuf;
309     bool destroyEglImage = false;
310 
311     if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) {
312         if (item->mGraphicBuffer != NULL) {
313             // This buffer has not been acquired before, so we must assume
314             // that any EGLImage in mEglSlots is stale.
315             destroyEglImage = true;
316         } else if (mEglSlots[slot].mCropRect != item->mCrop) {
317             // We've already seen this buffer before, but it now has a
318             // different crop rect, so we'll need to recreate the EGLImage if
319             // we're using the EGL_ANDROID_image_crop extension.
320             destroyEglImage = hasEglAndroidImageCrop();
321         }
322     }
323 
324     if (destroyEglImage) {
325         if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) {
326             ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d",
327                   slot);
328             // keep going
329         }
330         mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR;
331     }
332 
333     return NO_ERROR;
334 }
335 
releaseBufferLocked(int buf,sp<GraphicBuffer> graphicBuffer,EGLDisplay display,EGLSyncKHR eglFence)336 status_t GLConsumer::releaseBufferLocked(int buf,
337         sp<GraphicBuffer> graphicBuffer,
338         EGLDisplay display, EGLSyncKHR eglFence) {
339     // release the buffer if it hasn't already been discarded by the
340     // BufferQueue. This can happen, for example, when the producer of this
341     // buffer has reallocated the original buffer slot after this buffer
342     // was acquired.
343     status_t err = ConsumerBase::releaseBufferLocked(
344             buf, graphicBuffer, display, eglFence);
345     mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
346     return err;
347 }
348 
updateAndReleaseLocked(const BufferQueue::BufferItem & item)349 status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item)
350 {
351     status_t err = NO_ERROR;
352 
353     if (!mAttached) {
354         ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
355                 "ES context");
356         return INVALID_OPERATION;
357     }
358 
359     // Confirm state.
360     err = checkAndUpdateEglStateLocked();
361     if (err != NO_ERROR) {
362         return err;
363     }
364 
365     int buf = item.mBuf;
366 
367     // If the mEglSlot entry is empty, create an EGLImage for the gralloc
368     // buffer currently in the slot in ConsumerBase.
369     //
370     // We may have to do this even when item.mGraphicBuffer == NULL (which
371     // means the buffer was previously acquired), if we destroyed the
372     // EGLImage when detaching from a context but the buffer has not been
373     // re-allocated.
374     if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) {
375         EGLImageKHR image = createImage(mEglDisplay,
376                 mSlots[buf].mGraphicBuffer, item.mCrop);
377         if (image == EGL_NO_IMAGE_KHR) {
378             ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
379                   mEglDisplay, buf);
380             return UNKNOWN_ERROR;
381         }
382         mEglSlots[buf].mEglImage = image;
383         mEglSlots[buf].mCropRect = item.mCrop;
384     }
385 
386     // Do whatever sync ops we need to do before releasing the old slot.
387     err = syncForReleaseLocked(mEglDisplay);
388     if (err != NO_ERROR) {
389         // Release the buffer we just acquired.  It's not safe to
390         // release the old buffer, so instead we just drop the new frame.
391         // As we are still under lock since acquireBuffer, it is safe to
392         // release by slot.
393         releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
394                 mEglDisplay, EGL_NO_SYNC_KHR);
395         return err;
396     }
397 
398     ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
399             mCurrentTexture,
400             mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
401             buf, mSlots[buf].mGraphicBuffer->handle);
402 
403     // release old buffer
404     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
405         status_t status = releaseBufferLocked(
406                 mCurrentTexture, mCurrentTextureBuf, mEglDisplay,
407                 mEglSlots[mCurrentTexture].mEglFence);
408         if (status < NO_ERROR) {
409             ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
410                    strerror(-status), status);
411             err = status;
412             // keep going, with error raised [?]
413         }
414     }
415 
416     // Update the GLConsumer state.
417     mCurrentTexture = buf;
418     mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
419     mCurrentCrop = item.mCrop;
420     mCurrentTransform = item.mTransform;
421     mCurrentScalingMode = item.mScalingMode;
422     mCurrentTimestamp = item.mTimestamp;
423     mCurrentFence = item.mFence;
424     mCurrentFrameNumber = item.mFrameNumber;
425 
426     computeCurrentTransformMatrixLocked();
427 
428     return err;
429 }
430 
bindTextureImageLocked()431 status_t GLConsumer::bindTextureImageLocked() {
432     if (mEglDisplay == EGL_NO_DISPLAY) {
433         ALOGE("bindTextureImage: invalid display");
434         return INVALID_OPERATION;
435     }
436 
437     GLint error;
438     while ((error = glGetError()) != GL_NO_ERROR) {
439         ST_LOGW("bindTextureImage: clearing GL error: %#04x", error);
440     }
441 
442     glBindTexture(mTexTarget, mTexName);
443     if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
444         if (mCurrentTextureBuf == NULL) {
445             ST_LOGE("bindTextureImage: no currently-bound texture");
446             return NO_INIT;
447         }
448         status_t err = bindUnslottedBufferLocked(mEglDisplay);
449         if (err != NO_ERROR) {
450             return err;
451         }
452     } else {
453         EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage;
454 
455         glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
456 
457         while ((error = glGetError()) != GL_NO_ERROR) {
458             ST_LOGE("bindTextureImage: error binding external texture image %p"
459                     ": %#04x", image, error);
460             return UNKNOWN_ERROR;
461         }
462     }
463 
464     // Wait for the new buffer to be ready.
465     return doGLFenceWaitLocked();
466 
467 }
468 
checkAndUpdateEglStateLocked(bool contextCheck)469 status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
470     EGLDisplay dpy = eglGetCurrentDisplay();
471     EGLContext ctx = eglGetCurrentContext();
472 
473     if (!contextCheck) {
474         // if this is the first time we're called, mEglDisplay/mEglContext have
475         // never been set, so don't error out (below).
476         if (mEglDisplay == EGL_NO_DISPLAY) {
477             mEglDisplay = dpy;
478         }
479         if (mEglContext == EGL_NO_DISPLAY) {
480             mEglContext = ctx;
481         }
482     }
483 
484     if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
485         ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
486         return INVALID_OPERATION;
487     }
488 
489     if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
490         ST_LOGE("checkAndUpdateEglState: invalid current EGLContext");
491         return INVALID_OPERATION;
492     }
493 
494     mEglDisplay = dpy;
495     mEglContext = ctx;
496     return NO_ERROR;
497 }
498 
setReleaseFence(const sp<Fence> & fence)499 void GLConsumer::setReleaseFence(const sp<Fence>& fence) {
500     if (fence->isValid() &&
501             mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
502         status_t err = addReleaseFence(mCurrentTexture,
503                 mCurrentTextureBuf, fence);
504         if (err != OK) {
505             ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)",
506                     strerror(-err), err);
507         }
508     }
509 }
510 
detachFromContext()511 status_t GLConsumer::detachFromContext() {
512     ATRACE_CALL();
513     ST_LOGV("detachFromContext");
514     Mutex::Autolock lock(mMutex);
515 
516     if (mAbandoned) {
517         ST_LOGE("detachFromContext: abandoned GLConsumer");
518         return NO_INIT;
519     }
520 
521     if (!mAttached) {
522         ST_LOGE("detachFromContext: GLConsumer is not attached to a "
523                 "context");
524         return INVALID_OPERATION;
525     }
526 
527     EGLDisplay dpy = eglGetCurrentDisplay();
528     EGLContext ctx = eglGetCurrentContext();
529 
530     if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
531         ST_LOGE("detachFromContext: invalid current EGLDisplay");
532         return INVALID_OPERATION;
533     }
534 
535     if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
536         ST_LOGE("detachFromContext: invalid current EGLContext");
537         return INVALID_OPERATION;
538     }
539 
540     if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
541         status_t err = syncForReleaseLocked(dpy);
542         if (err != OK) {
543             return err;
544         }
545 
546         glDeleteTextures(1, &mTexName);
547     }
548 
549     // Because we're giving up the EGLDisplay we need to free all the EGLImages
550     // that are associated with it.  They'll be recreated when the
551     // GLConsumer gets attached to a new OpenGL ES context (and thus gets a
552     // new EGLDisplay).
553     for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
554         EGLImageKHR img = mEglSlots[i].mEglImage;
555         if (img != EGL_NO_IMAGE_KHR) {
556             eglDestroyImageKHR(mEglDisplay, img);
557             mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
558         }
559     }
560 
561     mEglDisplay = EGL_NO_DISPLAY;
562     mEglContext = EGL_NO_CONTEXT;
563     mAttached = false;
564 
565     return OK;
566 }
567 
attachToContext(uint32_t tex)568 status_t GLConsumer::attachToContext(uint32_t tex) {
569     ATRACE_CALL();
570     ST_LOGV("attachToContext");
571     Mutex::Autolock lock(mMutex);
572 
573     if (mAbandoned) {
574         ST_LOGE("attachToContext: abandoned GLConsumer");
575         return NO_INIT;
576     }
577 
578     if (mAttached) {
579         ST_LOGE("attachToContext: GLConsumer is already attached to a "
580                 "context");
581         return INVALID_OPERATION;
582     }
583 
584     EGLDisplay dpy = eglGetCurrentDisplay();
585     EGLContext ctx = eglGetCurrentContext();
586 
587     if (dpy == EGL_NO_DISPLAY) {
588         ST_LOGE("attachToContext: invalid current EGLDisplay");
589         return INVALID_OPERATION;
590     }
591 
592     if (ctx == EGL_NO_CONTEXT) {
593         ST_LOGE("attachToContext: invalid current EGLContext");
594         return INVALID_OPERATION;
595     }
596 
597     // We need to bind the texture regardless of whether there's a current
598     // buffer.
599     glBindTexture(mTexTarget, GLuint(tex));
600 
601     if (mCurrentTextureBuf != NULL) {
602         // The EGLImageKHR that was associated with the slot was destroyed when
603         // the GLConsumer was detached from the old context, so we need to
604         // recreate it here.
605         status_t err = bindUnslottedBufferLocked(dpy);
606         if (err != NO_ERROR) {
607             return err;
608         }
609     }
610 
611     mEglDisplay = dpy;
612     mEglContext = ctx;
613     mTexName = tex;
614     mAttached = true;
615 
616     return OK;
617 }
618 
bindUnslottedBufferLocked(EGLDisplay dpy)619 status_t GLConsumer::bindUnslottedBufferLocked(EGLDisplay dpy) {
620     ST_LOGV("bindUnslottedBuffer ct=%d ctb=%p",
621             mCurrentTexture, mCurrentTextureBuf.get());
622 
623     // Create a temporary EGLImageKHR.
624     Rect crop;
625     EGLImageKHR image = createImage(dpy, mCurrentTextureBuf, mCurrentCrop);
626     if (image == EGL_NO_IMAGE_KHR) {
627         return UNKNOWN_ERROR;
628     }
629 
630     // Attach the current buffer to the GL texture.
631     glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
632 
633     GLint error;
634     status_t err = OK;
635     while ((error = glGetError()) != GL_NO_ERROR) {
636         ST_LOGE("bindUnslottedBuffer: error binding external texture image %p "
637                 "(slot %d): %#04x", image, mCurrentTexture, error);
638         err = UNKNOWN_ERROR;
639     }
640 
641     // We destroy the EGLImageKHR here because the current buffer may no
642     // longer be associated with one of the buffer slots, so we have
643     // nowhere to to store it.  If the buffer is still associated with a
644     // slot then another EGLImageKHR will be created next time that buffer
645     // gets acquired in updateTexImage.
646     eglDestroyImageKHR(dpy, image);
647 
648     return err;
649 }
650 
651 
syncForReleaseLocked(EGLDisplay dpy)652 status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
653     ST_LOGV("syncForReleaseLocked");
654 
655     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
656         if (SyncFeatures::getInstance().useNativeFenceSync()) {
657             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
658                     EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
659             if (sync == EGL_NO_SYNC_KHR) {
660                 ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
661                         eglGetError());
662                 return UNKNOWN_ERROR;
663             }
664             glFlush();
665             int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
666             eglDestroySyncKHR(dpy, sync);
667             if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
668                 ST_LOGE("syncForReleaseLocked: error dup'ing native fence "
669                         "fd: %#x", eglGetError());
670                 return UNKNOWN_ERROR;
671             }
672             sp<Fence> fence(new Fence(fenceFd));
673             status_t err = addReleaseFenceLocked(mCurrentTexture,
674                     mCurrentTextureBuf, fence);
675             if (err != OK) {
676                 ST_LOGE("syncForReleaseLocked: error adding release fence: "
677                         "%s (%d)", strerror(-err), err);
678                 return err;
679             }
680         } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
681             EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence;
682             if (fence != EGL_NO_SYNC_KHR) {
683                 // There is already a fence for the current slot.  We need to
684                 // wait on that before replacing it with another fence to
685                 // ensure that all outstanding buffer accesses have completed
686                 // before the producer accesses it.
687                 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
688                 if (result == EGL_FALSE) {
689                     ST_LOGE("syncForReleaseLocked: error waiting for previous "
690                             "fence: %#x", eglGetError());
691                     return UNKNOWN_ERROR;
692                 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
693                     ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
694                             "fence");
695                     return TIMED_OUT;
696                 }
697                 eglDestroySyncKHR(dpy, fence);
698             }
699 
700             // Create a fence for the outstanding accesses in the current
701             // OpenGL ES context.
702             fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
703             if (fence == EGL_NO_SYNC_KHR) {
704                 ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
705                         eglGetError());
706                 return UNKNOWN_ERROR;
707             }
708             glFlush();
709             mEglSlots[mCurrentTexture].mEglFence = fence;
710         }
711     }
712 
713     return OK;
714 }
715 
isExternalFormat(uint32_t format)716 bool GLConsumer::isExternalFormat(uint32_t format)
717 {
718     switch (format) {
719     // supported YUV formats
720     case HAL_PIXEL_FORMAT_YV12:
721     // Legacy/deprecated YUV formats
722     case HAL_PIXEL_FORMAT_YCbCr_422_SP:
723     case HAL_PIXEL_FORMAT_YCrCb_420_SP:
724     case HAL_PIXEL_FORMAT_YCbCr_422_I:
725         return true;
726     }
727 
728     // Any OEM format needs to be considered
729     if (format>=0x100 && format<=0x1FF)
730         return true;
731 
732     return false;
733 }
734 
getCurrentTextureTarget() const735 uint32_t GLConsumer::getCurrentTextureTarget() const {
736     return mTexTarget;
737 }
738 
getTransformMatrix(float mtx[16])739 void GLConsumer::getTransformMatrix(float mtx[16]) {
740     Mutex::Autolock lock(mMutex);
741     memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
742 }
743 
setFilteringEnabled(bool enabled)744 void GLConsumer::setFilteringEnabled(bool enabled) {
745     Mutex::Autolock lock(mMutex);
746     if (mAbandoned) {
747         ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!");
748         return;
749     }
750     bool needsRecompute = mFilteringEnabled != enabled;
751     mFilteringEnabled = enabled;
752 
753     if (needsRecompute && mCurrentTextureBuf==NULL) {
754         ST_LOGD("setFilteringEnabled called with mCurrentTextureBuf == NULL");
755     }
756 
757     if (needsRecompute && mCurrentTextureBuf != NULL) {
758         computeCurrentTransformMatrixLocked();
759     }
760 }
761 
computeCurrentTransformMatrixLocked()762 void GLConsumer::computeCurrentTransformMatrixLocked() {
763     ST_LOGV("computeCurrentTransformMatrixLocked");
764 
765     float xform[16];
766     for (int i = 0; i < 16; i++) {
767         xform[i] = mtxIdentity[i];
768     }
769     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
770         float result[16];
771         mtxMul(result, xform, mtxFlipH);
772         for (int i = 0; i < 16; i++) {
773             xform[i] = result[i];
774         }
775     }
776     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
777         float result[16];
778         mtxMul(result, xform, mtxFlipV);
779         for (int i = 0; i < 16; i++) {
780             xform[i] = result[i];
781         }
782     }
783     if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
784         float result[16];
785         mtxMul(result, xform, mtxRot90);
786         for (int i = 0; i < 16; i++) {
787             xform[i] = result[i];
788         }
789     }
790 
791     sp<GraphicBuffer>& buf(mCurrentTextureBuf);
792 
793     if (buf == NULL) {
794         ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL");
795     }
796 
797     float mtxBeforeFlipV[16];
798     if (!isEglImageCroppable(mCurrentCrop)) {
799         Rect cropRect = mCurrentCrop;
800         float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
801         float bufferWidth = buf->getWidth();
802         float bufferHeight = buf->getHeight();
803         if (!cropRect.isEmpty()) {
804             float shrinkAmount = 0.0f;
805             if (mFilteringEnabled) {
806                 // In order to prevent bilinear sampling beyond the edge of the
807                 // crop rectangle we may need to shrink it by 2 texels in each
808                 // dimension.  Normally this would just need to take 1/2 a texel
809                 // off each end, but because the chroma channels of YUV420 images
810                 // are subsampled we may need to shrink the crop region by a whole
811                 // texel on each side.
812                 switch (buf->getPixelFormat()) {
813                     case PIXEL_FORMAT_RGBA_8888:
814                     case PIXEL_FORMAT_RGBX_8888:
815                     case PIXEL_FORMAT_RGB_888:
816                     case PIXEL_FORMAT_RGB_565:
817                     case PIXEL_FORMAT_BGRA_8888:
818                         // We know there's no subsampling of any channels, so we
819                         // only need to shrink by a half a pixel.
820                         shrinkAmount = 0.5;
821                         break;
822 
823                     default:
824                         // If we don't recognize the format, we must assume the
825                         // worst case (that we care about), which is YUV420.
826                         shrinkAmount = 1.0;
827                         break;
828                 }
829             }
830 
831             // Only shrink the dimensions that are not the size of the buffer.
832             if (cropRect.width() < bufferWidth) {
833                 tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
834                 sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
835                         bufferWidth;
836             }
837             if (cropRect.height() < bufferHeight) {
838                 ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
839                         bufferHeight;
840                 sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
841                         bufferHeight;
842             }
843         }
844         float crop[16] = {
845             sx, 0, 0, 0,
846             0, sy, 0, 0,
847             0, 0, 1, 0,
848             tx, ty, 0, 1,
849         };
850 
851         mtxMul(mtxBeforeFlipV, crop, xform);
852     } else {
853         for (int i = 0; i < 16; i++) {
854             mtxBeforeFlipV[i] = xform[i];
855         }
856     }
857 
858     // SurfaceFlinger expects the top of its window textures to be at a Y
859     // coordinate of 0, so GLConsumer must behave the same way.  We don't
860     // want to expose this to applications, however, so we must add an
861     // additional vertical flip to the transform after all the other transforms.
862     mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
863 }
864 
getTimestamp()865 nsecs_t GLConsumer::getTimestamp() {
866     ST_LOGV("getTimestamp");
867     Mutex::Autolock lock(mMutex);
868     return mCurrentTimestamp;
869 }
870 
getFrameNumber()871 nsecs_t GLConsumer::getFrameNumber() {
872     ST_LOGV("getFrameNumber");
873     Mutex::Autolock lock(mMutex);
874     return mCurrentFrameNumber;
875 }
876 
createImage(EGLDisplay dpy,const sp<GraphicBuffer> & graphicBuffer,const Rect & crop)877 EGLImageKHR GLConsumer::createImage(EGLDisplay dpy,
878         const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
879     EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
880     EGLint attrs[] = {
881         EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
882         EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
883         EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
884         EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
885         EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
886         EGL_NONE,
887     };
888     if (!crop.isValid()) {
889         // No crop rect to set, so terminate the attrib array before the crop.
890         attrs[2] = EGL_NONE;
891     } else if (!isEglImageCroppable(crop)) {
892         // The crop rect is not at the origin, so we can't set the crop on the
893         // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
894         // extension.  In the future we can add a layered extension that
895         // removes this restriction if there is hardware that can support it.
896         attrs[2] = EGL_NONE;
897     }
898     EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
899             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
900     if (image == EGL_NO_IMAGE_KHR) {
901         EGLint error = eglGetError();
902         ST_LOGE("error creating EGLImage: %#x", error);
903     }
904     return image;
905 }
906 
getCurrentBuffer() const907 sp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
908     Mutex::Autolock lock(mMutex);
909     return mCurrentTextureBuf;
910 }
911 
getCurrentCrop() const912 Rect GLConsumer::getCurrentCrop() const {
913     Mutex::Autolock lock(mMutex);
914 
915     Rect outCrop = mCurrentCrop;
916     if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
917         int32_t newWidth = mCurrentCrop.width();
918         int32_t newHeight = mCurrentCrop.height();
919 
920         if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
921             newWidth = newHeight * mDefaultWidth / mDefaultHeight;
922             ST_LOGV("too wide: newWidth = %d", newWidth);
923         } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
924             newHeight = newWidth * mDefaultHeight / mDefaultWidth;
925             ST_LOGV("too tall: newHeight = %d", newHeight);
926         }
927 
928         // The crop is too wide
929         if (newWidth < mCurrentCrop.width()) {
930             int32_t dw = (newWidth - mCurrentCrop.width())/2;
931             outCrop.left -=dw;
932             outCrop.right += dw;
933         // The crop is too tall
934         } else if (newHeight < mCurrentCrop.height()) {
935             int32_t dh = (newHeight - mCurrentCrop.height())/2;
936             outCrop.top -= dh;
937             outCrop.bottom += dh;
938         }
939 
940         ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
941             outCrop.left, outCrop.top,
942             outCrop.right,outCrop.bottom);
943     }
944 
945     return outCrop;
946 }
947 
getCurrentTransform() const948 uint32_t GLConsumer::getCurrentTransform() const {
949     Mutex::Autolock lock(mMutex);
950     return mCurrentTransform;
951 }
952 
getCurrentScalingMode() const953 uint32_t GLConsumer::getCurrentScalingMode() const {
954     Mutex::Autolock lock(mMutex);
955     return mCurrentScalingMode;
956 }
957 
getCurrentFence() const958 sp<Fence> GLConsumer::getCurrentFence() const {
959     Mutex::Autolock lock(mMutex);
960     return mCurrentFence;
961 }
962 
doGLFenceWait() const963 status_t GLConsumer::doGLFenceWait() const {
964     Mutex::Autolock lock(mMutex);
965     return doGLFenceWaitLocked();
966 }
967 
doGLFenceWaitLocked() const968 status_t GLConsumer::doGLFenceWaitLocked() const {
969 
970     EGLDisplay dpy = eglGetCurrentDisplay();
971     EGLContext ctx = eglGetCurrentContext();
972 
973     if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
974         ST_LOGE("doGLFenceWait: invalid current EGLDisplay");
975         return INVALID_OPERATION;
976     }
977 
978     if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
979         ST_LOGE("doGLFenceWait: invalid current EGLContext");
980         return INVALID_OPERATION;
981     }
982 
983     if (mCurrentFence->isValid()) {
984         if (SyncFeatures::getInstance().useWaitSync()) {
985             // Create an EGLSyncKHR from the current fence.
986             int fenceFd = mCurrentFence->dup();
987             if (fenceFd == -1) {
988                 ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
989                 return -errno;
990             }
991             EGLint attribs[] = {
992                 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
993                 EGL_NONE
994             };
995             EGLSyncKHR sync = eglCreateSyncKHR(dpy,
996                     EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
997             if (sync == EGL_NO_SYNC_KHR) {
998                 close(fenceFd);
999                 ST_LOGE("doGLFenceWait: error creating EGL fence: %#x",
1000                         eglGetError());
1001                 return UNKNOWN_ERROR;
1002             }
1003 
1004             // XXX: The spec draft is inconsistent as to whether this should
1005             // return an EGLint or void.  Ignore the return value for now, as
1006             // it's not strictly needed.
1007             eglWaitSyncKHR(dpy, sync, 0);
1008             EGLint eglErr = eglGetError();
1009             eglDestroySyncKHR(dpy, sync);
1010             if (eglErr != EGL_SUCCESS) {
1011                 ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x",
1012                         eglErr);
1013                 return UNKNOWN_ERROR;
1014             }
1015         } else {
1016             status_t err = mCurrentFence->waitForever(
1017                     "GLConsumer::doGLFenceWaitLocked");
1018             if (err != NO_ERROR) {
1019                 ST_LOGE("doGLFenceWait: error waiting for fence: %d", err);
1020                 return err;
1021             }
1022         }
1023     }
1024 
1025     return NO_ERROR;
1026 }
1027 
freeBufferLocked(int slotIndex)1028 void GLConsumer::freeBufferLocked(int slotIndex) {
1029     ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
1030     if (slotIndex == mCurrentTexture) {
1031         mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
1032     }
1033     EGLImageKHR img = mEglSlots[slotIndex].mEglImage;
1034     if (img != EGL_NO_IMAGE_KHR) {
1035         ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
1036         eglDestroyImageKHR(mEglDisplay, img);
1037     }
1038     mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
1039     ConsumerBase::freeBufferLocked(slotIndex);
1040 }
1041 
abandonLocked()1042 void GLConsumer::abandonLocked() {
1043     ST_LOGV("abandonLocked");
1044     mCurrentTextureBuf.clear();
1045     ConsumerBase::abandonLocked();
1046 }
1047 
setName(const String8 & name)1048 void GLConsumer::setName(const String8& name) {
1049     Mutex::Autolock _l(mMutex);
1050     mName = name;
1051     mConsumer->setConsumerName(name);
1052 }
1053 
setDefaultBufferFormat(uint32_t defaultFormat)1054 status_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) {
1055     Mutex::Autolock lock(mMutex);
1056     return mConsumer->setDefaultBufferFormat(defaultFormat);
1057 }
1058 
setConsumerUsageBits(uint32_t usage)1059 status_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
1060     Mutex::Autolock lock(mMutex);
1061     usage |= DEFAULT_USAGE_FLAGS;
1062     return mConsumer->setConsumerUsageBits(usage);
1063 }
1064 
setTransformHint(uint32_t hint)1065 status_t GLConsumer::setTransformHint(uint32_t hint) {
1066     Mutex::Autolock lock(mMutex);
1067     return mConsumer->setTransformHint(hint);
1068 }
1069 
dumpLocked(String8 & result,const char * prefix) const1070 void GLConsumer::dumpLocked(String8& result, const char* prefix) const
1071 {
1072     result.appendFormat(
1073        "%smTexName=%d mCurrentTexture=%d\n"
1074        "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
1075        prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
1076        mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
1077        mCurrentTransform);
1078 
1079     ConsumerBase::dumpLocked(result, prefix);
1080 }
1081 
mtxMul(float out[16],const float a[16],const float b[16])1082 static void mtxMul(float out[16], const float a[16], const float b[16]) {
1083     out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
1084     out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
1085     out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
1086     out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
1087 
1088     out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
1089     out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
1090     out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
1091     out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
1092 
1093     out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
1094     out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
1095     out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
1096     out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
1097 
1098     out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
1099     out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
1100     out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
1101     out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
1102 }
1103 
1104 }; // namespace android
1105