diff options
19 files changed, 193 insertions, 61 deletions
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 1395551642..53b0e4cf20 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -242,23 +242,43 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32 bool useContextPriority = extensions.hasContextPriority() && (featureFlags & RenderEngine::USE_HIGH_PRIORITY_CONTEXT); - EGLContext ctxt = createEglContext(display, config, EGL_NO_CONTEXT, useContextPriority); + EGLContext protectedContext = EGL_NO_CONTEXT; + if (extensions.hasProtectedContent()) { + protectedContext = createEglContext(display, config, nullptr, useContextPriority, + Protection::PROTECTED); + ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context"); + } + + EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority, + Protection::UNPROTECTED); // if can't create a GL context, we can only abort. LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed"); EGLSurface dummy = EGL_NO_SURFACE; if (!extensions.hasSurfacelessContext()) { - dummy = createDummyEglPbufferSurface(display, config, hwcFormat); + dummy = createDummyEglPbufferSurface(display, config, hwcFormat, Protection::UNPROTECTED); 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"); - extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER), glGetString(GL_VERSION), glGetString(GL_EXTENSIONS)); + // In order to have protected contents in GPU composition, the OpenGL ES extension + // GL_EXT_protected_textures must be supported. If it's not supported, reset + // protected context to EGL_NO_CONTEXT to indicate that protected contents is not supported. + if (!extensions.hasProtectedTexture()) { + protectedContext = EGL_NO_CONTEXT; + } + + EGLSurface protectedDummy = EGL_NO_SURFACE; + if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) { + protectedDummy = + createDummyEglPbufferSurface(display, config, hwcFormat, Protection::PROTECTED); + ALOGE_IF(protectedDummy == EGL_NO_SURFACE, "can't create protected dummy pbuffer"); + } + // now figure out what version of GL did we actually get GlesVersion version = parseGlesVersion(extensions.getVersion()); @@ -271,7 +291,8 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32 break; case GLES_VERSION_2_0: case GLES_VERSION_3_0: - engine = std::make_unique<GLESRenderEngine>(featureFlags, display, config, ctxt, dummy); + engine = std::make_unique<GLESRenderEngine>(featureFlags, display, config, ctxt, dummy, + protectedContext, protectedDummy); break; } @@ -326,12 +347,15 @@ EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool } GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config, - EGLContext ctxt, EGLSurface dummy) + EGLContext ctxt, EGLSurface dummy, EGLContext protectedContext, + EGLSurface protectedDummy) : renderengine::impl::RenderEngine(featureFlags), mEGLDisplay(display), mEGLConfig(config), mEGLContext(ctxt), mDummySurface(dummy), + mProtectedEGLContext(protectedContext), + mProtectedDummySurface(protectedDummy), mVpWidth(0), mVpHeight(0), mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) { @@ -341,6 +365,17 @@ GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EG glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_PACK_ALIGNMENT, 4); + // Initialize protected EGL Context. + if (mProtectedEGLContext != EGL_NO_CONTEXT) { + EGLBoolean success = eglMakeCurrent(display, mProtectedDummySurface, mProtectedDummySurface, + mProtectedEGLContext); + ALOGE_IF(!success, "can't make protected context current"); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + success = eglMakeCurrent(display, mDummySurface, mDummySurface, mEGLContext); + LOG_ALWAYS_FATAL_IF(!success, "can't make default context current"); + } + const uint16_t protTexData[] = {0}; glGenTextures(1, &mProtectedTexName); glBindTexture(GL_TEXTURE_2D, mProtectedTexName); @@ -395,7 +430,8 @@ std::unique_ptr<Image> GLESRenderEngine::createImage() { } void GLESRenderEngine::primeCache() const { - ProgramCache::getInstance().primeCache(mFeatureFlags & USE_COLOR_MANAGEMENT); + ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext, + mFeatureFlags & USE_COLOR_MANAGEMENT); } bool GLESRenderEngine::isCurrent() const { @@ -539,6 +575,10 @@ void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& i const GLenum target = GL_TEXTURE_EXTERNAL_OES; glBindTexture(target, texName); + if (supportsProtectedContent()) { + glTexParameteri(target, GL_TEXTURE_PROTECTED_EXT, + glImage.isProtected() ? GL_TRUE : GL_FALSE); + } if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) { glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage())); } @@ -552,6 +592,10 @@ status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) { // Bind the texture and turn our EGLImage into a texture glBindTexture(GL_TEXTURE_2D, textureName); + if (supportsProtectedContent()) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_PROTECTED_EXT, + mInProtectedContext ? GL_TRUE : GL_FALSE); + } glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage); // Bind the Framebuffer to render into @@ -584,6 +628,26 @@ void GLESRenderEngine::checkErrors() const { } while (true); } +bool GLESRenderEngine::supportsProtectedContent() const { + return mProtectedEGLContext != EGL_NO_CONTEXT; +} + +bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) { + if (useProtectedContext == mInProtectedContext) { + return true; + } + if (useProtectedContext && mProtectedEGLContext == EGL_NO_CONTEXT) { + return false; + } + const EGLSurface surface = useProtectedContext ? mProtectedDummySurface : mDummySurface; + const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext; + const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE; + if (success) { + mInProtectedContext = useProtectedContext; + } + return success; +} + status_t GLESRenderEngine::drawLayers(const DisplaySettings& /*settings*/, const std::vector<LayerSettings>& /*layers*/, ANativeWindowBuffer* const /*buffer*/, @@ -822,7 +886,9 @@ void GLESRenderEngine::drawMesh(const Mesh& mesh) { Description::dataSpaceToTransferFunction(outputTransfer); } - ProgramCache::getInstance().useProgram(managedState); + ProgramCache::getInstance().useProgram(mInProtectedContext ? mProtectedEGLContext + : mEGLContext, + managedState); glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); @@ -833,7 +899,9 @@ void GLESRenderEngine::drawMesh(const Mesh& mesh) { writePPM(out.str().c_str(), mVpWidth, mVpHeight); } } else { - ProgramCache::getInstance().useProgram(mState); + ProgramCache::getInstance().useProgram(mInProtectedContext ? mProtectedEGLContext + : mEGLContext, + mState); glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount()); } @@ -857,17 +925,18 @@ size_t GLESRenderEngine::getMaxViewportDims() const { void GLESRenderEngine::dump(std::string& result) { const GLExtensions& extensions = GLExtensions::getInstance(); + ProgramCache& cache = ProgramCache::getInstance(); StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion()); StringAppendF(&result, "%s\n", extensions.getEGLExtensions()); - StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(), extensions.getVersion()); StringAppendF(&result, "%s\n", extensions.getExtensions()); - - StringAppendF(&result, "RenderEngine program cache size: %zu\n", - ProgramCache::getInstance().getSize()); - + StringAppendF(&result, "RenderEngine is in protected context : %d\n", mInProtectedContext); + StringAppendF(&result, "RenderEngine program cache size for unprotected context: %zu\n", + cache.getSize(mEGLContext)); + StringAppendF(&result, "RenderEngine program cache size for protected context: %zu\n", + cache.getSize(mProtectedEGLContext)); StringAppendF(&result, "RenderEngine last dataspace conversion: (%s) to (%s)\n", dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(), dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str()); @@ -892,7 +961,8 @@ GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str } EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig config, - EGLContext shareContext, bool useContextPriority) { + EGLContext shareContext, bool useContextPriority, + Protection protection) { EGLint renderableType = 0; if (config == EGL_NO_CONFIG) { renderableType = EGL_OPENGL_ES3_BIT; @@ -911,13 +981,17 @@ EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig conf } std::vector<EGLint> contextAttributes; - contextAttributes.reserve(5); + contextAttributes.reserve(7); contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION); contextAttributes.push_back(contextClientVersion); if (useContextPriority) { contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG); contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG); } + if (protection == Protection::PROTECTED) { + contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT); + contextAttributes.push_back(EGL_TRUE); + } contextAttributes.push_back(EGL_NONE); EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data()); @@ -938,17 +1012,21 @@ EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig conf } EGLSurface GLESRenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config, - int hwcFormat) { + int hwcFormat, Protection protection) { EGLConfig dummyConfig = config; if (dummyConfig == EGL_NO_CONFIG) { dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true); } std::vector<EGLint> attributes; - attributes.reserve(5); + attributes.reserve(7); attributes.push_back(EGL_WIDTH); attributes.push_back(1); attributes.push_back(EGL_HEIGHT); attributes.push_back(1); + if (protection == Protection::PROTECTED) { + attributes.push_back(EGL_PROTECTED_CONTENT_EXT); + attributes.push_back(EGL_TRUE); + } attributes.push_back(EGL_NONE); return eglCreatePbufferSurface(display, dummyConfig, attributes.data()); diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 21d5b8197d..07e5585c04 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -45,7 +45,8 @@ public: static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag - EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy); + EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy, + EGLContext protectedContext, EGLSurface protectedDummy); ~GLESRenderEngine() override; std::unique_ptr<Framebuffer> createFramebuffer() override; @@ -68,6 +69,9 @@ public: void unbindFrameBuffer(Framebuffer* framebuffer) override; void checkErrors() const override; + bool isProtected() const override { return mInProtectedContext; } + bool supportsProtectedContent() const override; + bool useProtectedContext(bool useProtectedContext) override; status_t drawLayers(const DisplaySettings& settings, const std::vector<LayerSettings>& layers, ANativeWindowBuffer* const buffer, base::unique_fd* displayFence) const override; @@ -112,20 +116,22 @@ private: static GlesVersion parseGlesVersion(const char* str); static EGLContext createEglContext(EGLDisplay display, EGLConfig config, - EGLContext shareContext, bool useContextPriority); + EGLContext shareContext, bool useContextPriority, + Protection protection); static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config, - int hwcFormat); + int hwcFormat, Protection protection); // A data space is considered HDR data space if it has BT2020 color space // with PQ or HLG transfer function. bool isHdrDataSpace(const ui::Dataspace dataSpace) const; bool needsXYZTransformMatrix() const; - void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy); EGLDisplay mEGLDisplay; EGLConfig mEGLConfig; EGLContext mEGLContext; EGLSurface mDummySurface; + EGLContext mProtectedEGLContext; + EGLSurface mProtectedDummySurface; GLuint mProtectedTexName; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; @@ -146,6 +152,7 @@ private: mat4 mBt2020ToSrgb; mat4 mBt2020ToDisplayP3; + bool mInProtectedContext = false; int32_t mFboHeight = 0; // Current dataspace of layer being rendered diff --git a/libs/renderengine/gl/GLExtensions.cpp b/libs/renderengine/gl/GLExtensions.cpp index ce83dd576b..2924b0e8b3 100644 --- a/libs/renderengine/gl/GLExtensions.cpp +++ b/libs/renderengine/gl/GLExtensions.cpp @@ -60,6 +60,11 @@ void GLExtensions::initWithGLStrings(GLubyte const* vendor, GLubyte const* rende mRenderer = (char const*)renderer; mVersion = (char const*)version; mExtensions = (char const*)extensions; + + ExtensionSet extensionSet(mExtensions.c_str()); + if (extensionSet.hasExtension("GL_EXT_protected_textures")) { + mHasProtectedTexture = true; + } } char const* GLExtensions::getVendor() const { diff --git a/libs/renderengine/gl/GLExtensions.h b/libs/renderengine/gl/GLExtensions.h index 2a654d5356..ef000090a8 100644 --- a/libs/renderengine/gl/GLExtensions.h +++ b/libs/renderengine/gl/GLExtensions.h @@ -40,6 +40,7 @@ public: bool hasProtectedContent() const { return mHasProtectedContent; } bool hasContextPriority() const { return mHasContextPriority; } bool hasSurfacelessContext() const { return mHasSurfacelessContext; } + bool hasProtectedTexture() const { return mHasProtectedTexture; } void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version, GLubyte const* extensions); @@ -65,12 +66,12 @@ private: bool mHasProtectedContent = false; bool mHasContextPriority = false; bool mHasSurfacelessContext = false; + bool mHasProtectedTexture = false; String8 mVendor; String8 mRenderer; String8 mVersion; String8 mExtensions; - String8 mEGLVersion; String8 mEGLExtensions; diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp index f4de91a0a9..4a519bb422 100644 --- a/libs/renderengine/gl/GLFramebuffer.cpp +++ b/libs/renderengine/gl/GLFramebuffer.cpp @@ -39,7 +39,7 @@ GLFramebuffer::~GLFramebuffer() { eglDestroyImageKHR(mEGLDisplay, mEGLImage); } -bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) { +bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) { if (mEGLImage != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(mEGLDisplay, mEGLImage); mEGLImage = EGL_NO_IMAGE_KHR; @@ -48,8 +48,13 @@ bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) { } if (nativeBuffer) { + EGLint attributes[] = { + isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE, + isProtected ? EGL_TRUE : EGL_NONE, + EGL_NONE, + }; mEGLImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, - nativeBuffer, nullptr); + nativeBuffer, attributes); if (mEGLImage == EGL_NO_IMAGE_KHR) { return false; } diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h index 358ab47061..5043c590a9 100644 --- a/libs/renderengine/gl/GLFramebuffer.h +++ b/libs/renderengine/gl/GLFramebuffer.h @@ -35,7 +35,7 @@ public: explicit GLFramebuffer(const GLESRenderEngine& engine); ~GLFramebuffer() override; - bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) override; + bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) override; EGLImageKHR getEGLImage() const { return mEGLImage; } uint32_t getTextureName() const { return mTextureName; } uint32_t getFramebufferName() const { return mFramebufferName; } diff --git a/libs/renderengine/gl/GLImage.cpp b/libs/renderengine/gl/GLImage.cpp index a9529a757c..587cb313c2 100644 --- a/libs/renderengine/gl/GLImage.cpp +++ b/libs/renderengine/gl/GLImage.cpp @@ -65,6 +65,7 @@ bool GLImage::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtecte ALOGE("failed to create EGLImage: %#x", eglGetError()); return false; } + mProtected = isProtected; } return true; diff --git a/libs/renderengine/gl/GLImage.h b/libs/renderengine/gl/GLImage.h index c897d8e5ec..59d6ce3549 100644 --- a/libs/renderengine/gl/GLImage.h +++ b/libs/renderengine/gl/GLImage.h @@ -39,10 +39,12 @@ public: bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override; EGLImageKHR getEGLImage() const { return mEGLImage; } + bool isProtected() const { return mProtected; } private: EGLDisplay mEGLDisplay; EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR; + bool mProtected = false; DISALLOW_COPY_AND_ASSIGN(GLImage); }; diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp index 41870d2158..bf2354dbfd 100644 --- a/libs/renderengine/gl/ProgramCache.cpp +++ b/libs/renderengine/gl/ProgramCache.cpp @@ -77,7 +77,8 @@ Formatter& dedent(Formatter& f) { return f; } -void ProgramCache::primeCache(bool useColorManagement) { +void ProgramCache::primeCache(EGLContext context, bool useColorManagement) { + auto& cache = mCaches[context]; uint32_t shaderCount = 0; uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | Key::ALPHA_MASK | Key::TEXTURE_MASK | Key::ROUNDED_CORNERS_MASK; @@ -92,8 +93,8 @@ void ProgramCache::primeCache(bool useColorManagement) { if (tex != Key::TEXTURE_OFF && tex != Key::TEXTURE_EXT && tex != Key::TEXTURE_2D) { continue; } - if (mCache.count(shaderKey) == 0) { - mCache.emplace(shaderKey, generateProgram(shaderKey)); + if (cache.count(shaderKey) == 0) { + cache.emplace(shaderKey, generateProgram(shaderKey)); shaderCount++; } } @@ -109,8 +110,8 @@ void ProgramCache::primeCache(bool useColorManagement) { shaderKey.set(Key::OPACITY_MASK, (i & 1) ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT); shaderKey.set(Key::ALPHA_MASK, (i & 2) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE); - if (mCache.count(shaderKey) == 0) { - mCache.emplace(shaderKey, generateProgram(shaderKey)); + if (cache.count(shaderKey) == 0) { + cache.emplace(shaderKey, generateProgram(shaderKey)); shaderCount++; } } @@ -695,20 +696,21 @@ std::unique_ptr<Program> ProgramCache::generateProgram(const Key& needs) { return std::make_unique<Program>(needs, vs.string(), fs.string()); } -void ProgramCache::useProgram(const Description& description) { +void ProgramCache::useProgram(EGLContext context, const Description& description) { // generate the key for the shader based on the description Key needs(computeKey(description)); // look-up the program in the cache - auto it = mCache.find(needs); - if (it == mCache.end()) { + auto& cache = mCaches[context]; + auto it = cache.find(needs); + if (it == cache.end()) { // we didn't find our program, so generate one... nsecs_t time = systemTime(); - it = mCache.emplace(needs, generateProgram(needs)).first; + it = cache.emplace(needs, generateProgram(needs)).first; time = systemTime() - time; - ALOGV(">>> generated new program: needs=%08X, time=%u ms (%zu programs)", needs.mKey, - uint32_t(ns2ms(time)), mCache.size()); + ALOGV(">>> generated new program for context %p: needs=%08X, time=%u ms (%zu programs)", + context, needs.mKey, uint32_t(ns2ms(time)), cache.size()); } // here we have a suitable program for this description diff --git a/libs/renderengine/gl/ProgramCache.h b/libs/renderengine/gl/ProgramCache.h index 653aaf0f6c..400ad74fca 100644 --- a/libs/renderengine/gl/ProgramCache.h +++ b/libs/renderengine/gl/ProgramCache.h @@ -20,6 +20,7 @@ #include <memory> #include <unordered_map> +#include <EGL/egl.h> #include <GLES2/gl2.h> #include <renderengine/private/Description.h> #include <utils/Singleton.h> @@ -178,13 +179,13 @@ public: ~ProgramCache() = default; // Generate shaders to populate the cache - void primeCache(bool useColorManagement); + void primeCache(const EGLContext context, bool useColorManagement); - size_t getSize() const { return mCache.size(); } + size_t getSize(const EGLContext context) { return mCaches[context].size(); } // useProgram lookup a suitable program in the cache or generates one // if none can be found. - void useProgram(const Description& description); + void useProgram(const EGLContext context, const Description& description); private: // compute a cache Key from a Description @@ -206,7 +207,8 @@ private: // Key/Value map used for caching Programs. Currently the cache // is never shrunk (and the GL program objects are never deleted). - std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash> mCache; + std::unordered_map<EGLContext, std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash>> + mCaches; }; } // namespace gl diff --git a/libs/renderengine/include/renderengine/Framebuffer.h b/libs/renderengine/include/renderengine/Framebuffer.h index 558b9c7b21..66eb9ef206 100644 --- a/libs/renderengine/include/renderengine/Framebuffer.h +++ b/libs/renderengine/include/renderengine/Framebuffer.h @@ -27,7 +27,7 @@ class Framebuffer { public: virtual ~Framebuffer() = default; - virtual bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) = 0; + virtual bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) = 0; }; } // namespace renderengine diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 8eaa2d296b..5e88159207 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -53,6 +53,11 @@ namespace impl { class RenderEngine; } +enum class Protection { + UNPROTECTED = 1, + PROTECTED = 2, +}; + class RenderEngine { public: enum FeatureFlag { @@ -150,6 +155,10 @@ public: // ----- BEGIN NEW INTERFACE ----- + virtual bool isProtected() const = 0; + virtual bool supportsProtectedContent() const = 0; + virtual bool useProtectedContext(bool useProtectedContext) = 0; + // Renders layers for a particular display via GPU composition. This method // should be called for every display that needs to be rendered via the GPU. // @param settings The display-wide settings that should be applied prior to @@ -182,12 +191,12 @@ class BindNativeBufferAsFramebuffer { public: BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer) : mEngine(engine), mFramebuffer(mEngine.createFramebuffer()), mStatus(NO_ERROR) { - mStatus = mFramebuffer->setNativeWindowBuffer(buffer) + mStatus = mFramebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected()) ? mEngine.bindFrameBuffer(mFramebuffer.get()) : NO_MEMORY; } ~BindNativeBufferAsFramebuffer() { - mFramebuffer->setNativeWindowBuffer(nullptr); + mFramebuffer->setNativeWindowBuffer(nullptr, false); mEngine.unbindFrameBuffer(mFramebuffer.get()); } status_t getStatus() const { return mStatus; } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 55d68f691a..98ae2861f2 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -71,6 +71,10 @@ public: // isVisible - true if this layer is visible, false otherwise bool isVisible() const override EXCLUDES(mStateMutex); + // isProtected - true if the layer may contain protected content in the + // GRALLOC_USAGE_PROTECTED sense. + bool isProtected() const override; + // isFixedSize - true if content has a fixed size bool isFixedSize() const override; @@ -155,13 +159,6 @@ private: virtual void setHwcLayerBuffer(DisplayId displayId) EXCLUDES(mStateMutex) = 0; - // ----------------------------------------------------------------------- - -public: - // isProtected - true if the layer may contain protected content in the - // GRALLOC_USAGE_PROTECTED sense. - bool isProtected() const; - protected: // Loads the corresponding system property once per process static bool latchUnsignaledBuffers(); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 3ad07ae41a..2003fb15d9 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -366,6 +366,15 @@ status_t DisplayDevice::prepareFrame(HWComposer& hwc, return mDisplaySurface->prepareFrame(compositionType); } +void DisplayDevice::setProtected(bool useProtected) { + uint64_t usageFlags = GRALLOC_USAGE_HW_RENDER; + if (useProtected) { + usageFlags |= GRALLOC_USAGE_PROTECTED; + } + const int status = native_window_set_usage(mNativeWindow.get(), usageFlags); + ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status); +} + sp<GraphicBuffer> DisplayDevice::dequeueBuffer() { int fd; ANativeWindowBuffer* buffer; diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index ba85432d52..2c2a3abf86 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -146,6 +146,7 @@ public: ui::Dataspace* outDataspace, ui::ColorMode* outMode, ui::RenderIntent* outIntent) const; + void setProtected(bool useProtected); // Queues the drawn buffer for consumption by HWC. void queueBuffer(HWComposer& hwc); // Allocates a buffer as scratch space for GPU composition diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 57ef65a18f..fb75e4c694 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -399,6 +399,12 @@ public: bool isHiddenByPolicy() const EXCLUDES(mStateMutex); /* + * isProtected - true if the layer may contain protected content in the + * GRALLOC_USAGE_PROTECTED sense. + */ + virtual bool isProtected() const { return false; } + + /* * isFixedSize - true if content has a fixed size */ virtual bool isFixedSize() const { return true; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e6a43c521c..a5ba0546a0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5439,10 +5439,11 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } + auto& engine(getRenderEngine()); // this binds the given EGLImage as a framebuffer for the // duration of this scope. - renderengine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer); + renderengine::BindNativeBufferAsFramebuffer bufferBond(engine, buffer); if (bufferBond.getStatus() != NO_ERROR) { ALOGE("got ANWB binding error while taking screenshot"); return INVALID_OPERATION; @@ -5454,9 +5455,9 @@ status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea, // dependent on the context's EGLConfig. renderScreenImplLocked(renderArea, traverseLayers, useIdentityTransform); - base::unique_fd syncFd = getRenderEngine().flush(); + base::unique_fd syncFd = engine.flush(); if (syncFd < 0) { - getRenderEngine().finish(); + engine.finish(); } *outSyncFd = syncFd.release(); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 5a6aa9279a..b7c09ed503 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -286,8 +286,10 @@ struct BaseDisplayVariant { static void setupCommonScreensCaptureCallExpectations(CompositionTest* test) { // Called once with a non-null value to set a framebuffer, and then // again with nullptr to clear it. - EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull())).WillOnce(Return(true)); - EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull())).WillOnce(Return(true)); + EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull(), false)) + .WillOnce(Return(true)); + EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull(), false)) + .WillOnce(Return(true)); EXPECT_CALL(*test->mRenderEngine, checkErrors()).WillRepeatedly(Return()); EXPECT_CALL(*test->mRenderEngine, createFramebuffer()) @@ -344,8 +346,10 @@ struct BaseDisplayVariant { Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), ui::Transform::ROT_0)) .Times(1); - EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull())).WillOnce(Return(true)); - EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull())).WillOnce(Return(true)); + EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull(), false)) + .WillOnce(Return(true)); + EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull(), false)) + .WillOnce(Return(true)); EXPECT_CALL(*test->mRenderEngine, createFramebuffer()) .WillOnce(Return( ByMove(std::unique_ptr<renderengine::Framebuffer>(test->mReFrameBuffer)))); diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h index 11e56317b0..1bee271865 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h @@ -74,6 +74,9 @@ public: MOCK_METHOD1(drawMesh, void(const Mesh&)); MOCK_CONST_METHOD0(getMaxTextureSize, size_t()); MOCK_CONST_METHOD0(getMaxViewportDims, size_t()); + MOCK_CONST_METHOD0(isProtected, bool()); + MOCK_CONST_METHOD0(supportsProtectedContent, bool()); + MOCK_METHOD1(useProtectedContext, bool(bool)); MOCK_CONST_METHOD4(drawLayers, status_t(const DisplaySettings&, const std::vector<LayerSettings>&, ANativeWindowBuffer* const, base::unique_fd*)); @@ -84,8 +87,7 @@ public: Image(); ~Image() override; - MOCK_METHOD2(setNativeWindowBuffer, - bool(ANativeWindowBuffer* buffer, bool isProtected)); + MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool)); }; class Framebuffer : public renderengine::Framebuffer { @@ -93,7 +95,7 @@ public: Framebuffer(); ~Framebuffer() override; - MOCK_METHOD1(setNativeWindowBuffer, bool(ANativeWindowBuffer*)); + MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool)); }; } // namespace mock |