summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-14 07:13:48 +0000
committerjamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-14 07:13:48 +0000
commit66321643bdea820f7682d79dee3663610f26b95d (patch)
tree9f0302ed0ba4f944b52b780053cda804168e7791
parentcf64404b033f544103752869df8ec97c3be10a5d (diff)
downloadchromium_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.cc14
-rw-r--r--cc/direct_renderer.h5
-rw-r--r--cc/gl_renderer.cc33
-rw-r--r--cc/gl_renderer.h7
-rw-r--r--cc/gl_renderer_pixeltest.cc117
-rw-r--r--cc/shader.cc24
-rw-r--r--cc/shader.h2
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 {