Loading libs/renderengine/gl/GLESRenderEngine.cpp +25 −13 Original line number Diff line number Diff line Loading @@ -984,18 +984,19 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, } std::unique_ptr<BindNativeBufferAsFramebuffer> fbo; // Let's find the topmost layer requesting background blur (if any.) // Blurs in multiple layers are not supported, given the cost of the shader. const LayerSettings* blurLayer = nullptr; // Gathering layers that requested blur, we'll need them to decide when to render to an // offscreen buffer, and when to render to the native buffer. std::deque<const LayerSettings*> blurLayers; if (CC_LIKELY(mBlurFilter != nullptr)) { for (auto const layer : layers) { for (auto layer : layers) { if (layer->backgroundBlurRadius > 0) { blurLayer = layer; blurLayers.push_back(layer); } } } const auto blurLayersSize = blurLayers.size(); if (blurLayer == nullptr) { if (blurLayersSize == 0) { fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer, useFramebufferCache); if (fbo->getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", Loading @@ -1006,7 +1007,8 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, setViewportAndProjection(display.physicalDisplay, display.clip); } else { setViewportAndProjection(display.physicalDisplay, display.clip); auto status = mBlurFilter->setAsDrawTarget(display, blurLayer->backgroundBlurRadius); auto status = mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", buffer->handle); Loading Loading @@ -1039,7 +1041,9 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, .setCropCoords(2 /* size */) .build(); for (auto const layer : layers) { if (blurLayer == layer) { if (blurLayers.size() > 0 && blurLayers.front() == layer) { blurLayers.pop_front(); auto status = mBlurFilter->prepare(); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", Loading @@ -1048,18 +1052,26 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return status; } if (blurLayers.size() == 0) { // Done blurring, time to bind the native FBO and render our blur onto it. fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer, useFramebufferCache); status = fbo->getStatus(); setViewportAndProjection(display.physicalDisplay, display.clip); } else { // There's still something else to blur, so let's keep rendering to our FBO // instead of to the display. status = mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", buffer->handle); checkErrors("Can't bind native framebuffer"); return status; } setViewportAndProjection(display.physicalDisplay, display.clip); status = mBlurFilter->render(); status = mBlurFilter->render(blurLayersSize > 1); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", buffer->handle); Loading libs/renderengine/gl/filters/BlurFilter.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -96,13 +96,17 @@ void BlurFilter::drawMesh(GLuint uv, GLuint position) { mEngine.checkErrors("Drawing blur mesh"); } status_t BlurFilter::render() { status_t BlurFilter::render(bool multiPass) { ATRACE_NAME("BlurFilter::render"); // Now let's scale our blur up. It will be interpolated with the larger composited // texture for the first frames, to hide downscaling artifacts. GLfloat mix = fmin(1.0, mRadius / kMaxCrossFadeRadius); if (mix >= 1) { // When doing multiple passes, we cannot try to read mCompositionFbo, given that we'll // be writing onto it. Let's disable the crossfade, otherwise we'd need 1 extra frame buffer, // as large as the screen size. if (mix >= 1 || multiPass) { mBlurredFbo.bindAsReadBuffer(); glBlitFramebuffer(0, 0, mBlurredFbo.getBufferWidth(), mBlurredFbo.getBufferHeight(), 0, 0, mDisplayWidth, mDisplayHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); Loading libs/renderengine/gl/filters/BlurFilter.h +1 −1 Original line number Diff line number Diff line Loading @@ -45,7 +45,7 @@ public: // Execute blur passes, rendering to offscreen texture. virtual status_t prepare() = 0; // Render blur to the bound framebuffer (screen). status_t render(); status_t render(bool multiPass); protected: uint32_t mRadius; Loading services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -279,6 +279,48 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadius) { 50 /* tolerance */); } TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusOnMultipleLayers) { char value[PROPERTY_VALUE_MAX]; property_get("ro.surface_flinger.supports_background_blur", value, "0"); if (!atoi(value)) { // This device doesn't support blurs, no-op. return; } auto size = 256; auto center = size / 2; auto blurRadius = 50; sp<SurfaceControl> backgroundLayer; ASSERT_NO_FATAL_FAILURE(backgroundLayer = createLayer("background", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(backgroundLayer, Color::GREEN, size, size)); sp<SurfaceControl> leftLayer; ASSERT_NO_FATAL_FAILURE(leftLayer = createLayer("left", size / 2, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(leftLayer, Color::RED, size / 2, size)); sp<SurfaceControl> blurLayer1; auto centralSquareSize = size / 2; ASSERT_NO_FATAL_FAILURE(blurLayer1 = createLayer("blur1", centralSquareSize, centralSquareSize)); ASSERT_NO_FATAL_FAILURE( fillLayerColor(blurLayer1, Color::BLUE, centralSquareSize, centralSquareSize)); sp<SurfaceControl> blurLayer2; ASSERT_NO_FATAL_FAILURE(blurLayer2 = createLayer("blur2", size, size)); ASSERT_NO_FATAL_FAILURE( fillLayerColor(blurLayer2, Color::TRANSPARENT, centralSquareSize, centralSquareSize)); Transaction() .setBackgroundBlurRadius(blurLayer1, blurRadius) .setBackgroundBlurRadius(blurLayer2, blurRadius) .apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(center - 5, center - 5, center, center), Color{100, 100, 100, 255}, 40 /* tolerance */); } TEST_P(LayerTypeAndRenderTypeTransactionTest, SetColorWithBuffer) { sp<SurfaceControl> bufferLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32)); Loading Loading
libs/renderengine/gl/GLESRenderEngine.cpp +25 −13 Original line number Diff line number Diff line Loading @@ -984,18 +984,19 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, } std::unique_ptr<BindNativeBufferAsFramebuffer> fbo; // Let's find the topmost layer requesting background blur (if any.) // Blurs in multiple layers are not supported, given the cost of the shader. const LayerSettings* blurLayer = nullptr; // Gathering layers that requested blur, we'll need them to decide when to render to an // offscreen buffer, and when to render to the native buffer. std::deque<const LayerSettings*> blurLayers; if (CC_LIKELY(mBlurFilter != nullptr)) { for (auto const layer : layers) { for (auto layer : layers) { if (layer->backgroundBlurRadius > 0) { blurLayer = layer; blurLayers.push_back(layer); } } } const auto blurLayersSize = blurLayers.size(); if (blurLayer == nullptr) { if (blurLayersSize == 0) { fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer, useFramebufferCache); if (fbo->getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", Loading @@ -1006,7 +1007,8 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, setViewportAndProjection(display.physicalDisplay, display.clip); } else { setViewportAndProjection(display.physicalDisplay, display.clip); auto status = mBlurFilter->setAsDrawTarget(display, blurLayer->backgroundBlurRadius); auto status = mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", buffer->handle); Loading Loading @@ -1039,7 +1041,9 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, .setCropCoords(2 /* size */) .build(); for (auto const layer : layers) { if (blurLayer == layer) { if (blurLayers.size() > 0 && blurLayers.front() == layer) { blurLayers.pop_front(); auto status = mBlurFilter->prepare(); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", Loading @@ -1048,18 +1052,26 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return status; } if (blurLayers.size() == 0) { // Done blurring, time to bind the native FBO and render our blur onto it. fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer, useFramebufferCache); status = fbo->getStatus(); setViewportAndProjection(display.physicalDisplay, display.clip); } else { // There's still something else to blur, so let's keep rendering to our FBO // instead of to the display. status = mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", buffer->handle); checkErrors("Can't bind native framebuffer"); return status; } setViewportAndProjection(display.physicalDisplay, display.clip); status = mBlurFilter->render(); status = mBlurFilter->render(blurLayersSize > 1); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", buffer->handle); Loading
libs/renderengine/gl/filters/BlurFilter.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -96,13 +96,17 @@ void BlurFilter::drawMesh(GLuint uv, GLuint position) { mEngine.checkErrors("Drawing blur mesh"); } status_t BlurFilter::render() { status_t BlurFilter::render(bool multiPass) { ATRACE_NAME("BlurFilter::render"); // Now let's scale our blur up. It will be interpolated with the larger composited // texture for the first frames, to hide downscaling artifacts. GLfloat mix = fmin(1.0, mRadius / kMaxCrossFadeRadius); if (mix >= 1) { // When doing multiple passes, we cannot try to read mCompositionFbo, given that we'll // be writing onto it. Let's disable the crossfade, otherwise we'd need 1 extra frame buffer, // as large as the screen size. if (mix >= 1 || multiPass) { mBlurredFbo.bindAsReadBuffer(); glBlitFramebuffer(0, 0, mBlurredFbo.getBufferWidth(), mBlurredFbo.getBufferHeight(), 0, 0, mDisplayWidth, mDisplayHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); Loading
libs/renderengine/gl/filters/BlurFilter.h +1 −1 Original line number Diff line number Diff line Loading @@ -45,7 +45,7 @@ public: // Execute blur passes, rendering to offscreen texture. virtual status_t prepare() = 0; // Render blur to the bound framebuffer (screen). status_t render(); status_t render(bool multiPass); protected: uint32_t mRadius; Loading
services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -279,6 +279,48 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadius) { 50 /* tolerance */); } TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusOnMultipleLayers) { char value[PROPERTY_VALUE_MAX]; property_get("ro.surface_flinger.supports_background_blur", value, "0"); if (!atoi(value)) { // This device doesn't support blurs, no-op. return; } auto size = 256; auto center = size / 2; auto blurRadius = 50; sp<SurfaceControl> backgroundLayer; ASSERT_NO_FATAL_FAILURE(backgroundLayer = createLayer("background", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(backgroundLayer, Color::GREEN, size, size)); sp<SurfaceControl> leftLayer; ASSERT_NO_FATAL_FAILURE(leftLayer = createLayer("left", size / 2, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(leftLayer, Color::RED, size / 2, size)); sp<SurfaceControl> blurLayer1; auto centralSquareSize = size / 2; ASSERT_NO_FATAL_FAILURE(blurLayer1 = createLayer("blur1", centralSquareSize, centralSquareSize)); ASSERT_NO_FATAL_FAILURE( fillLayerColor(blurLayer1, Color::BLUE, centralSquareSize, centralSquareSize)); sp<SurfaceControl> blurLayer2; ASSERT_NO_FATAL_FAILURE(blurLayer2 = createLayer("blur2", size, size)); ASSERT_NO_FATAL_FAILURE( fillLayerColor(blurLayer2, Color::TRANSPARENT, centralSquareSize, centralSquareSize)); Transaction() .setBackgroundBlurRadius(blurLayer1, blurRadius) .setBackgroundBlurRadius(blurLayer2, blurRadius) .apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(center - 5, center - 5, center, center), Color{100, 100, 100, 255}, 40 /* tolerance */); } TEST_P(LayerTypeAndRenderTypeTransactionTest, SetColorWithBuffer) { sp<SurfaceControl> bufferLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32)); Loading