From 9575f60722f7a4f54384fe0be6938a8de48dc23a Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Fri, 7 Oct 2011 14:51:16 -0700 Subject: [PATCH] SurfaceFlinger: screenshots w/ protected buffers This change modifies SurfaceFlinger's screenshot behavior when a layer with a protected buffer is visible. The previous behavior was to simply fail the screenshot. The new behavior is to render the screenshot using a placeholder texture where the protected buffer would have been. Change-Id: I5e50cb2f3b31b2ea81cfe291c9b4a42e9ee71874 --- services/surfaceflinger/Layer.cpp | 33 ++++++++++++++-------- services/surfaceflinger/SurfaceFlinger.cpp | 32 +++++++++------------ services/surfaceflinger/SurfaceFlinger.h | 3 ++ 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 41d7a9097..feb2c5272 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -280,20 +280,29 @@ void Layer::onDraw(const Region& clip) const return; } - const GLenum target = GL_TEXTURE_EXTERNAL_OES; - glBindTexture(target, mTextureName); - if (getFiltering() || needsFiltering() || isFixedSize() || isCropped()) { - // TODO: we could be more subtle with isFixedSize() - glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + GLenum target = GL_TEXTURE_EXTERNAL_OES; + if (!isProtected()) { + glBindTexture(target, mTextureName); + if (getFiltering() || needsFiltering() || isFixedSize() || isCropped()) { + // TODO: we could be more subtle with isFixedSize() + glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + glEnable(target); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(mTextureMatrix); + glMatrixMode(GL_MODELVIEW); } else { - glTexParameterx(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + target = GL_TEXTURE_2D; + glBindTexture(target, mFlinger->getProtectedTexName()); + glEnable(target); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); } - glEnable(target); - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(mTextureMatrix); - glMatrixMode(GL_MODELVIEW); drawWithOpenGL(clip); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3f154ce32..b01a6a34d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -275,7 +275,7 @@ status_t SurfaceFlinger::readyToRun() const uint16_t g0 = pack565(0x0F,0x1F,0x0F); const uint16_t g1 = pack565(0x17,0x2f,0x17); - const uint16_t textureData[4] = { g0, g1, g1, g0 }; + const uint16_t wormholeTexData[4] = { g0, g1, g1, g0 }; glGenTextures(1, &mWormholeTexName); glBindTexture(GL_TEXTURE_2D, mWormholeTexName); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -283,7 +283,17 @@ status_t SurfaceFlinger::readyToRun() glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData); + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, wormholeTexData); + + const uint16_t protTexData[] = { pack565(0x03, 0x03, 0x03) }; + glGenTextures(1, &mProtectedTexName); + glBindTexture(GL_TEXTURE_2D, mProtectedTexName); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); @@ -2255,22 +2265,6 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT)) return BAD_VALUE; - // make sure none of the layers are protected - const LayerVector& layers(mDrawingState.layersSortedByZ); - const size_t count = layers.size(); - for (size_t i=0 ; i& layer(layers[i]); - const uint32_t flags = layer->drawingState().flags; - if (!(flags & ISurfaceComposer::eLayerHidden)) { - const uint32_t z = layer->drawingState().z; - if (z >= minLayerZ && z <= maxLayerZ) { - if (layer->isProtected()) { - return INVALID_OPERATION; - } - } - } - } - if (!GLExtensions::getInstance().haveFramebufferObject()) return INVALID_OPERATION; @@ -2320,6 +2314,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); + const LayerVector& layers(mDrawingState.layersSortedByZ); + const size_t count = layers.size(); for (size_t i=0 ; i& layer(layers[i]); const uint32_t flags = layer->drawingState().flags; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 128a64dbd..92b265ec8 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -192,6 +192,8 @@ public: sp getLayer(const sp& sur) const; + GLuint getProtectedTexName() const { return mProtectedTexName; } + private: // DeathRecipient interface virtual void binderDied(const wp& who); @@ -349,6 +351,7 @@ private: sp mServerHeap; surface_flinger_cblk_t* mServerCblk; GLuint mWormholeTexName; + GLuint mProtectedTexName; nsecs_t mBootTime; // Can only accessed from the main thread, these members