Loading libs/renderengine/gl/GLESRenderEngine.cpp +85 −16 Original line number Diff line number Diff line Loading @@ -648,27 +648,89 @@ bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) { return success; } status_t GLESRenderEngine::drawLayers(const DisplaySettings& /*settings*/, const std::vector<LayerSettings>& /*layers*/, ANativeWindowBuffer* const /*buffer*/, base::unique_fd* /*displayFence*/) const { status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers, ANativeWindowBuffer* const buffer, base::unique_fd* drawFence) { if (layers.empty()) { ALOGV("Drawing empty layer stack"); return NO_ERROR; } BindNativeBufferAsFramebuffer fbo(*this, buffer); if (fbo.getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", buffer->handle); checkErrors(); return fbo.getStatus(); } setViewportAndProjection(display.physicalDisplay, display.clip); setOutputDataSpace(display.outputDataspace); setDisplayMaxLuminance(display.maxLuminance); mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform; Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); for (auto layer : layers) { // for now, assume that all pixel sources are solid colors. // TODO(alecmouri): support buffer sources if (layer.source.buffer.buffer != nullptr) { continue; } setColorTransform(display.colorTransform * layer.colorTransform); mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform; FloatRect bounds = layer.geometry.boundaries; Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); position[0] = vec2(bounds.left, bounds.top); position[1] = vec2(bounds.left, bounds.bottom); position[2] = vec2(bounds.right, bounds.bottom); position[3] = vec2(bounds.right, bounds.top); half3 solidColor = layer.source.solidColor; half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha); setupLayerBlending(/*premultipliedAlpha=*/true, /*opaque=*/false, /*disableTexture=*/true, color, /*cornerRadius=*/0.0); setSourceDataSpace(layer.sourceDataspace); drawMesh(mesh); } *drawFence = flush(); // If flush failed or we don't support native fences, we need to force the // gl command stream to be executed. if (drawFence->get() < 0) { bool success = finish(); if (!success) { ALOGE("Failed to flush RenderEngine commands"); checkErrors(); // Chances are, something illegal happened (either the caller passed // us bad parameters, or we messed up our shader generation). return INVALID_OPERATION; } } checkErrors(); return NO_ERROR; } void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, ui::Transform::orientation_flags rotation) { int32_t l = sourceCrop.left; int32_t r = sourceCrop.right; int32_t b = sourceCrop.bottom; int32_t t = sourceCrop.top; std::swap(t, b); mat4 m = mat4::ortho(l, r, b, t, 0, 1); setViewportAndProjection(Rect(vpw, vph), sourceCrop); if (rotation == ui::Transform::ROT_0) { return; } // Apply custom rotation to the projection. float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f; mat4 m = mState.projectionMatrix; switch (rotation) { case ui::Transform::ROT_0: break; case ui::Transform::ROT_90: m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m; break; Loading @@ -681,11 +743,18 @@ void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sou default: break; } glViewport(0, 0, vpw, vph); mState.projectionMatrix = m; mVpWidth = vpw; mVpHeight = vph; } void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) { mVpWidth = viewport.getWidth(); mVpHeight = viewport.getHeight(); // We pass the the top left corner instead of the bottom left corner, // because since we're rendering off-screen first. glViewport(viewport.left, viewport.top, mVpWidth, mVpHeight); mState.projectionMatrix = mat4::ortho(clip.left, clip.right, clip.top, clip.bottom, 0, 1); } void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, Loading libs/renderengine/gl/GLESRenderEngine.h +5 −3 Original line number Diff line number Diff line Loading @@ -72,9 +72,8 @@ public: 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; status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers, ANativeWindowBuffer* buffer, base::unique_fd* drawFence) override; // internal to RenderEngine EGLDisplay getEGLDisplay() const { return mEGLDisplay; } Loading Loading @@ -125,6 +124,9 @@ private: // with PQ or HLG transfer function. bool isHdrDataSpace(const ui::Dataspace dataSpace) const; bool needsXYZTransformMatrix() const; // Defines the viewport, and sets the projection matrix to the projection // defined by the clip. void setViewportAndProjection(Rect viewport, Rect clip); EGLDisplay mEGLDisplay; EGLConfig mEGLConfig; Loading libs/renderengine/include/renderengine/DisplaySettings.h +1 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ struct DisplaySettings { mat4 globalTransform = mat4(); // Maximum luminance pulled from the display's HDR capabilities. float maxLuminence = 1.0f; float maxLuminance = 1.0f; // Output dataspace that will be populated if wide color gamut is used, or // DataSpace::UNKNOWN otherwise. Loading libs/renderengine/include/renderengine/LayerSettings.h +5 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,11 @@ struct LayerSettings { half alpha = half(0.0); // Color space describing how the source pixels should be interpreted. ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN; ui::Dataspace sourceDataspace; // Additional layer-specific color transform to be applied before the global // transform. mat4 colorTransform; }; } // namespace renderengine Loading libs/renderengine/include/renderengine/RenderEngine.h +4 −5 Original line number Diff line number Diff line Loading @@ -161,12 +161,12 @@ public: // 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 // @param display The display-wide settings that should be applied prior to // drawing any layers. // @param layers The layers to draw onto the display, in Z-order. // @param buffer The buffer which will be drawn to. This buffer will be // ready once displayFence fires. // @param displayFence A pointer to a fence, which will fire when the buffer // @param drawFence A pointer to a fence, which will fire when the buffer // has been drawn to and is ready to be examined. The fence will be // initialized by this method. The caller will be responsible for owning the // fence. Loading @@ -174,10 +174,9 @@ public: // now, this always returns NO_ERROR. // TODO(alecmouri): Consider making this a multi-display API, so that the // caller deoes not need to handle multiple fences. virtual status_t drawLayers(const DisplaySettings& settings, virtual status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers, ANativeWindowBuffer* const buffer, base::unique_fd* displayFence) const = 0; ANativeWindowBuffer* buffer, base::unique_fd* drawFence) = 0; // TODO(alecmouri): Expose something like bindTexImage() so that devices // that don't support native sync fences can get rid of code duplicated Loading Loading
libs/renderengine/gl/GLESRenderEngine.cpp +85 −16 Original line number Diff line number Diff line Loading @@ -648,27 +648,89 @@ bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) { return success; } status_t GLESRenderEngine::drawLayers(const DisplaySettings& /*settings*/, const std::vector<LayerSettings>& /*layers*/, ANativeWindowBuffer* const /*buffer*/, base::unique_fd* /*displayFence*/) const { status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers, ANativeWindowBuffer* const buffer, base::unique_fd* drawFence) { if (layers.empty()) { ALOGV("Drawing empty layer stack"); return NO_ERROR; } BindNativeBufferAsFramebuffer fbo(*this, buffer); if (fbo.getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", buffer->handle); checkErrors(); return fbo.getStatus(); } setViewportAndProjection(display.physicalDisplay, display.clip); setOutputDataSpace(display.outputDataspace); setDisplayMaxLuminance(display.maxLuminance); mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform; Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2); for (auto layer : layers) { // for now, assume that all pixel sources are solid colors. // TODO(alecmouri): support buffer sources if (layer.source.buffer.buffer != nullptr) { continue; } setColorTransform(display.colorTransform * layer.colorTransform); mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform; FloatRect bounds = layer.geometry.boundaries; Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); position[0] = vec2(bounds.left, bounds.top); position[1] = vec2(bounds.left, bounds.bottom); position[2] = vec2(bounds.right, bounds.bottom); position[3] = vec2(bounds.right, bounds.top); half3 solidColor = layer.source.solidColor; half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha); setupLayerBlending(/*premultipliedAlpha=*/true, /*opaque=*/false, /*disableTexture=*/true, color, /*cornerRadius=*/0.0); setSourceDataSpace(layer.sourceDataspace); drawMesh(mesh); } *drawFence = flush(); // If flush failed or we don't support native fences, we need to force the // gl command stream to be executed. if (drawFence->get() < 0) { bool success = finish(); if (!success) { ALOGE("Failed to flush RenderEngine commands"); checkErrors(); // Chances are, something illegal happened (either the caller passed // us bad parameters, or we messed up our shader generation). return INVALID_OPERATION; } } checkErrors(); return NO_ERROR; } void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, ui::Transform::orientation_flags rotation) { int32_t l = sourceCrop.left; int32_t r = sourceCrop.right; int32_t b = sourceCrop.bottom; int32_t t = sourceCrop.top; std::swap(t, b); mat4 m = mat4::ortho(l, r, b, t, 0, 1); setViewportAndProjection(Rect(vpw, vph), sourceCrop); if (rotation == ui::Transform::ROT_0) { return; } // Apply custom rotation to the projection. float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f; mat4 m = mState.projectionMatrix; switch (rotation) { case ui::Transform::ROT_0: break; case ui::Transform::ROT_90: m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m; break; Loading @@ -681,11 +743,18 @@ void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sou default: break; } glViewport(0, 0, vpw, vph); mState.projectionMatrix = m; mVpWidth = vpw; mVpHeight = vph; } void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) { mVpWidth = viewport.getWidth(); mVpHeight = viewport.getHeight(); // We pass the the top left corner instead of the bottom left corner, // because since we're rendering off-screen first. glViewport(viewport.left, viewport.top, mVpWidth, mVpHeight); mState.projectionMatrix = mat4::ortho(clip.left, clip.right, clip.top, clip.bottom, 0, 1); } void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, Loading
libs/renderengine/gl/GLESRenderEngine.h +5 −3 Original line number Diff line number Diff line Loading @@ -72,9 +72,8 @@ public: 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; status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers, ANativeWindowBuffer* buffer, base::unique_fd* drawFence) override; // internal to RenderEngine EGLDisplay getEGLDisplay() const { return mEGLDisplay; } Loading Loading @@ -125,6 +124,9 @@ private: // with PQ or HLG transfer function. bool isHdrDataSpace(const ui::Dataspace dataSpace) const; bool needsXYZTransformMatrix() const; // Defines the viewport, and sets the projection matrix to the projection // defined by the clip. void setViewportAndProjection(Rect viewport, Rect clip); EGLDisplay mEGLDisplay; EGLConfig mEGLConfig; Loading
libs/renderengine/include/renderengine/DisplaySettings.h +1 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ struct DisplaySettings { mat4 globalTransform = mat4(); // Maximum luminance pulled from the display's HDR capabilities. float maxLuminence = 1.0f; float maxLuminance = 1.0f; // Output dataspace that will be populated if wide color gamut is used, or // DataSpace::UNKNOWN otherwise. Loading
libs/renderengine/include/renderengine/LayerSettings.h +5 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,11 @@ struct LayerSettings { half alpha = half(0.0); // Color space describing how the source pixels should be interpreted. ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN; ui::Dataspace sourceDataspace; // Additional layer-specific color transform to be applied before the global // transform. mat4 colorTransform; }; } // namespace renderengine Loading
libs/renderengine/include/renderengine/RenderEngine.h +4 −5 Original line number Diff line number Diff line Loading @@ -161,12 +161,12 @@ public: // 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 // @param display The display-wide settings that should be applied prior to // drawing any layers. // @param layers The layers to draw onto the display, in Z-order. // @param buffer The buffer which will be drawn to. This buffer will be // ready once displayFence fires. // @param displayFence A pointer to a fence, which will fire when the buffer // @param drawFence A pointer to a fence, which will fire when the buffer // has been drawn to and is ready to be examined. The fence will be // initialized by this method. The caller will be responsible for owning the // fence. Loading @@ -174,10 +174,9 @@ public: // now, this always returns NO_ERROR. // TODO(alecmouri): Consider making this a multi-display API, so that the // caller deoes not need to handle multiple fences. virtual status_t drawLayers(const DisplaySettings& settings, virtual status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers, ANativeWindowBuffer* const buffer, base::unique_fd* displayFence) const = 0; ANativeWindowBuffer* buffer, base::unique_fd* drawFence) = 0; // TODO(alecmouri): Expose something like bindTexImage() so that devices // that don't support native sync fences can get rid of code duplicated Loading