1e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 2376b1529a383c39adf4674baf6db83a5e63f97acJason Evans * Copyright (C) 2010 The Android Open Source Project 3e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 4e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Licensed under the Apache License, Version 2.0 (the "License"); 5e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * you may not use this file except in compliance with the License. 6e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * You may obtain a copy of the License at 7609ae595f0358157b19311b0f9f9591db7cee705Jason Evans * 8609ae595f0358157b19311b0f9f9591db7cee705Jason Evans * http://www.apache.org/licenses/LICENSE-2.0 9e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 103c2343518c2b1fbbd66065c75a3c19f908de1d78Jason Evans * Unless required by applicable law or agreed to in writing, software 11e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * distributed under the License is distributed on an "AS IS" BASIS, 12e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans * See the License for the specific language governing permissions and 147ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans * limitations under the License. 157ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans */ 167ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 177ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#define LOG_TAG "GLConsumer" 187ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#define ATRACE_TAG ATRACE_TAG_GRAPHICS 19609ae595f0358157b19311b0f9f9591db7cee705Jason Evans//#define LOG_NDEBUG 0 20609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 21609ae595f0358157b19311b0f9f9591db7cee705Jason Evans#define GL_GLEXT_PROTOTYPES 22609ae595f0358157b19311b0f9f9591db7cee705Jason Evans#define EGL_EGLEXT_PROTOTYPES 237ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 242dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans#include <EGL/egl.h> 252dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans#include <EGL/eglext.h> 26e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <GLES2/gl2.h> 27e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <GLES2/gl2ext.h> 28e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <cutils/compiler.h> 29e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 307393f44ff025ca67716fc53b68003fd65122fd97Jason Evans#include <hardware/hardware.h> 31e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 32e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <gui/GLConsumer.h> 33e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#include <gui/IGraphicBufferAlloc.h> 3412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans#include <gui/ISurfaceComposer.h> 3512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans#include <gui/SurfaceComposerClient.h> 3612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 3712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans#include <private/gui/ComposerService.h> 387ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#include <private/gui/SyncFeatures.h> 3912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 407ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#include <utils/Log.h> 417ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#include <utils/String8.h> 427ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#include <utils/Trace.h> 437ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 44609ae595f0358157b19311b0f9f9591db7cee705Jason EvansEGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); 45609ae595f0358157b19311b0f9f9591db7cee705Jason Evans#define CROP_EXT_STR "EGL_ANDROID_image_crop" 467ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 477ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansnamespace android { 487ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 497ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans// Macros for including the GLConsumer name in log messages 507ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__) 517de92767c20cb72c94609b9c78985526fb84a679Jason Evans#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__) 527ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans#define ST_LOGI(x, ...) ALOGI("[%s] "x, mName.string(), ##__VA_ARGS__) 5334a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans#define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) 5434a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans#define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) 5534a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans 5634a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evansstatic const struct { 5734a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans size_t width, height; 5834a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans char const* bits; 5934a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans} kDebugData = { 15, 12, 6034a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans "___________________________________XX_XX_______X_X_____X_X____X_XXXXXXX_X____XXXXXXXXXXX__" 6134a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans "___XX_XXX_XX_______XXXXXXX_________X___X_________X_____X__________________________________" 6234a8cf6c4029c09e1db776b7027a9c1b31f9e5b4Jason Evans}; 637ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 647ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans// Transform matrices 657ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic float mtxIdentity[16] = { 667ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 1, 0, 0, 0, 677ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 0, 1, 0, 0, 687ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 0, 0, 1, 0, 697ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 0, 0, 0, 1, 70609ae595f0358157b19311b0f9f9591db7cee705Jason Evans}; 717ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic float mtxFlipH[16] = { 727ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans -1, 0, 0, 0, 737ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 0, 1, 0, 0, 747ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 0, 0, 1, 0, 757ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 1, 0, 0, 1, 767ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans}; 77374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evansstatic float mtxFlipV[16] = { 78374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans 1, 0, 0, 0, 797ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 0, -1, 0, 0, 8014a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans 0, 0, 1, 0, 8114a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans 0, 1, 0, 1, 8214a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans}; 837ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic float mtxRot90[16] = { 84609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 0, 1, 0, 0, 85609ae595f0358157b19311b0f9f9591db7cee705Jason Evans -1, 0, 0, 0, 867ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 0, 0, 1, 0, 877ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 1, 0, 0, 1, 887ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans}; 89609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 90609ae595f0358157b19311b0f9f9591db7cee705Jason Evansstatic void mtxMul(float out[16], const float a[16], const float b[16]); 917ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 927ca0fdfb85b2a9fc7a112e158892c098e004385bJason EvansMutex GLConsumer::sStaticInitLock; 937ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evanssp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer; 947ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 957ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic bool hasEglAndroidImageCropImpl() { 967ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 977ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS); 987ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans size_t cropExtLen = strlen(CROP_EXT_STR); 997ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans size_t extsLen = strlen(exts); 1007ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans bool equal = !strcmp(CROP_EXT_STR, exts); 1017ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen+1); 1027ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans bool atEnd = (cropExtLen+1) < extsLen && 1037ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen+1)); 1047ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans bool inMiddle = strstr(exts, " " CROP_EXT_STR " "); 1057ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans return equal || atStart || atEnd || inMiddle; 10612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans} 1077ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 1087ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatic bool hasEglAndroidImageCrop() { 1097ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans // Only compute whether the extension is present once the first time this 1107ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans // function is called. 1117ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans static bool hasIt = hasEglAndroidImageCropImpl(); 1127ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans return hasIt; 113a7a28c334e5526ba716bf6046eab8d60598183ebJason Evans} 114609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 115609ae595f0358157b19311b0f9f9591db7cee705Jason Evansstatic bool isEglImageCroppable(const Rect& crop) { 1167ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0); 1177ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans} 1187ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 1197ca0fdfb85b2a9fc7a112e158892c098e004385bJason EvansGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, 12014a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans uint32_t texTarget, bool useFenceSync, bool isControlledByApp) : 12112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans ConsumerBase(bq, isControlledByApp), 12214a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mCurrentTransform(0), 12314a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), 12414a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mCurrentFence(Fence::NO_FENCE), 12514a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mCurrentTimestamp(0), 12614a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mCurrentFrameNumber(0), 12714a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mDefaultWidth(1), 12814a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mDefaultHeight(1), 129bd87b01999416ec7418ff8bdb504d9b6c009ff68Jason Evans mFilteringEnabled(true), 13014a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mTexName(tex), 13114a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mUseFenceSync(useFenceSync), 13214a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mTexTarget(texTarget), 13314a2c6a698a207ac3f3825443cf3441c8842e990Jason Evans mEglDisplay(EGL_NO_DISPLAY), 1347ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans mEglContext(EGL_NO_CONTEXT), 1357ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), 136e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mAttached(true) 13741631d00618d7262125e501c91d31b4d70e605faJason Evans{ 13841631d00618d7262125e501c91d31b4d70e605faJason Evans ST_LOGV("GLConsumer"); 13941631d00618d7262125e501c91d31b4d70e605faJason Evans 14041631d00618d7262125e501c91d31b4d70e605faJason Evans memcpy(mCurrentTransformMatrix, mtxIdentity, 14141631d00618d7262125e501c91d31b4d70e605faJason Evans sizeof(mCurrentTransformMatrix)); 14241631d00618d7262125e501c91d31b4d70e605faJason Evans 14359113bcc94b9fc7549611afb99ca99cad1a7f196aravind mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); 14459113bcc94b9fc7549611afb99ca99cad1a7f196aravind} 145609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 146e476f8a161d445211fd6e54fe370275196e66bcbJason EvansGLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget, 147e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool useFenceSync, bool isControlledByApp) : 148e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ConsumerBase(bq, isControlledByApp), 149e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mCurrentTransform(0), 150e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), 151de6fbdb72c6e1401b36f8f2073404645bac6cd2bJason Evans mCurrentFence(Fence::NO_FENCE), 152eae269036c9f702d9fa9be497a1a2aa1be13a29eMike Hommey mCurrentTimestamp(0), 153e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mCurrentFrameNumber(0), 154609ae595f0358157b19311b0f9f9591db7cee705Jason Evans mDefaultWidth(1), 1554d434adb146375ad17f0d5e994ed5728d2942e3fJason Evans mDefaultHeight(1), 15612efefb1953062795f5a971c1a72706787c7895cJason Evans mFilteringEnabled(true), 15712efefb1953062795f5a971c1a72706787c7895cJason Evans mTexName(-1), 15859113bcc94b9fc7549611afb99ca99cad1a7f196aravind mUseFenceSync(useFenceSync), 15912efefb1953062795f5a971c1a72706787c7895cJason Evans mTexTarget(texTarget), 16059113bcc94b9fc7549611afb99ca99cad1a7f196aravind mEglDisplay(EGL_NO_DISPLAY), 16112efefb1953062795f5a971c1a72706787c7895cJason Evans mEglContext(EGL_NO_CONTEXT), 162609ae595f0358157b19311b0f9f9591db7cee705Jason Evans mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT), 163609ae595f0358157b19311b0f9f9591db7cee705Jason Evans mAttached(false) 164609ae595f0358157b19311b0f9f9591db7cee705Jason Evans{ 16559113bcc94b9fc7549611afb99ca99cad1a7f196aravind ST_LOGV("GLConsumer"); 166609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 16759113bcc94b9fc7549611afb99ca99cad1a7f196aravind memcpy(mCurrentTransformMatrix, mtxIdentity, 168609ae595f0358157b19311b0f9f9591db7cee705Jason Evans sizeof(mCurrentTransformMatrix)); 1694d434adb146375ad17f0d5e994ed5728d2942e3fJason Evans 17012efefb1953062795f5a971c1a72706787c7895cJason Evans mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS); 17112efefb1953062795f5a971c1a72706787c7895cJason Evans} 17259113bcc94b9fc7549611afb99ca99cad1a7f196aravind 17312efefb1953062795f5a971c1a72706787c7895cJason Evansstatus_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) { 17459113bcc94b9fc7549611afb99ca99cad1a7f196aravind Mutex::Autolock lock(mMutex); 17512efefb1953062795f5a971c1a72706787c7895cJason Evans return mConsumer->setDefaultMaxBufferCount(bufferCount); 176e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 177e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 17859113bcc94b9fc7549611afb99ca99cad1a7f196aravind 17959113bcc94b9fc7549611afb99ca99cad1a7f196aravindstatus_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) 18059113bcc94b9fc7549611afb99ca99cad1a7f196aravind{ 18112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans Mutex::Autolock lock(mMutex); 18212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans mDefaultWidth = w; 18359113bcc94b9fc7549611afb99ca99cad1a7f196aravind mDefaultHeight = h; 18459113bcc94b9fc7549611afb99ca99cad1a7f196aravind return mConsumer->setDefaultBufferSize(w, h); 18512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans} 18612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 18712141150fdbda57651a53ae2fe0edaea4891d814Jason Evansstatus_t GLConsumer::updateTexImage() { 18812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans ATRACE_CALL(); 18912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans ST_LOGV("updateTexImage"); 19012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans Mutex::Autolock lock(mMutex); 19112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 19212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (mAbandoned) { 19312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans ST_LOGE("updateTexImage: GLConsumer is abandoned!"); 19412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans return NO_INIT; 19512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 19612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 19712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // Make sure the EGL state is the same as in previous calls. 19812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans status_t err = checkAndUpdateEglStateLocked(); 19912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (err != NO_ERROR) { 20012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans return err; 20112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 20212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 20312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans BufferQueue::BufferItem item; 20412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 20512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // Acquire the next buffer. 20612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // In asynchronous mode the list is guaranteed to be one buffer 20712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // deep, while in synchronous mode we use the oldest buffer. 20812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans err = acquireBufferLocked(&item, 0); 20912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (err != NO_ERROR) { 21012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (err == BufferQueue::NO_BUFFER_AVAILABLE) { 21112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // We always bind the texture even if we don't update its contents. 21259113bcc94b9fc7549611afb99ca99cad1a7f196aravind ST_LOGV("updateTexImage: no buffers were available"); 21359113bcc94b9fc7549611afb99ca99cad1a7f196aravind glBindTexture(mTexTarget, mTexName); 21459113bcc94b9fc7549611afb99ca99cad1a7f196aravind err = NO_ERROR; 21512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } else { 21659113bcc94b9fc7549611afb99ca99cad1a7f196aravind ST_LOGE("updateTexImage: acquire failed: %s (%d)", 21759113bcc94b9fc7549611afb99ca99cad1a7f196aravind strerror(-err), err); 21812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 21959113bcc94b9fc7549611afb99ca99cad1a7f196aravind return err; 22012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 22112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 22212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // Release the previous buffer. 22312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans err = updateAndReleaseLocked(item); 22412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (err != NO_ERROR) { 22512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // We always bind the texture. 22612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans glBindTexture(mTexTarget, mTexName); 22712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans return err; 22812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 22912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 23012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // Bind the new buffer to the GL texture, and wait until it's ready. 23159113bcc94b9fc7549611afb99ca99cad1a7f196aravind return bindTextureImageLocked(); 23212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans} 23312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 23412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 23512141150fdbda57651a53ae2fe0edaea4891d814Jason Evansstatus_t GLConsumer::releaseTexImage() { 23612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans ATRACE_CALL(); 23712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans ST_LOGV("releaseTexImage"); 23812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans Mutex::Autolock lock(mMutex); 23912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 24012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (mAbandoned) { 24112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans ST_LOGE("releaseTexImage: GLConsumer is abandoned!"); 242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return NO_INIT; 24312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 244e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 245e476f8a161d445211fd6e54fe370275196e66bcbJason Evans // Make sure the EGL state is the same as in previous calls. 246e476f8a161d445211fd6e54fe370275196e66bcbJason Evans status_t err = NO_ERROR; 24712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 24812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (mAttached) { 24912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans err = checkAndUpdateEglStateLocked(true); 25012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (err != NO_ERROR) { 25112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans return err; 25212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 25312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } else { 25412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // if we're detached, no need to validate EGL's state -- we won't use it. 25512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 25612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 2577ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans // Update the GLConsumer state. 258609ae595f0358157b19311b0f9f9591db7cee705Jason Evans int buf = mCurrentTexture; 259609ae595f0358157b19311b0f9f9591db7cee705Jason Evans if (buf != BufferQueue::INVALID_BUFFER_SLOT) { 2607ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans 2617de92767c20cb72c94609b9c78985526fb84a679Jason Evans ST_LOGV("releaseTexImage: (slot=%d, mAttached=%d)", buf, mAttached); 2624f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans 2637ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans if (mAttached) { 2647de92767c20cb72c94609b9c78985526fb84a679Jason Evans // Do whatever sync ops we need to do before releasing the slot. 265bd87b01999416ec7418ff8bdb504d9b6c009ff68Jason Evans err = syncForReleaseLocked(mEglDisplay); 2667ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans if (err != NO_ERROR) { 267374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err); 268374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans return err; 269374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans } 270374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans } else { 271374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans // if we're detached, we just use the fence that was created in detachFromContext() 272374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans // so... basically, nothing more to do here. 273374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans } 2744f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans 2754f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR); 276374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans if (err < NO_ERROR) { 2777ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)", 278374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans strerror(-err), err); 279609ae595f0358157b19311b0f9f9591db7cee705Jason Evans return err; 280374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans } 281374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans 282374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans if (mReleasedTexImage == NULL) { 283374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans mReleasedTexImage = new EglImage(getDebugTexImageBuffer()); 284374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans } 285374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans 286374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; 287609ae595f0358157b19311b0f9f9591db7cee705Jason Evans mCurrentTextureImage = mReleasedTexImage; 288374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans mCurrentCrop.makeInvalid(); 289374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans mCurrentTransform = 0; 2907de92767c20cb72c94609b9c78985526fb84a679Jason Evans mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; 291609ae595f0358157b19311b0f9f9591db7cee705Jason Evans mCurrentTimestamp = 0; 292374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans mCurrentFence = Fence::NO_FENCE; 293374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans 294374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans if (mAttached) { 2957ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans // This binds a dummy buffer (mReleasedTexImage). 296374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans status_t err = bindTextureImageLocked(); 297374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans if (err != NO_ERROR) { 298374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans return err; 299374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans } 3007ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans } else { 301741fbc6ba4499da39dd7d0c067c859fa52f1023fJason Evans // detached, don't touch the texture (and we may not even have an 3027ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans // EGLDisplay here. 303374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans } 304741fbc6ba4499da39dd7d0c067c859fa52f1023fJason Evans } 305374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans 306374d26a43bcceb12eb56ed7cc47815d7f933901cJason Evans return NO_ERROR; 3077de92767c20cb72c94609b9c78985526fb84a679Jason Evans} 308609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 309609ae595f0358157b19311b0f9f9591db7cee705Jason Evanssp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() { 3107ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans Mutex::Autolock _l(sStaticInitLock); 3117ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) { 3127ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans // The first time, create the debug texture in case the application 313609ae595f0358157b19311b0f9f9591db7cee705Jason Evans // continues to use it. 3147ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans sp<GraphicBuffer> buffer = new GraphicBuffer( 3157ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888, 3167ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans GraphicBuffer::USAGE_SW_WRITE_RARELY); 3177ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans uint32_t* bits; 3187ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits)); 3197ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans size_t w = buffer->getStride(); 3207ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans size_t h = buffer->getHeight(); 321609ae595f0358157b19311b0f9f9591db7cee705Jason Evans memset(bits, 0, w*h*4); 322609ae595f0358157b19311b0f9f9591db7cee705Jason Evans for (size_t y=0 ; y<kDebugData.height ; y++) { 3237ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans for (size_t x=0 ; x<kDebugData.width ; x++) { 324609ae595f0358157b19311b0f9f9591db7cee705Jason Evans bits[x] = (kDebugData.bits[y*kDebugData.width+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF; 3257ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans } 3267ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans bits += w; 3277de92767c20cb72c94609b9c78985526fb84a679Jason Evans } 328609ae595f0358157b19311b0f9f9591db7cee705Jason Evans buffer->unlock(); 3297ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans sReleasedTexImageBuffer = buffer; 3304f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans } 3317ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans return sReleasedTexImageBuffer; 332741fbc6ba4499da39dd7d0c067c859fa52f1023fJason Evans} 333741fbc6ba4499da39dd7d0c067c859fa52f1023fJason Evans 3347ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evansstatus_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item, 3354f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans nsecs_t presentWhen) { 3364f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen); 3374f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans if (err != NO_ERROR) { 3384f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans return err; 3394f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans } 34012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 3414f929aa94853ecd7da2791f462d1b972ee66db8eJason Evans // If item->mGraphicBuffer is not null, this buffer has not been acquired 34212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // before, so any prior EglImage created is using a stale buffer. This 3437ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans // replaces any old EglImage with a new one (using the new buffer). 3447ca0fdfb85b2a9fc7a112e158892c098e004385bJason Evans if (item->mGraphicBuffer != NULL) { 345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans int slot = item->mBuf; 346609ae595f0358157b19311b0f9f9591db7cee705Jason Evans mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer); 347609ae595f0358157b19311b0f9f9591db7cee705Jason Evans } 348609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 349609ae595f0358157b19311b0f9f9591db7cee705Jason Evans return NO_ERROR; 350609ae595f0358157b19311b0f9f9591db7cee705Jason Evans} 351609ae595f0358157b19311b0f9f9591db7cee705Jason Evans 352609ae595f0358157b19311b0f9f9591db7cee705Jason Evansstatus_t GLConsumer::releaseBufferLocked(int buf, 3534d434adb146375ad17f0d5e994ed5728d2942e3fJason Evans sp<GraphicBuffer> graphicBuffer, 354609ae595f0358157b19311b0f9f9591db7cee705Jason Evans EGLDisplay display, EGLSyncKHR eglFence) { 35512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // release the buffer if it hasn't already been discarded by the 356609ae595f0358157b19311b0f9f9591db7cee705Jason Evans // BufferQueue. This can happen, for example, when the producer of this 357609ae595f0358157b19311b0f9f9591db7cee705Jason Evans // buffer has reallocated the original buffer slot after this buffer 358609ae595f0358157b19311b0f9f9591db7cee705Jason Evans // was acquired. 35912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans status_t err = ConsumerBase::releaseBufferLocked( 36012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans buf, graphicBuffer, display, eglFence); 361e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR; 362e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return err; 363e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 364e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 365e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatus_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) 366e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 367e476f8a161d445211fd6e54fe370275196e66bcbJason Evans status_t err = NO_ERROR; 3687372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans 369b954bc5d3a65966df0ce7801cd6102542b5e894bJason Evans int buf = item.mBuf; 3707372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans 3717372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (!mAttached) { 372609ae595f0358157b19311b0f9f9591db7cee705Jason Evans ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL " 3737372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans "ES context"); 3747372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, 3757372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans mEglDisplay, EGL_NO_SYNC_KHR); 376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return INVALID_OPERATION; 37712141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 37812141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 37912141150fdbda57651a53ae2fe0edaea4891d814Jason Evans // Confirm state. 38012141150fdbda57651a53ae2fe0edaea4891d814Jason Evans err = checkAndUpdateEglStateLocked(); 38112141150fdbda57651a53ae2fe0edaea4891d814Jason Evans if (err != NO_ERROR) { 38212141150fdbda57651a53ae2fe0edaea4891d814Jason Evans releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, 38312141150fdbda57651a53ae2fe0edaea4891d814Jason Evans mEglDisplay, EGL_NO_SYNC_KHR); 38412141150fdbda57651a53ae2fe0edaea4891d814Jason Evans return err; 38512141150fdbda57651a53ae2fe0edaea4891d814Jason Evans } 38612141150fdbda57651a53ae2fe0edaea4891d814Jason Evans 387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans // Ensure we have a valid EglImageKHR for the slot, creating an EglImage 388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans // if nessessary, for the gralloc buffer currently in the slot in 389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans // ConsumerBase. 390a8f8d7540d66ddee7337db80c92890916e1063caJason Evans // We may have to do this even when item.mGraphicBuffer == NULL (which 391e476f8a161d445211fd6e54fe370275196e66bcbJason Evans // means the buffer was previously acquired). 392e476f8a161d445211fd6e54fe370275196e66bcbJason Evans err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop); 393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (err != NO_ERROR) { 3942dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", 395ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans mEglDisplay, buf); 396e476f8a161d445211fd6e54fe370275196e66bcbJason Evans releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, 397ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans mEglDisplay, EGL_NO_SYNC_KHR); 398e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return UNKNOWN_ERROR; 3997372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 4007372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans 4017372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans // Do whatever sync ops we need to do before releasing the old slot. 4027372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans err = syncForReleaseLocked(mEglDisplay); 4037372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (err != NO_ERROR) { 4044d434adb146375ad17f0d5e994ed5728d2942e3fJason Evans // Release the buffer we just acquired. It's not safe to 405e476f8a161d445211fd6e54fe370275196e66bcbJason Evans // release the old buffer, so instead we just drop the new frame. 406609ae595f0358157b19311b0f9f9591db7cee705Jason Evans // As we are still under lock since acquireBuffer, it is safe to 407609ae595f0358157b19311b0f9f9591db7cee705Jason Evans // release by slot. 408609ae595f0358157b19311b0f9f9591db7cee705Jason Evans releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, 409609ae595f0358157b19311b0f9f9591db7cee705Jason Evans mEglDisplay, EGL_NO_SYNC_KHR); 4107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans return err; 4117372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 412b980cc774a9ccb208a82f4e9ccdcc695d06a960aJason Evans 4137372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", 4147372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans mCurrentTexture, mCurrentTextureImage != NULL ? 4157372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans mCurrentTextureImage->graphicBufferHandle() : 0, 416e476f8a161d445211fd6e54fe370275196e66bcbJason Evans buf, mSlots[buf].mGraphicBuffer->handle); 417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 418e476f8a161d445211fd6e54fe370275196e66bcbJason Evans // release old buffer 41920f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { 42020f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans status_t status = releaseBufferLocked( 42120f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentTexture, mCurrentTextureImage->graphicBuffer(), 42220f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mEglDisplay, mEglSlots[mCurrentTexture].mEglFence); 42320f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans if (status < NO_ERROR) { 424f1c3da8b02489b7728d4275ac011336299eace62Jason Evans ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)", 42520f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans strerror(-status), status); 42620f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans err = status; 42720f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans // keep going, with error raised [?] 42820f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans } 42920f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans } 43020f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans 43120f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans // Update the GLConsumer state. 43220f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentTexture = buf; 43320f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentTextureImage = mEglSlots[buf].mEglImage; 43420f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentCrop = item.mCrop; 43520f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentTransform = item.mTransform; 43620f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentScalingMode = item.mScalingMode; 43720f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentTimestamp = item.mTimestamp; 43820f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentFence = item.mFence; 43920f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans mCurrentFrameNumber = item.mFrameNumber; 44020f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans 44120f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans computeCurrentTransformMatrixLocked(); 44220f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans 44320f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans return err; 44420f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans} 44520f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans 44620f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evansstatus_t GLConsumer::bindTextureImageLocked() { 44720f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans if (mEglDisplay == EGL_NO_DISPLAY) { 44820f1fc95adb35ea63dc61f47f2b0ffbd37d39f32Jason Evans ALOGE("bindTextureImage: invalid display"); 449 return INVALID_OPERATION; 450 } 451 452 GLint error; 453 while ((error = glGetError()) != GL_NO_ERROR) { 454 ST_LOGW("bindTextureImage: clearing GL error: %#04x", error); 455 } 456 457 glBindTexture(mTexTarget, mTexName); 458 if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && 459 mCurrentTextureImage == NULL) { 460 ST_LOGE("bindTextureImage: no currently-bound texture"); 461 return NO_INIT; 462 } 463 464 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, 465 mCurrentCrop); 466 if (err != NO_ERROR) { 467 ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d", 468 mEglDisplay, mCurrentTexture); 469 return UNKNOWN_ERROR; 470 } 471 mCurrentTextureImage->bindToTextureTarget(mTexTarget); 472 473 // In the rare case that the display is terminated and then initialized 474 // again, we can't detect that the display changed (it didn't), but the 475 // image is invalid. In this case, repeat the exact same steps while 476 // forcing the creation of a new image. 477 if ((error = glGetError()) != GL_NO_ERROR) { 478 glBindTexture(mTexTarget, mTexName); 479 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, 480 mCurrentCrop, 481 true); 482 if (err != NO_ERROR) { 483 ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d", 484 mEglDisplay, mCurrentTexture); 485 return UNKNOWN_ERROR; 486 } 487 mCurrentTextureImage->bindToTextureTarget(mTexTarget); 488 if ((error = glGetError()) != GL_NO_ERROR) { 489 ST_LOGE("bindTextureImage: error binding external image: %#04x", error); 490 return UNKNOWN_ERROR; 491 } 492 } 493 494 // Wait for the new buffer to be ready. 495 return doGLFenceWaitLocked(); 496} 497 498status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) { 499 EGLDisplay dpy = eglGetCurrentDisplay(); 500 EGLContext ctx = eglGetCurrentContext(); 501 502 if (!contextCheck) { 503 // if this is the first time we're called, mEglDisplay/mEglContext have 504 // never been set, so don't error out (below). 505 if (mEglDisplay == EGL_NO_DISPLAY) { 506 mEglDisplay = dpy; 507 } 508 if (mEglContext == EGL_NO_CONTEXT) { 509 mEglContext = ctx; 510 } 511 } 512 513 if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) { 514 ST_LOGE("checkAndUpdateEglState: invalid current EGLDisplay"); 515 return INVALID_OPERATION; 516 } 517 518 if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) { 519 ST_LOGE("checkAndUpdateEglState: invalid current EGLContext"); 520 return INVALID_OPERATION; 521 } 522 523 mEglDisplay = dpy; 524 mEglContext = ctx; 525 return NO_ERROR; 526} 527 528void GLConsumer::setReleaseFence(const sp<Fence>& fence) { 529 if (fence->isValid() && 530 mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { 531 status_t err = addReleaseFence(mCurrentTexture, 532 mCurrentTextureImage->graphicBuffer(), fence); 533 if (err != OK) { 534 ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)", 535 strerror(-err), err); 536 } 537 } 538} 539 540status_t GLConsumer::detachFromContext() { 541 ATRACE_CALL(); 542 ST_LOGV("detachFromContext"); 543 Mutex::Autolock lock(mMutex); 544 545 if (mAbandoned) { 546 ST_LOGE("detachFromContext: abandoned GLConsumer"); 547 return NO_INIT; 548 } 549 550 if (!mAttached) { 551 ST_LOGE("detachFromContext: GLConsumer is not attached to a " 552 "context"); 553 return INVALID_OPERATION; 554 } 555 556 EGLDisplay dpy = eglGetCurrentDisplay(); 557 EGLContext ctx = eglGetCurrentContext(); 558 559 if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) { 560 ST_LOGE("detachFromContext: invalid current EGLDisplay"); 561 return INVALID_OPERATION; 562 } 563 564 if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) { 565 ST_LOGE("detachFromContext: invalid current EGLContext"); 566 return INVALID_OPERATION; 567 } 568 569 if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) { 570 status_t err = syncForReleaseLocked(dpy); 571 if (err != OK) { 572 return err; 573 } 574 575 glDeleteTextures(1, &mTexName); 576 } 577 578 mEglDisplay = EGL_NO_DISPLAY; 579 mEglContext = EGL_NO_CONTEXT; 580 mAttached = false; 581 582 return OK; 583} 584 585status_t GLConsumer::attachToContext(uint32_t tex) { 586 ATRACE_CALL(); 587 ST_LOGV("attachToContext"); 588 Mutex::Autolock lock(mMutex); 589 590 if (mAbandoned) { 591 ST_LOGE("attachToContext: abandoned GLConsumer"); 592 return NO_INIT; 593 } 594 595 if (mAttached) { 596 ST_LOGE("attachToContext: GLConsumer is already attached to a " 597 "context"); 598 return INVALID_OPERATION; 599 } 600 601 EGLDisplay dpy = eglGetCurrentDisplay(); 602 EGLContext ctx = eglGetCurrentContext(); 603 604 if (dpy == EGL_NO_DISPLAY) { 605 ST_LOGE("attachToContext: invalid current EGLDisplay"); 606 return INVALID_OPERATION; 607 } 608 609 if (ctx == EGL_NO_CONTEXT) { 610 ST_LOGE("attachToContext: invalid current EGLContext"); 611 return INVALID_OPERATION; 612 } 613 614 // We need to bind the texture regardless of whether there's a current 615 // buffer. 616 glBindTexture(mTexTarget, GLuint(tex)); 617 618 mEglDisplay = dpy; 619 mEglContext = ctx; 620 mTexName = tex; 621 mAttached = true; 622 623 if (mCurrentTextureImage != NULL) { 624 // This may wait for a buffer a second time. This is likely required if 625 // this is a different context, since otherwise the wait could be skipped 626 // by bouncing through another context. For the same context the extra 627 // wait is redundant. 628 status_t err = bindTextureImageLocked(); 629 if (err != NO_ERROR) { 630 return err; 631 } 632 } 633 634 return OK; 635} 636 637 638status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { 639 ST_LOGV("syncForReleaseLocked"); 640 641 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { 642 if (SyncFeatures::getInstance().useNativeFenceSync()) { 643 EGLSyncKHR sync = eglCreateSyncKHR(dpy, 644 EGL_SYNC_NATIVE_FENCE_ANDROID, NULL); 645 if (sync == EGL_NO_SYNC_KHR) { 646 ST_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", 647 eglGetError()); 648 return UNKNOWN_ERROR; 649 } 650 glFlush(); 651 int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync); 652 eglDestroySyncKHR(dpy, sync); 653 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { 654 ST_LOGE("syncForReleaseLocked: error dup'ing native fence " 655 "fd: %#x", eglGetError()); 656 return UNKNOWN_ERROR; 657 } 658 sp<Fence> fence(new Fence(fenceFd)); 659 status_t err = addReleaseFenceLocked(mCurrentTexture, 660 mCurrentTextureImage->graphicBuffer(), fence); 661 if (err != OK) { 662 ST_LOGE("syncForReleaseLocked: error adding release fence: " 663 "%s (%d)", strerror(-err), err); 664 return err; 665 } 666 } else if (mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) { 667 EGLSyncKHR fence = mEglSlots[mCurrentTexture].mEglFence; 668 if (fence != EGL_NO_SYNC_KHR) { 669 // There is already a fence for the current slot. We need to 670 // wait on that before replacing it with another fence to 671 // ensure that all outstanding buffer accesses have completed 672 // before the producer accesses it. 673 EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000); 674 if (result == EGL_FALSE) { 675 ST_LOGE("syncForReleaseLocked: error waiting for previous " 676 "fence: %#x", eglGetError()); 677 return UNKNOWN_ERROR; 678 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 679 ST_LOGE("syncForReleaseLocked: timeout waiting for previous " 680 "fence"); 681 return TIMED_OUT; 682 } 683 eglDestroySyncKHR(dpy, fence); 684 } 685 686 // Create a fence for the outstanding accesses in the current 687 // OpenGL ES context. 688 fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 689 if (fence == EGL_NO_SYNC_KHR) { 690 ST_LOGE("syncForReleaseLocked: error creating fence: %#x", 691 eglGetError()); 692 return UNKNOWN_ERROR; 693 } 694 glFlush(); 695 mEglSlots[mCurrentTexture].mEglFence = fence; 696 } 697 } 698 699 return OK; 700} 701 702bool GLConsumer::isExternalFormat(uint32_t format) 703{ 704 switch (format) { 705 // supported YUV formats 706 case HAL_PIXEL_FORMAT_YV12: 707 // Legacy/deprecated YUV formats 708 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 709 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 710 case HAL_PIXEL_FORMAT_YCbCr_422_I: 711 return true; 712 } 713 714 // Any OEM format needs to be considered 715 if (format>=0x100 && format<=0x1FF) 716 return true; 717 718 return false; 719} 720 721uint32_t GLConsumer::getCurrentTextureTarget() const { 722 return mTexTarget; 723} 724 725void GLConsumer::getTransformMatrix(float mtx[16]) { 726 Mutex::Autolock lock(mMutex); 727 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix)); 728} 729 730void GLConsumer::setFilteringEnabled(bool enabled) { 731 Mutex::Autolock lock(mMutex); 732 if (mAbandoned) { 733 ST_LOGE("setFilteringEnabled: GLConsumer is abandoned!"); 734 return; 735 } 736 bool needsRecompute = mFilteringEnabled != enabled; 737 mFilteringEnabled = enabled; 738 739 if (needsRecompute && mCurrentTextureImage==NULL) { 740 ST_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL"); 741 } 742 743 if (needsRecompute && mCurrentTextureImage != NULL) { 744 computeCurrentTransformMatrixLocked(); 745 } 746} 747 748void GLConsumer::computeCurrentTransformMatrixLocked() { 749 ST_LOGV("computeCurrentTransformMatrixLocked"); 750 751 float xform[16]; 752 for (int i = 0; i < 16; i++) { 753 xform[i] = mtxIdentity[i]; 754 } 755 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { 756 float result[16]; 757 mtxMul(result, xform, mtxFlipH); 758 for (int i = 0; i < 16; i++) { 759 xform[i] = result[i]; 760 } 761 } 762 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { 763 float result[16]; 764 mtxMul(result, xform, mtxFlipV); 765 for (int i = 0; i < 16; i++) { 766 xform[i] = result[i]; 767 } 768 } 769 if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 770 float result[16]; 771 mtxMul(result, xform, mtxRot90); 772 for (int i = 0; i < 16; i++) { 773 xform[i] = result[i]; 774 } 775 } 776 777 sp<GraphicBuffer> buf = (mCurrentTextureImage == NULL) ? 778 NULL : mCurrentTextureImage->graphicBuffer(); 779 780 if (buf == NULL) { 781 ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL"); 782 } 783 784 float mtxBeforeFlipV[16]; 785 if (!isEglImageCroppable(mCurrentCrop)) { 786 Rect cropRect = mCurrentCrop; 787 float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f; 788 float bufferWidth = buf->getWidth(); 789 float bufferHeight = buf->getHeight(); 790 if (!cropRect.isEmpty()) { 791 float shrinkAmount = 0.0f; 792 if (mFilteringEnabled) { 793 // In order to prevent bilinear sampling beyond the edge of the 794 // crop rectangle we may need to shrink it by 2 texels in each 795 // dimension. Normally this would just need to take 1/2 a texel 796 // off each end, but because the chroma channels of YUV420 images 797 // are subsampled we may need to shrink the crop region by a whole 798 // texel on each side. 799 switch (buf->getPixelFormat()) { 800 case PIXEL_FORMAT_RGBA_8888: 801 case PIXEL_FORMAT_RGBX_8888: 802 case PIXEL_FORMAT_RGB_888: 803 case PIXEL_FORMAT_RGB_565: 804 case PIXEL_FORMAT_BGRA_8888: 805 // We know there's no subsampling of any channels, so we 806 // only need to shrink by a half a pixel. 807 shrinkAmount = 0.5; 808 break; 809 810 default: 811 // If we don't recognize the format, we must assume the 812 // worst case (that we care about), which is YUV420. 813 shrinkAmount = 1.0; 814 break; 815 } 816 } 817 818 // Only shrink the dimensions that are not the size of the buffer. 819 if (cropRect.width() < bufferWidth) { 820 tx = (float(cropRect.left) + shrinkAmount) / bufferWidth; 821 sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) / 822 bufferWidth; 823 } 824 if (cropRect.height() < bufferHeight) { 825 ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) / 826 bufferHeight; 827 sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) / 828 bufferHeight; 829 } 830 } 831 float crop[16] = { 832 sx, 0, 0, 0, 833 0, sy, 0, 0, 834 0, 0, 1, 0, 835 tx, ty, 0, 1, 836 }; 837 838 mtxMul(mtxBeforeFlipV, crop, xform); 839 } else { 840 for (int i = 0; i < 16; i++) { 841 mtxBeforeFlipV[i] = xform[i]; 842 } 843 } 844 845 // SurfaceFlinger expects the top of its window textures to be at a Y 846 // coordinate of 0, so GLConsumer must behave the same way. We don't 847 // want to expose this to applications, however, so we must add an 848 // additional vertical flip to the transform after all the other transforms. 849 mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV); 850} 851 852nsecs_t GLConsumer::getTimestamp() { 853 ST_LOGV("getTimestamp"); 854 Mutex::Autolock lock(mMutex); 855 return mCurrentTimestamp; 856} 857 858nsecs_t GLConsumer::getFrameNumber() { 859 ST_LOGV("getFrameNumber"); 860 Mutex::Autolock lock(mMutex); 861 return mCurrentFrameNumber; 862} 863 864sp<GraphicBuffer> GLConsumer::getCurrentBuffer() const { 865 Mutex::Autolock lock(mMutex); 866 return (mCurrentTextureImage == NULL) ? 867 NULL : mCurrentTextureImage->graphicBuffer(); 868} 869 870Rect GLConsumer::getCurrentCrop() const { 871 Mutex::Autolock lock(mMutex); 872 873 Rect outCrop = mCurrentCrop; 874 if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) { 875 int32_t newWidth = mCurrentCrop.width(); 876 int32_t newHeight = mCurrentCrop.height(); 877 878 if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) { 879 newWidth = newHeight * mDefaultWidth / mDefaultHeight; 880 ST_LOGV("too wide: newWidth = %d", newWidth); 881 } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) { 882 newHeight = newWidth * mDefaultHeight / mDefaultWidth; 883 ST_LOGV("too tall: newHeight = %d", newHeight); 884 } 885 886 // The crop is too wide 887 if (newWidth < mCurrentCrop.width()) { 888 int32_t dw = (newWidth - mCurrentCrop.width())/2; 889 outCrop.left -=dw; 890 outCrop.right += dw; 891 // The crop is too tall 892 } else if (newHeight < mCurrentCrop.height()) { 893 int32_t dh = (newHeight - mCurrentCrop.height())/2; 894 outCrop.top -= dh; 895 outCrop.bottom += dh; 896 } 897 898 ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]", 899 outCrop.left, outCrop.top, 900 outCrop.right,outCrop.bottom); 901 } 902 903 return outCrop; 904} 905 906uint32_t GLConsumer::getCurrentTransform() const { 907 Mutex::Autolock lock(mMutex); 908 return mCurrentTransform; 909} 910 911uint32_t GLConsumer::getCurrentScalingMode() const { 912 Mutex::Autolock lock(mMutex); 913 return mCurrentScalingMode; 914} 915 916sp<Fence> GLConsumer::getCurrentFence() const { 917 Mutex::Autolock lock(mMutex); 918 return mCurrentFence; 919} 920 921status_t GLConsumer::doGLFenceWait() const { 922 Mutex::Autolock lock(mMutex); 923 return doGLFenceWaitLocked(); 924} 925 926status_t GLConsumer::doGLFenceWaitLocked() const { 927 928 EGLDisplay dpy = eglGetCurrentDisplay(); 929 EGLContext ctx = eglGetCurrentContext(); 930 931 if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) { 932 ST_LOGE("doGLFenceWait: invalid current EGLDisplay"); 933 return INVALID_OPERATION; 934 } 935 936 if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) { 937 ST_LOGE("doGLFenceWait: invalid current EGLContext"); 938 return INVALID_OPERATION; 939 } 940 941 if (mCurrentFence->isValid()) { 942 if (SyncFeatures::getInstance().useWaitSync()) { 943 // Create an EGLSyncKHR from the current fence. 944 int fenceFd = mCurrentFence->dup(); 945 if (fenceFd == -1) { 946 ST_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno); 947 return -errno; 948 } 949 EGLint attribs[] = { 950 EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, 951 EGL_NONE 952 }; 953 EGLSyncKHR sync = eglCreateSyncKHR(dpy, 954 EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); 955 if (sync == EGL_NO_SYNC_KHR) { 956 close(fenceFd); 957 ST_LOGE("doGLFenceWait: error creating EGL fence: %#x", 958 eglGetError()); 959 return UNKNOWN_ERROR; 960 } 961 962 // XXX: The spec draft is inconsistent as to whether this should 963 // return an EGLint or void. Ignore the return value for now, as 964 // it's not strictly needed. 965 eglWaitSyncKHR(dpy, sync, 0); 966 EGLint eglErr = eglGetError(); 967 eglDestroySyncKHR(dpy, sync); 968 if (eglErr != EGL_SUCCESS) { 969 ST_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", 970 eglErr); 971 return UNKNOWN_ERROR; 972 } 973 } else { 974 status_t err = mCurrentFence->waitForever( 975 "GLConsumer::doGLFenceWaitLocked"); 976 if (err != NO_ERROR) { 977 ST_LOGE("doGLFenceWait: error waiting for fence: %d", err); 978 return err; 979 } 980 } 981 } 982 983 return NO_ERROR; 984} 985 986void GLConsumer::freeBufferLocked(int slotIndex) { 987 ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); 988 if (slotIndex == mCurrentTexture) { 989 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; 990 } 991 mEglSlots[slotIndex].mEglImage.clear(); 992 ConsumerBase::freeBufferLocked(slotIndex); 993} 994 995void GLConsumer::abandonLocked() { 996 ST_LOGV("abandonLocked"); 997 mCurrentTextureImage.clear(); 998 ConsumerBase::abandonLocked(); 999} 1000 1001void GLConsumer::setName(const String8& name) { 1002 Mutex::Autolock _l(mMutex); 1003 mName = name; 1004 mConsumer->setConsumerName(name); 1005} 1006 1007status_t GLConsumer::setDefaultBufferFormat(uint32_t defaultFormat) { 1008 Mutex::Autolock lock(mMutex); 1009 return mConsumer->setDefaultBufferFormat(defaultFormat); 1010} 1011 1012status_t GLConsumer::setConsumerUsageBits(uint32_t usage) { 1013 Mutex::Autolock lock(mMutex); 1014 usage |= DEFAULT_USAGE_FLAGS; 1015 return mConsumer->setConsumerUsageBits(usage); 1016} 1017 1018status_t GLConsumer::setTransformHint(uint32_t hint) { 1019 Mutex::Autolock lock(mMutex); 1020 return mConsumer->setTransformHint(hint); 1021} 1022 1023void GLConsumer::dumpLocked(String8& result, const char* prefix) const 1024{ 1025 result.appendFormat( 1026 "%smTexName=%d mCurrentTexture=%d\n" 1027 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n", 1028 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left, 1029 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom, 1030 mCurrentTransform); 1031 1032 ConsumerBase::dumpLocked(result, prefix); 1033} 1034 1035static void mtxMul(float out[16], const float a[16], const float b[16]) { 1036 out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; 1037 out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; 1038 out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; 1039 out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; 1040 1041 out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; 1042 out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; 1043 out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; 1044 out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; 1045 1046 out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; 1047 out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; 1048 out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; 1049 out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; 1050 1051 out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; 1052 out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; 1053 out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; 1054 out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; 1055} 1056 1057GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) : 1058 mGraphicBuffer(graphicBuffer), 1059 mEglImage(EGL_NO_IMAGE_KHR), 1060 mEglDisplay(EGL_NO_DISPLAY) { 1061} 1062 1063GLConsumer::EglImage::~EglImage() { 1064 if (mEglImage != EGL_NO_IMAGE_KHR) { 1065 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { 1066 ALOGE("~EglImage: eglDestroyImageKHR failed"); 1067 } 1068 eglTerminate(mEglDisplay); 1069 } 1070} 1071 1072status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, 1073 const Rect& cropRect, 1074 bool forceCreation) { 1075 // If there's an image and it's no longer valid, destroy it. 1076 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR; 1077 bool displayInvalid = mEglDisplay != eglDisplay; 1078 bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect; 1079 if (haveImage && (displayInvalid || cropInvalid || forceCreation)) { 1080 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { 1081 ALOGE("createIfNeeded: eglDestroyImageKHR failed"); 1082 } 1083 eglTerminate(mEglDisplay); 1084 mEglImage = EGL_NO_IMAGE_KHR; 1085 mEglDisplay = EGL_NO_DISPLAY; 1086 } 1087 1088 // If there's no image, create one. 1089 if (mEglImage == EGL_NO_IMAGE_KHR) { 1090 mEglDisplay = eglDisplay; 1091 mCropRect = cropRect; 1092 mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect); 1093 } 1094 1095 // Fail if we can't create a valid image. 1096 if (mEglImage == EGL_NO_IMAGE_KHR) { 1097 mEglDisplay = EGL_NO_DISPLAY; 1098 mCropRect.makeInvalid(); 1099 const sp<GraphicBuffer>& buffer = mGraphicBuffer; 1100 ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d", 1101 buffer->getWidth(), buffer->getHeight(), buffer->getStride(), 1102 buffer->getUsage(), buffer->getPixelFormat()); 1103 return UNKNOWN_ERROR; 1104 } 1105 1106 return OK; 1107} 1108 1109void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) { 1110 glEGLImageTargetTexture2DOES(texTarget, (GLeglImageOES)mEglImage); 1111} 1112 1113EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy, 1114 const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) { 1115 EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); 1116 EGLint attrs[] = { 1117 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 1118 EGL_IMAGE_CROP_LEFT_ANDROID, crop.left, 1119 EGL_IMAGE_CROP_TOP_ANDROID, crop.top, 1120 EGL_IMAGE_CROP_RIGHT_ANDROID, crop.right, 1121 EGL_IMAGE_CROP_BOTTOM_ANDROID, crop.bottom, 1122 EGL_NONE, 1123 }; 1124 if (!crop.isValid()) { 1125 // No crop rect to set, so terminate the attrib array before the crop. 1126 attrs[2] = EGL_NONE; 1127 } else if (!isEglImageCroppable(crop)) { 1128 // The crop rect is not at the origin, so we can't set the crop on the 1129 // EGLImage because that's not allowed by the EGL_ANDROID_image_crop 1130 // extension. In the future we can add a layered extension that 1131 // removes this restriction if there is hardware that can support it. 1132 attrs[2] = EGL_NONE; 1133 } 1134 eglInitialize(dpy, 0, 0); 1135 EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, 1136 EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); 1137 if (image == EGL_NO_IMAGE_KHR) { 1138 EGLint error = eglGetError(); 1139 ALOGE("error creating EGLImage: %#x", error); 1140 eglTerminate(dpy); 1141 } 1142 return image; 1143} 1144 1145}; // namespace android 1146