diff options
author | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-14 07:13:48 +0000 |
---|---|---|
committer | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-14 07:13:48 +0000 |
commit | 66321643bdea820f7682d79dee3663610f26b95d (patch) | |
tree | 9f0302ed0ba4f944b52b780053cda804168e7791 | |
parent | cf64404b033f544103752869df8ec97c3be10a5d (diff) | |
download | chromium_src-66321643bdea820f7682d79dee3663610f26b95d.zip chromium_src-66321643bdea820f7682d79dee3663610f26b95d.tar.gz chromium_src-66321643bdea820f7682d79dee3663610f26b95d.tar.bz2 |
Allow using a larger-than-necessary texture as cached render pass backing
When moving a composited layer around the screen that requires a render pass,
it's not all that unusual for the required size to be slightly different from
frame to frame. This lets us use an oversized texture as the framebuffer
attachment.
BUG=161868
Review URL: https://chromiumcodereview.appspot.com/11420079
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@173112 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | cc/direct_renderer.cc | 14 | ||||
-rw-r--r-- | cc/direct_renderer.h | 5 | ||||
-rw-r--r-- | cc/gl_renderer.cc | 33 | ||||
-rw-r--r-- | cc/gl_renderer.h | 7 | ||||
-rw-r--r-- | cc/gl_renderer_pixeltest.cc | 117 | ||||
-rw-r--r-- | cc/shader.cc | 24 | ||||
-rw-r--r-- | cc/shader.h | 2 |
7 files changed, 166 insertions, 36 deletions
diff --git a/cc/direct_renderer.cc b/cc/direct_renderer.cc index 0b2d74b..3460160 100644 --- a/cc/direct_renderer.cc +++ b/cc/direct_renderer.cc @@ -113,6 +113,11 @@ DirectRenderer::~DirectRenderer() { } +void DirectRenderer::setEnlargePassTextureAmountForTesting(gfx::Vector2d amount) +{ + m_enlargePassTextureAmount = amount; +} + void DirectRenderer::decideRenderPassAllocationsForFrame(const RenderPassList& renderPassesInDrawOrder) { base::hash_map<RenderPass::Id, const RenderPass*> renderPassesInFrame; @@ -134,7 +139,9 @@ void DirectRenderer::decideRenderPassAllocationsForFrame(const RenderPassList& r CachedResource* texture = passIterator->second; DCHECK(texture); - if (texture->id() && (texture->size() != requiredSize || texture->format() != requiredFormat)) + bool sizeAppropriate = texture->size().width() >= requiredSize.width() && + texture->size().height() >= requiredSize.height(); + if (texture->id() && (!sizeAppropriate || texture->format() != requiredFormat)) texture->Free(); } @@ -267,7 +274,10 @@ bool DirectRenderer::useRenderPass(DrawingFrame& frame, const RenderPass* render CachedResource* texture = m_renderPassTextures.get(renderPass->id); DCHECK(texture); - if (!texture->id() && !texture->Allocate(Renderer::ImplPool, renderPassTextureSize(renderPass), renderPassTextureFormat(renderPass), ResourceProvider::TextureUsageFramebuffer)) + + gfx::Size size = renderPassTextureSize(renderPass); + size.Enlarge(m_enlargePassTextureAmount.x(), m_enlargePassTextureAmount.y()); + if (!texture->id() && !texture->Allocate(Renderer::ImplPool, size, renderPassTextureFormat(renderPass), ResourceProvider::TextureUsageFramebuffer)) return false; return bindFramebufferToTexture(frame, texture, renderPass->output_rect); diff --git a/cc/direct_renderer.h b/cc/direct_renderer.h index f7f1f89..f874611 100644 --- a/cc/direct_renderer.h +++ b/cc/direct_renderer.h @@ -44,6 +44,8 @@ public: bool flippedY; }; + void setEnlargePassTextureAmountForTesting(gfx::Vector2d amount); + protected: DirectRenderer(RendererClient* client, ResourceProvider* resourceProvider); @@ -102,6 +104,9 @@ protected: ResourceProvider* m_resourceProvider; private: + + gfx::Vector2d m_enlargePassTextureAmount; + DISALLOW_COPY_AND_ASSIGN(DirectRenderer); }; diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc index ad26183..5cd493c 100644 --- a/cc/gl_renderer.cc +++ b/cc/gl_renderer.cc @@ -494,7 +494,7 @@ scoped_ptr<ScopedResource> GLRenderer::drawBackgroundFilters( // Copy the readback pixels from device to the background texture for the surface. gfx::Transform deviceToFramebufferTransform; deviceToFramebufferTransform.Translate(quad->rect.width() / 2.0, quad->rect.height() / 2.0); - deviceToFramebufferTransform.Scale3d(quad->rect.width(), quad->rect.height(), 1); + deviceToFramebufferTransform.Scale(quad->rect.width(), quad->rect.height()); deviceToFramebufferTransform.PreconcatTransform(contentsDeviceTransformInverse); copyTextureToFramebuffer(frame, filteredDeviceBackgroundTextureId, deviceRect, deviceToFramebufferTransform); } @@ -583,6 +583,9 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua int shaderMaskTexCoordOffsetLocation = -1; int shaderMatrixLocation = -1; int shaderAlphaLocation = -1; + int shaderTexTransformLocation = -1; + int shaderTexScaleLocation = -1; + if (useAA && maskTextureId) { const RenderPassMaskProgramAA* program = renderPassMaskProgramAA(); setUseProgram(program->program()); @@ -595,6 +598,7 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation(); shaderMatrixLocation = program->vertexShader().matrixLocation(); shaderAlphaLocation = program->fragmentShader().alphaLocation(); + shaderTexScaleLocation = program->vertexShader().texScaleLocation(); } else if (!useAA && maskTextureId) { const RenderPassMaskProgram* program = renderPassMaskProgram(); setUseProgram(program->program()); @@ -605,6 +609,7 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation(); shaderMatrixLocation = program->vertexShader().matrixLocation(); shaderAlphaLocation = program->fragmentShader().alphaLocation(); + shaderTexTransformLocation = program->vertexShader().texTransformLocation(); } else if (useAA && !maskTextureId) { const RenderPassProgramAA* program = renderPassProgramAA(); setUseProgram(program->program()); @@ -614,6 +619,7 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua shaderEdgeLocation = program->fragmentShader().edgeLocation(); shaderMatrixLocation = program->vertexShader().matrixLocation(); shaderAlphaLocation = program->fragmentShader().alphaLocation(); + shaderTexScaleLocation = program->vertexShader().texScaleLocation(); } else { const RenderPassProgram* program = renderPassProgram(); setUseProgram(program->program()); @@ -621,6 +627,23 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua shaderMatrixLocation = program->vertexShader().matrixLocation(); shaderAlphaLocation = program->fragmentShader().alphaLocation(); + shaderTexTransformLocation = program->vertexShader().texTransformLocation(); + } + + float tex_scale_x = quad->rect.width() / static_cast<float>(contentsTexture->size().width()); + float tex_scale_y = quad->rect.height() / static_cast<float>(contentsTexture->size().height()); + DCHECK_LE(tex_scale_x, 1.0f); + DCHECK_LE(tex_scale_y, 1.0f); + + if (shaderTexTransformLocation != -1) { + GLC(context(), context()->uniform4f(shaderTexTransformLocation, + 0.0f, 0.0f, + tex_scale_x, tex_scale_y)); + } else if (shaderTexScaleLocation != -1) { + GLC(context(), context()->uniform2f(shaderTexScaleLocation, + tex_scale_x, tex_scale_y)); + } else { + NOTREACHED(); } if (shaderMaskSamplerLocation != -1) { @@ -628,8 +651,10 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua DCHECK(shaderMaskTexCoordOffsetLocation != 1); GLC(context(), context()->activeTexture(GL_TEXTURE1)); GLC(context(), context()->uniform1i(shaderMaskSamplerLocation, 1)); - GLC(context(), context()->uniform2f(shaderMaskTexCoordOffsetLocation, quad->mask_uv_rect.x(), quad->mask_uv_rect.y())); - GLC(context(), context()->uniform2f(shaderMaskTexCoordScaleLocation, quad->mask_uv_rect.width(), quad->mask_uv_rect.height())); + GLC(context(), context()->uniform2f(shaderMaskTexCoordOffsetLocation, + quad->mask_uv_rect.x(), quad->mask_uv_rect.y())); + GLC(context(), context()->uniform2f(shaderMaskTexCoordScaleLocation, + quad->mask_uv_rect.width() / tex_scale_x, quad->mask_uv_rect.height() / tex_scale_y)); m_resourceProvider->bindForSampling(quad->mask_resource_id, GL_TEXTURE_2D, GL_LINEAR); GLC(context(), context()->activeTexture(GL_TEXTURE0)); } @@ -1232,6 +1257,8 @@ void GLRenderer::copyTextureToFramebuffer(const DrawingFrame& frame, int texture setUseProgram(program->program()); GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0)); + GLC(context(), context()->uniform4f(program->vertexShader().texTransformLocation(), + 0.0f, 0.0f, 1.0f, 1.0f)); setShaderOpacity(1, program->fragmentShader().alphaLocation()); drawQuadGeometry(frame, drawMatrix, rect, program->vertexShader().matrixLocation()); } diff --git a/cc/gl_renderer.h b/cc/gl_renderer.h index 4cfdfc0..54119e3 100644 --- a/cc/gl_renderer.h +++ b/cc/gl_renderer.h @@ -97,7 +97,8 @@ private: void drawCheckerboardQuad(const DrawingFrame&, const CheckerboardDrawQuad*); void drawDebugBorderQuad(const DrawingFrame&, const DebugBorderDrawQuad*); scoped_ptr<ScopedResource> drawBackgroundFilters( - DrawingFrame&, const RenderPassDrawQuad*, const WebKit::WebFilterOperations&, + DrawingFrame&, const RenderPassDrawQuad*, + const WebKit::WebFilterOperations&, const gfx::Transform& contentsDeviceTransform, const gfx::Transform& contentsDeviceTransformInverse); void drawRenderPassQuad(DrawingFrame&, const RenderPassDrawQuad*); @@ -156,8 +157,8 @@ private: typedef ProgramBinding<VertexShaderPosTex, FragmentShaderCheckerboard> TileCheckerboardProgram; // Render surface shaders. - typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexAlpha> RenderPassProgram; - typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexAlphaMask> RenderPassMaskProgram; + typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexAlpha> RenderPassProgram; + typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexAlphaMask> RenderPassMaskProgram; typedef ProgramBinding<VertexShaderQuad, FragmentShaderRGBATexAlphaAA> RenderPassProgramAA; typedef ProgramBinding<VertexShaderQuad, FragmentShaderRGBATexAlphaMaskAA> RenderPassMaskProgramAA; diff --git a/cc/gl_renderer_pixeltest.cc b/cc/gl_renderer_pixeltest.cc index feadf37..ee2a015 100644 --- a/cc/gl_renderer_pixeltest.cc +++ b/cc/gl_renderer_pixeltest.cc @@ -43,7 +43,6 @@ class FakeRendererClient : public RendererClient { virtual bool hasImplThread() const OVERRIDE { return false; } }; - class GLRendererPixelTest : public testing::Test { protected: GLRendererPixelTest() {} @@ -55,24 +54,38 @@ class GLRendererPixelTest : public testing::Test { renderer_ = GLRenderer::create(&fake_client_, resource_provider_.get()); } + bool PixelsMatchReference(FilePath ref_file, gfx::Rect viewport_rect) { + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + viewport_rect.width(), viewport_rect.height()); + bitmap.allocPixels(); + unsigned char* pixels = static_cast<unsigned char*>(bitmap.getPixels()); + renderer_->getFramebufferPixels(pixels, viewport_rect); + + FilePath test_data_dir; + if (!PathService::Get(cc::test::DIR_TEST_DATA, &test_data_dir)) + return false; + + return test::IsSameAsPNGFile(bitmap, test_data_dir.Append(ref_file)); + } + scoped_ptr<OutputSurface> output_surface_; FakeRendererClient fake_client_; scoped_ptr<ResourceProvider> resource_provider_; scoped_ptr<GLRenderer> renderer_; }; -#if !defined(OS_ANDROID) -TEST_F(GLRendererPixelTest, simpleGreenRect) { - gfx::Rect rect(0, 0, 200, 200); - - RenderPass::Id id(1, 1); +scoped_ptr<RenderPass> CreateTestRenderPass(RenderPass::Id id, gfx::Rect rect) { + scoped_ptr<RenderPass> pass = RenderPass::Create(); const gfx::Rect output_rect = rect; const gfx::RectF damage_rect = rect; const gfx::Transform transform_to_root_target; - scoped_ptr<RenderPass> pass = RenderPass::Create(); pass->SetNew(id, output_rect, damage_rect, transform_to_root_target); + return pass.Pass(); +} - const gfx::Transform content_to_target_transform; +scoped_ptr<SharedQuadState> CreateTestSharedQuadState( + gfx::Transform content_to_target_transform, gfx::Rect rect) { const gfx::Rect visible_content_rect = rect; const gfx::Rect clipped_rect_in_target = rect; const gfx::Rect clip_rect = rect; @@ -85,6 +98,34 @@ TEST_F(GLRendererPixelTest, simpleGreenRect) { clip_rect, is_clipped, opacity); + return shared_state.Pass(); +} + +scoped_ptr<DrawQuad> CreateTestRenderPassDrawQuad( + SharedQuadState* shared_state, gfx::Rect rect, RenderPass::Id pass_id) { + scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create(); + quad->SetNew(shared_state, + rect, + pass_id, + false, // is_replica + 0, // mask_resource_id + rect, // contents_changed_since_last_frame + gfx::RectF()); // mask_uv_rect + + return quad.PassAs<DrawQuad>(); +} + + +#if !defined(OS_ANDROID) +TEST_F(GLRendererPixelTest, simpleGreenRect) { + gfx::Rect rect(0, 0, 200, 200); + + RenderPass::Id id(1, 1); + scoped_ptr<RenderPass> pass = CreateTestRenderPass(id, rect); + + gfx::Transform content_to_target_transform; + scoped_ptr<SharedQuadState> shared_state = + CreateTestSharedQuadState(content_to_target_transform, rect); scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create(); color_quad->SetNew(shared_state.get(), rect, SK_ColorGREEN); @@ -98,17 +139,55 @@ TEST_F(GLRendererPixelTest, simpleGreenRect) { renderer_->drawFrame(pass_list, pass_map); - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200); - bitmap.allocPixels(); - unsigned char* pixels = static_cast<unsigned char*>(bitmap.getPixels()); - renderer_->getFramebufferPixels(pixels, gfx::Rect(0, 0, 200, 200)); - - FilePath test_data_dir; - ASSERT_TRUE(PathService::Get(cc::test::DIR_TEST_DATA, &test_data_dir)); - // test::WritePNGFile(bitmap, test_data_dir.AppendASCII("green.png")); - EXPECT_TRUE(test::IsSameAsPNGFile(bitmap, - test_data_dir.AppendASCII("green.png"))); + EXPECT_TRUE(PixelsMatchReference(FilePath(FILE_PATH_LITERAL("green.png")), + rect)); +} + +TEST_F(GLRendererPixelTest, RenderPassChangesSize) { + gfx::Rect viewport_rect(200, 200); + + RenderPass::Id root_pass_id(1, 1); + scoped_ptr<RenderPass> root_pass = + CreateTestRenderPass(root_pass_id, viewport_rect); + + RenderPass::Id child_pass_id(2, 2); + gfx::Rect pass_rect(200, 200); + scoped_ptr<RenderPass> child_pass = + CreateTestRenderPass(child_pass_id, pass_rect); + + gfx::Transform content_to_target_transform; + scoped_ptr<SharedQuadState> shared_state = + CreateTestSharedQuadState(content_to_target_transform, viewport_rect); + + scoped_ptr<SolidColorDrawQuad> blue = SolidColorDrawQuad::Create(); + blue->SetNew(shared_state.get(), gfx::Rect(0, 0, 100, 200), SK_ColorBLUE); + scoped_ptr<SolidColorDrawQuad> yellow = SolidColorDrawQuad::Create(); + yellow->SetNew(shared_state.get(), gfx::Rect(100, 0, 100, 200), SK_ColorYELLOW); + + child_pass->quad_list.append(blue.PassAs<DrawQuad>()); + child_pass->quad_list.append(yellow.PassAs<DrawQuad>()); + + scoped_ptr<SharedQuadState> pass_shared_state = + CreateTestSharedQuadState(gfx::Transform(), pass_rect); + root_pass->quad_list.append( + CreateTestRenderPassDrawQuad(pass_shared_state.get(), + pass_rect, + child_pass_id)); + + RenderPassList pass_list; + pass_list.push_back(child_pass.get()); + pass_list.push_back(root_pass.get()); + + RenderPassIdHashMap pass_map; + pass_map.add(child_pass_id, child_pass.Pass()); + pass_map.add(root_pass_id, root_pass.Pass()); + + renderer_->setEnlargePassTextureAmountForTesting(gfx::Vector2d(50, 75)); + renderer_->decideRenderPassAllocationsForFrame(pass_list); + renderer_->drawFrame(pass_list, pass_map); + + EXPECT_TRUE(PixelsMatchReference( + FilePath(FILE_PATH_LITERAL("blue_yellow.png")), viewport_rect)); } #endif diff --git a/cc/shader.cc b/cc/shader.cc index c84d88a..074f41a 100644 --- a/cc/shader.cc +++ b/cc/shader.cc @@ -171,12 +171,6 @@ std::string VertexShaderPosTexTransform::getShaderString() const ); } -VertexShaderQuad::VertexShaderQuad() - : m_matrixLocation(-1) - , m_pointLocation(-1) -{ -} - std::string VertexShaderPosTexIdentity::getShaderString() const { return SHADER( @@ -190,19 +184,30 @@ std::string VertexShaderPosTexIdentity::getShaderString() const ); } +VertexShaderQuad::VertexShaderQuad() + : m_matrixLocation(-1) + , m_pointLocation(-1) + , m_texScaleLocation(-1) +{ +} + void VertexShaderQuad::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex) { static const char* shaderUniforms[] = { "matrix", "point", + "texScale", }; - int locations[2]; + int locations[3]; getProgramUniformLocations(context, program, shaderUniforms, arraysize(shaderUniforms), arraysize(locations), locations, usingBindUniform, baseUniformIndex); m_matrixLocation = locations[0]; m_pointLocation = locations[1]; - DCHECK(m_matrixLocation != -1 && m_pointLocation != -1); + m_texScaleLocation = locations[2]; + DCHECK_NE(m_matrixLocation, -1); + DCHECK_NE(m_pointLocation, -1); + DCHECK_NE(m_texScaleLocation, -1); } std::string VertexShaderQuad::getShaderString() const @@ -212,6 +217,7 @@ std::string VertexShaderQuad::getShaderString() const attribute vec2 a_texCoord; uniform mat4 matrix; uniform vec2 point[4]; + uniform vec2 texScale; varying vec2 v_texCoord; void main() { @@ -222,7 +228,7 @@ std::string VertexShaderQuad::getShaderString() const pos.xy += (a_texCoord.x * a_texCoord.y) * point[2]; pos.xy += (complement.x * a_texCoord.y) * point[3]; gl_Position = matrix * pos; - v_texCoord = pos.xy + vec2(0.5); + v_texCoord = (pos.xy + vec2(0.5)) * texScale; } ); } diff --git a/cc/shader.h b/cc/shader.h index 67e93cb..a1aec88 100644 --- a/cc/shader.h +++ b/cc/shader.h @@ -85,10 +85,12 @@ public: int matrixLocation() const { return m_matrixLocation; } int pointLocation() const { return m_pointLocation; } + int texScaleLocation() const { return m_texScaleLocation; } private: int m_matrixLocation; int m_pointLocation; + int m_texScaleLocation; }; class VertexShaderTile { |