diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 800137bdf..0d0f98d89 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -53,6 +53,7 @@ DisplayDevice::DisplayDevice( const sp& flinger, DisplayType type, int32_t hwcId, + int format, bool isSecure, const wp& displayToken, const sp& displaySurface, @@ -76,9 +77,6 @@ DisplayDevice::DisplayDevice( mNativeWindow = new Surface(producer, false); ANativeWindow* const window = mNativeWindow.get(); - int format; - window->query(window, NATIVE_WINDOW_FORMAT, &format); - // Make sure that composition can never be stalled by a virtual display // consumer that isn't processing buffers fast enough. We have to do this // in two places: @@ -96,6 +94,9 @@ DisplayDevice::DisplayDevice( EGLSurface surface; EGLint w, h; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (config == EGL_NO_CONFIG) { + config = RenderEngine::chooseEglConfig(display, format); + } surface = eglCreateWindowSurface(display, config, window, NULL); eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth); eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index c3abe89d6..01a9d2efc 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -75,6 +75,7 @@ public: const sp& flinger, DisplayType type, int32_t hwcId, // negative for non-HWC-composited displays + int format, bool isSecure, const wp& displayToken, const sp& displaySurface, diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 642702fae..474f63342 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -454,7 +454,11 @@ uint32_t HWComposer::getHeight(int disp) const { } uint32_t HWComposer::getFormat(int disp) const { - return mDisplayData[disp].format; + if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) { + return HAL_PIXEL_FORMAT_RGBA_8888; + } else { + return mDisplayData[disp].format; + } } float HWComposer::getDpiX(int disp) const { @@ -1146,7 +1150,7 @@ bool HWComposer::VSyncThread::threadLoop() { } HWComposer::DisplayData::DisplayData() -: width(0), height(0), format(0), +: width(0), height(0), format(HAL_PIXEL_FORMAT_RGBA_8888), xdpi(0.0f), ydpi(0.0f), refresh(0), connected(false), diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index 759839b9e..2871ce996 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -25,21 +25,51 @@ #include "GLExtensions.h" #include "Mesh.h" +EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); + // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- -RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { - EGLConfig config = chooseEglConfig(display, hwcFormat); +static bool findExtension(const char* exts, const char* name) { + if (!exts) + return false; + size_t len = strlen(name); - EGLint renderableType = 0; - EGLint contextClientVersion = 0; - - // query the renderable type, setting the EGL_CONTEXT_CLIENT_VERSION accordingly - if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) { - LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE"); + const char* pos = exts; + while ((pos = strstr(pos, name)) != NULL) { + if (pos[len] == '\0' || pos[len] == ' ') + return true; + pos += len; } + return false; +} + +RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { + // EGL_ANDROIDX_no_config_context is an experimental extension with no + // written specification. It will be replaced by something more formal. + // SurfaceFlinger is using it to allow a single EGLContext to render to + // both a 16-bit primary display framebuffer and a 32-bit virtual display + // framebuffer. + // + // The code assumes that ES2 or later is available if this extension is + // supported. + EGLConfig config = EGL_NO_CONFIG; + if (!findExtension( + eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS), + "EGL_ANDROIDX_no_config_context")) { + config = chooseEglConfig(display, hwcFormat); + } + + EGLint renderableType = 0; + if (config == EGL_NO_CONFIG) { + renderableType = EGL_OPENGL_ES2_BIT; + } else if (!eglGetConfigAttrib(display, config, + EGL_RENDERABLE_TYPE, &renderableType)) { + LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE"); + } + EGLint contextClientVersion = 0; if (renderableType & EGL_OPENGL_ES2_BIT) { contextClientVersion = 2; } else if (renderableType & EGL_OPENGL_ES_BIT) { @@ -68,8 +98,12 @@ RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { // now figure out what version of GL did we actually get // NOTE: a dummy surface is not needed if KHR_create_context is supported + EGLConfig dummyConfig = config; + if (dummyConfig == EGL_NO_CONFIG) { + dummyConfig = chooseEglConfig(display, hwcFormat); + } EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE }; - EGLSurface dummy = eglCreatePbufferSurface(display, config, attribs); + EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs); LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer"); EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt); LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current"); diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 4dc94575d..577dc0aa8 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -25,6 +25,8 @@ #include #include +#define EGL_NO_CONFIG ((EGLConfig)0) + // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b8fc599e8..af3185237 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -421,8 +421,9 @@ void SurfaceFlinger::init() { sp bq = new BufferQueue(new GraphicBufferAlloc()); sp fbs = new FramebufferSurface(*mHwc, i, bq); + int32_t hwcId = allocateHwcDisplayId(type); sp hw = new DisplayDevice(this, - type, allocateHwcDisplayId(type), isSecure, token, + type, hwcId, mHwc->getFormat(hwcId), isSecure, token, fbs, bq, mRenderEngine->getEGLConfig()); if (i > DisplayDevice::DISPLAY_PRIMARY) { @@ -1186,7 +1187,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const wp& display(curr.keyAt(i)); if (dispSurface != NULL) { sp hw = new DisplayDevice(this, - state.type, hwcDisplayId, state.isSecure, + state.type, hwcDisplayId, + mHwc->getFormat(hwcDisplayId), state.isSecure, display, dispSurface, producer, mRenderEngine->getEGLConfig()); hw->setLayerStack(state.layerStack);