From 05f8c703d4a050669ff8f406be3a9dc2357935f7 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Mon, 23 Dec 2013 20:44:38 -0800 Subject: [PATCH] Move EGLConfig selection to RenderEngine Bug: 12230666 Change-Id: I8d1111a7e0fd9d9e2525e6a80da8ce46d7dd085d Signed-off-by: Jesse Hall --- .../RenderEngine/RenderEngine.cpp | 171 +++++++++++++++++- .../RenderEngine/RenderEngine.h | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 170 +---------------- services/surfaceflinger/SurfaceFlinger.h | 6 - 4 files changed, 178 insertions(+), 177 deletions(-) diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index ba82cadb0..759839b9e 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -29,7 +29,9 @@ namespace android { // --------------------------------------------------------------------------- -RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { +RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { + EGLConfig config = chooseEglConfig(display, hwcFormat); + EGLint renderableType = 0; EGLint contextClientVersion = 0; @@ -96,7 +98,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { engine = new GLES20RenderEngine(); break; } - engine->setEGLContext(ctxt); + engine->setEGLHandles(config, ctxt); ALOGI("OpenGL ES informations:"); ALOGI("vendor : %s", extensions.getVendor()); @@ -118,10 +120,15 @@ RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) { RenderEngine::~RenderEngine() { } -void RenderEngine::setEGLContext(EGLContext ctxt) { +void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) { + mEGLConfig = config; mEGLContext = ctxt; } +EGLContext RenderEngine::getEGLConfig() const { + return mEGLConfig; +} + EGLContext RenderEngine::getEGLContext() const { return mEGLContext; } @@ -234,6 +241,164 @@ status_t RenderEngine::BindImageAsFramebuffer::getStatus() const { return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; } +// --------------------------------------------------------------------------- + +static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, + EGLint attribute, EGLint wanted, EGLConfig* outConfig) { + EGLConfig config = NULL; + EGLint numConfigs = -1, n = 0; + eglGetConfigs(dpy, NULL, 0, &numConfigs); + EGLConfig* const configs = new EGLConfig[numConfigs]; + eglChooseConfig(dpy, attrs, configs, numConfigs, &n); + + if (n) { + if (attribute != EGL_NONE) { + for (int i=0 ; i mList; + struct Attribute { + Attribute() {}; + Attribute(EGLint v) : v(v) { } + EGLint v; + bool operator < (const Attribute& other) const { + // this places EGL_NONE at the end + EGLint lhs(v); + EGLint rhs(other.v); + if (lhs == EGL_NONE) lhs = 0x7FFFFFFF; + if (rhs == EGL_NONE) rhs = 0x7FFFFFFF; + return lhs < rhs; + } + }; + class Adder { + friend class EGLAttributeVector; + EGLAttributeVector& v; + EGLint attribute; + Adder(EGLAttributeVector& v, EGLint attribute) + : v(v), attribute(attribute) { + } + public: + void operator = (EGLint value) { + if (attribute != EGL_NONE) { + v.mList.add(attribute, value); + } + } + operator EGLint () const { return v.mList[attribute]; } + }; +public: + EGLAttributeVector() { + mList.add(EGL_NONE, EGL_NONE); + } + void remove(EGLint attribute) { + if (attribute != EGL_NONE) { + mList.removeItem(attribute); + } + } + Adder operator [] (EGLint attribute) { + return Adder(*this, attribute); + } + EGLint operator [] (EGLint attribute) const { + return mList[attribute]; + } + // cast-operator to (EGLint const*) + operator EGLint const* () const { return &mList.keyAt(0).v; } +}; + + +static status_t selectEGLConfig(EGLDisplay display, EGLint format, + EGLint renderableType, EGLConfig* config) { + // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if + // it is to be used with WIFI displays + status_t err; + EGLint wantedAttribute; + EGLint wantedAttributeValue; + + EGLAttributeVector attribs; + if (renderableType) { + attribs[EGL_RENDERABLE_TYPE] = renderableType; + attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; + attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT|EGL_PBUFFER_BIT; + attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE; + attribs[EGL_RED_SIZE] = 8; + attribs[EGL_GREEN_SIZE] = 8; + attribs[EGL_BLUE_SIZE] = 8; + wantedAttribute = EGL_NONE; + wantedAttributeValue = EGL_NONE; + } else { + // if no renderable type specified, fallback to a simplified query + wantedAttribute = EGL_NATIVE_VISUAL_ID; + wantedAttributeValue = format; + } + + err = selectConfigForAttribute(display, attribs, + wantedAttribute, wantedAttributeValue, config); + if (err == NO_ERROR) { + EGLint caveat; + if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat)) + ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!"); + } + + return err; +} + +EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) { + status_t err; + EGLConfig config; + + // First try to get an ES2 config + err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config); + if (err != NO_ERROR) { + // If ES2 fails, try ES1 + err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config); + if (err != NO_ERROR) { + // still didn't work, probably because we're on the emulator... + // try a simplified query + ALOGW("no suitable EGLConfig found, trying a simpler query"); + err = selectEGLConfig(display, format, 0, &config); + if (err != NO_ERROR) { + // this EGL is too lame for android + LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); + } + } + } + + // print some debugging info + EGLint r,g,b,a; + eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); + eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a); + ALOGI("EGL information:"); + ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); + ALOGI("version : %s", eglQueryString(display, EGL_VERSION)); + ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS)); + ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); + ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config); + + return config; +} + // --------------------------------------------------------------------------- }; // namespace android // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 3c7f9ab09..4dc94575d 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -44,8 +44,9 @@ class RenderEngine { }; static GlesVersion parseGlesVersion(const char* str); + EGLConfig mEGLConfig; EGLContext mEGLContext; - void setEGLContext(EGLContext ctxt); + void setEGLHandles(EGLConfig config, EGLContext ctxt); virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName, uint32_t* status) = 0; virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0; @@ -55,7 +56,9 @@ protected: virtual ~RenderEngine() = 0; public: - static RenderEngine* create(EGLDisplay display, EGLConfig config); + static RenderEngine* create(EGLDisplay display, int hwcFormat); + + static EGLConfig chooseEglConfig(EGLDisplay display, int format); // dump the extension strings. always call the base class. virtual void dump(String8& result); @@ -107,6 +110,7 @@ public: virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxViewportDims() const = 0; + EGLConfig getEGLConfig() const; EGLContext getEGLContext() const; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9d94c874f..ec643906b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -318,128 +318,6 @@ void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture)); } -status_t SurfaceFlinger::selectConfigForAttribute( - EGLDisplay dpy, - EGLint const* attrs, - EGLint attribute, EGLint wanted, - EGLConfig* outConfig) -{ - EGLConfig config = NULL; - EGLint numConfigs = -1, n=0; - eglGetConfigs(dpy, NULL, 0, &numConfigs); - EGLConfig* const configs = new EGLConfig[numConfigs]; - eglChooseConfig(dpy, attrs, configs, numConfigs, &n); - - if (n) { - if (attribute != EGL_NONE) { - for (int i=0 ; i mList; - struct Attribute { - Attribute() {}; - Attribute(EGLint v) : v(v) { } - EGLint v; - bool operator < (const Attribute& other) const { - // this places EGL_NONE at the end - EGLint lhs(v); - EGLint rhs(other.v); - if (lhs == EGL_NONE) lhs = 0x7FFFFFFF; - if (rhs == EGL_NONE) rhs = 0x7FFFFFFF; - return lhs < rhs; - } - }; - class Adder { - friend class EGLAttributeVector; - EGLAttributeVector& v; - EGLint attribute; - Adder(EGLAttributeVector& v, EGLint attribute) - : v(v), attribute(attribute) { - } - public: - void operator = (EGLint value) { - if (attribute != EGL_NONE) { - v.mList.add(attribute, value); - } - } - operator EGLint () const { return v.mList[attribute]; } - }; -public: - EGLAttributeVector() { - mList.add(EGL_NONE, EGL_NONE); - } - void remove(EGLint attribute) { - if (attribute != EGL_NONE) { - mList.removeItem(attribute); - } - } - Adder operator [] (EGLint attribute) { - return Adder(*this, attribute); - } - EGLint operator [] (EGLint attribute) const { - return mList[attribute]; - } - // cast-operator to (EGLint const*) - operator EGLint const* () const { return &mList.keyAt(0).v; } -}; - -status_t SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisualId, - EGLint renderableType, EGLConfig* config) { - // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if - // it is to be used with WIFI displays - status_t err; - EGLint wantedAttribute; - EGLint wantedAttributeValue; - - EGLAttributeVector attribs; - if (renderableType) { - attribs[EGL_RENDERABLE_TYPE] = renderableType; - attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; - attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT|EGL_PBUFFER_BIT; - attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE; - attribs[EGL_RED_SIZE] = 8; - attribs[EGL_GREEN_SIZE] = 8; - attribs[EGL_BLUE_SIZE] = 8; - wantedAttribute = EGL_NONE; - wantedAttributeValue = EGL_NONE; - - } else { - // if no renderable type specified, fallback to a simplified query - wantedAttribute = EGL_NATIVE_VISUAL_ID; - wantedAttributeValue = nativeVisualId; - } - - err = selectConfigForAttribute(display, attribs, wantedAttribute, - wantedAttributeValue, config); - if (err == NO_ERROR) { - EGLint caveat; - if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat)) - ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!"); - } - return err; -} - class DispSyncSource : public VSyncSource, private DispSync::Callback { public: DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync) : @@ -521,51 +399,12 @@ void SurfaceFlinger::init() { mHwc = new HWComposer(this, *static_cast(this)); - // First try to get an ES2 config - err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT, - &mEGLConfig); - - if (err != NO_ERROR) { - // If ES2 fails, try ES1 - err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), - EGL_OPENGL_ES_BIT, &mEGLConfig); - } - - if (err != NO_ERROR) { - // still didn't work, probably because we're on the emulator... - // try a simplified query - ALOGW("no suitable EGLConfig found, trying a simpler query"); - err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig); - } - - if (err != NO_ERROR) { - // this EGL is too lame for android - LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); - } - - // print some debugging info - EGLint r,g,b,a; - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE, &r); - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g); - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE, &b); - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a); - ALOGI("EGL informations:"); - ALOGI("vendor : %s", eglQueryString(mEGLDisplay, EGL_VENDOR)); - ALOGI("version : %s", eglQueryString(mEGLDisplay, EGL_VERSION)); - ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS)); - ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported"); - ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig); - // get a RenderEngine for the given display / config (can't fail) - mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig); + mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID()); // retrieve the EGL context that was selected/created mEGLContext = mRenderEngine->getEGLContext(); - // figure out which format we got - eglGetConfigAttrib(mEGLDisplay, mEGLConfig, - EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId); - LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT, "couldn't create EGLContext"); @@ -584,7 +423,7 @@ void SurfaceFlinger::init() { sp hw = new DisplayDevice(this, type, allocateHwcDisplayId(type), isSecure, token, fbs, bq, - mEGLConfig); + mRenderEngine->getEGLConfig()); if (i > DisplayDevice::DISPLAY_PRIMARY) { // FIXME: currently we don't get blank/unblank requests // for displays other than the main display, so we always @@ -1347,7 +1186,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (dispSurface != NULL) { sp hw = new DisplayDevice(this, state.type, hwcDisplayId, state.isSecure, - display, dispSurface, producer, mEGLConfig); + display, dispSurface, producer, + mRenderEngine->getEGLConfig()); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); @@ -2544,7 +2384,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, " refresh-rate : %f fps\n" " x-dpi : %f\n" " y-dpi : %f\n" - " EGL_NATIVE_VISUAL_ID : %d\n" " gpu_to_cpu_unsupported : %d\n" , mLastSwapBufferTime/1000.0, @@ -2553,7 +2392,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector& args, size_t& index, 1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY), hwc.getDpiX(HWC_DISPLAY_PRIMARY), hwc.getDpiY(HWC_DISPLAY_PRIMARY), - mEGLNativeVisualId, !mGpuToCpuSupported); result.appendFormat(" eglSwapBuffers time: %f us\n", diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f08e66abc..80bb619d6 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -317,10 +317,6 @@ private: /* ------------------------------------------------------------------------ * EGL */ - static status_t selectConfigForAttribute(EGLDisplay dpy, - EGLint const* attrs, EGLint attribute, EGLint value, EGLConfig* outConfig); - static status_t selectEGLConfig(EGLDisplay disp, EGLint visualId, - EGLint renderableType, EGLConfig* config); size_t getMaxTextureSize() const; size_t getMaxViewportDims() const; @@ -431,9 +427,7 @@ private: sp mSFEventThread; sp mEventControlThread; EGLContext mEGLContext; - EGLConfig mEGLConfig; EGLDisplay mEGLDisplay; - EGLint mEGLNativeVisualId; sp mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; // Can only accessed from the main thread, these members