Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3023)

Unified Diff: cc/gl_renderer.cc

Issue 11415161: Texture Draw Calls Coalescing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: moved { to line above Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/gl_renderer.h ('k') | cc/gl_renderer_draw_cache.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/gl_renderer.cc
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc
index 94f8d83124f945b5118af3f5b1d07a7bbcdc5fba..c2646c10451fe72cb824a03a96b00cd79c142369 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -241,8 +241,10 @@ void GLRenderer::beginDrawingFrame(DrawingFrame& frame)
GLC(m_context, m_context->disable(GL_CULL_FACE));
GLC(m_context, m_context->colorMask(true, true, true, true));
GLC(m_context, m_context->enable(GL_BLEND));
+ m_blendShadow = true;
GLC(m_context, m_context->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
GLC(context(), context()->activeTexture(GL_TEXTURE0));
+ m_programShadow = 0;
}
void GLRenderer::doNoOp()
@@ -254,11 +256,10 @@ void GLRenderer::doNoOp()
void GLRenderer::drawQuad(DrawingFrame& frame, const DrawQuad* quad)
{
DCHECK(quad->rect.Contains(quad->visible_rect));
-
- if (quad->ShouldDrawWithBlending())
- GLC(m_context, m_context->enable(GL_BLEND));
- else
- GLC(m_context, m_context->disable(GL_BLEND));
+ if (quad->material != DrawQuad::TEXTURE_CONTENT) {
+ flushTextureQuadCache();
+ setBlendEnabled(quad->ShouldDrawWithBlending());
+ }
switch (quad->material) {
case DrawQuad::INVALID:
@@ -283,7 +284,7 @@ void GLRenderer::drawQuad(DrawingFrame& frame, const DrawQuad* quad)
drawStreamVideoQuad(frame, StreamVideoDrawQuad::MaterialCast(quad));
break;
case DrawQuad::TEXTURE_CONTENT:
- drawTextureQuad(frame, TextureDrawQuad::MaterialCast(quad));
+ enqueueTextureQuad(frame, TextureDrawQuad::MaterialCast(quad));
break;
case DrawQuad::TILED_CONTENT:
drawTileQuad(frame, TileDrawQuad::MaterialCast(quad));
@@ -298,7 +299,7 @@ void GLRenderer::drawCheckerboardQuad(const DrawingFrame& frame, const Checkerbo
{
const TileCheckerboardProgram* program = tileCheckerboardProgram();
DCHECK(program && (program->initialized() || isContextLost()));
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
SkColor color = quad->color;
GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), SkColorGetR(color) / 255.0, SkColorGetG(color) / 255.0, SkColorGetB(color) / 255.0, 1));
@@ -324,7 +325,7 @@ void GLRenderer::drawDebugBorderQuad(const DrawingFrame& frame, const DebugBorde
static float glMatrix[16];
const SolidColorProgram* program = solidColorProgram();
DCHECK(program && (program->initialized() || isContextLost()));
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
// Use the full quadRect for debug quads to not move the edges based on partial swaps.
const gfx::Rect& layerRect = quad->rect;
@@ -342,7 +343,7 @@ void GLRenderer::drawDebugBorderQuad(const DrawingFrame& frame, const DebugBorde
GLC(context(), context()->lineWidth(quad->width));
// The indices for the line are stored in the same array as the triangle indices.
- GLC(context(), context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
+ GLC(context(), context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 0));
}
static WebGraphicsContext3D* getFilterContext(bool hasImplThread)
@@ -587,7 +588,7 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua
int shaderAlphaLocation = -1;
if (useAA && maskTextureId) {
const RenderPassMaskProgramAA* program = renderPassMaskProgramAA();
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
shaderQuadLocation = program->vertexShader().pointLocation();
@@ -599,7 +600,7 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua
shaderAlphaLocation = program->fragmentShader().alphaLocation();
} else if (!useAA && maskTextureId) {
const RenderPassMaskProgram* program = renderPassMaskProgram();
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
@@ -609,7 +610,7 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua
shaderAlphaLocation = program->fragmentShader().alphaLocation();
} else if (useAA && !maskTextureId) {
const RenderPassProgramAA* program = renderPassProgramAA();
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
shaderQuadLocation = program->vertexShader().pointLocation();
@@ -618,7 +619,7 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua
shaderAlphaLocation = program->fragmentShader().alphaLocation();
} else {
const RenderPassProgram* program = renderPassProgram();
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
shaderMatrixLocation = program->vertexShader().matrixLocation();
@@ -660,7 +661,7 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua
void GLRenderer::drawSolidColorQuad(const DrawingFrame& frame, const SolidColorDrawQuad* quad)
{
const SolidColorProgram* program = solidColorProgram();
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
SkColor color = quad->color;
float opacity = quad->opacity();
@@ -778,7 +779,7 @@ void GLRenderer::drawTileQuad(const DrawingFrame& frame, const TileDrawQuad* qua
}
}
- GLC(context(), context()->useProgram(uniforms.program));
+ setUseProgram(uniforms.program);
GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0));
ResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resource_id);
GLC(context(), context()->bindTexture(GL_TEXTURE_2D, quadResourceLock.textureId()));
@@ -895,7 +896,7 @@ void GLRenderer::drawYUVVideoQuad(const DrawingFrame& frame, const YUVVideoDrawQ
GLC(context(), context()->activeTexture(GL_TEXTURE3));
GLC(context(), context()->bindTexture(GL_TEXTURE_2D, vPlaneLock.textureId()));
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
GLC(context(), context()->uniform2f(program->vertexShader().texScaleLocation(), quad->tex_scale.width(), quad->tex_scale.height()));
GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1));
@@ -938,7 +939,7 @@ void GLRenderer::drawStreamVideoQuad(const DrawingFrame& frame, const StreamVide
DCHECK(m_capabilities.usingEglImage);
const VideoStreamTextureProgram* program = videoStreamTextureProgram();
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
toGLMatrix(&glMatrix[0], quad->matrix);
GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, glMatrix));
@@ -977,6 +978,102 @@ struct TexTransformTextureProgramBinding : TextureProgramBinding {
int texTransformLocation;
};
+void GLRenderer::flushTextureQuadCache()
+{
+ // Check to see if we have anything to draw.
+ if (m_drawCache.program_id == 0)
+ return;
+
+ // Set the correct blending mode.
+ setBlendEnabled(m_drawCache.needs_blending);
+
+ // Bind the program to the GL state.
+ setUseProgram(m_drawCache.program_id);
+
+ // Assume the current active textures is 0.
+ ResourceProvider::ScopedReadLockGL lockedQuad(m_resourceProvider, m_drawCache.resource_id);
+ GLC(context(), context()->bindTexture(GL_TEXTURE_2D, lockedQuad.textureId()));
+
+ // set up premultiplied alpha.
+ if (!m_drawCache.use_premultiplied_alpha) {
+ // As it turns out, the premultiplied alpha blending function (ONE, ONE_MINUS_SRC_ALPHA)
+ // will never cause the alpha channel to be set to anything less than 1.0 if it is
+ // initialized to that value! Therefore, premultipliedAlpha being false is the first
+ // situation we can generally see an alpha channel less than 1.0 coming out of the
+ // compositor. This is causing platform differences in some layout tests (see
+ // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use a separate
+ // blend function for the alpha channel to avoid modifying it. Don't use colorMask for this
+ // as it has performance implications on some platforms.
+ GLC(context(), context()->blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE));
+ }
+
+ // Set the shader opacity.
+ setShaderOpacity(m_drawCache.alpha, m_drawCache.alpha_location);
+
+ COMPILE_ASSERT(sizeof(Float4) == 4 * sizeof(float), struct_is_densely_packed);
+ COMPILE_ASSERT(sizeof(Float16) == 16 * sizeof(float), struct_is_densely_packed);
+
+ // Upload the tranforms for both points and uvs.
+ GLC(m_context, m_context->uniformMatrix4fv((int)m_drawCache.matrix_location, (int)m_drawCache.matrix_data.size(), false, (float*)&m_drawCache.matrix_data.front()));
+ GLC(m_context, m_context->uniform4fv((int)m_drawCache.uv_xform_location, (int)m_drawCache.uv_xform_data.size(), (float*)&m_drawCache.uv_xform_data.front()));
+
+ // Draw the quads!
+ GLC(m_context, m_context->drawElements(GL_TRIANGLES, 6 * m_drawCache.matrix_data.size(), GL_UNSIGNED_SHORT, 0));
+
+ // Clean up after ourselves (reset state set above).
+ if (!m_drawCache.use_premultiplied_alpha)
+ GLC(m_context, m_context->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
+
+ // Clear the cache.
+ m_drawCache.program_id = 0;
+ m_drawCache.uv_xform_data.resize(0);
+ m_drawCache.matrix_data.resize(0);
+}
+
+void GLRenderer::enqueueTextureQuad(const DrawingFrame& frame, const TextureDrawQuad* quad)
+{
+ // Choose the correcte texture program binding
+ TexTransformTextureProgramBinding binding;
+ if (quad->flipped)
+ binding.set(textureProgramFlip(), context());
+ else
+ binding.set(textureProgram(), context());
+
+ int resourceID = quad->resource_id;
+
+ if (m_drawCache.program_id != binding.programId ||
+ m_drawCache.resource_id != resourceID ||
+ m_drawCache.alpha != quad->opacity() ||
+ m_drawCache.use_premultiplied_alpha != quad->premultiplied_alpha ||
+ m_drawCache.needs_blending != quad->ShouldDrawWithBlending() ||
+ m_drawCache.matrix_data.size() >= 8) {
+ flushTextureQuadCache();
+ m_drawCache.program_id = binding.programId;
+ m_drawCache.resource_id = resourceID;
+ m_drawCache.alpha = quad->opacity();
+ m_drawCache.use_premultiplied_alpha = quad->premultiplied_alpha;
+ m_drawCache.needs_blending = quad->ShouldDrawWithBlending();
+
+ m_drawCache.alpha_location = binding.alphaLocation;
+ m_drawCache.uv_xform_location = binding.texTransformLocation;
+ m_drawCache.matrix_location = binding.matrixLocation;
+ }
+
+ // Generate the uv-transform
+ const gfx::RectF& uvRect = quad->uv_rect;
+ Float4 uv = {uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height()};
+ m_drawCache.uv_xform_data.push_back(uv);
+
+ // Generate the transform matrix
+ gfx::Transform quadRectMatrix;
+ quadRectTransform(&quadRectMatrix, quad->quadTransform(), quad->rect);
+ quadRectMatrix = frame.projectionMatrix * quadRectMatrix;
+
+ Float16 m;
+ quadRectMatrix.matrix().asColMajorf(m.data);
+ m_drawCache.matrix_data.push_back(m);
+}
+
void GLRenderer::drawTextureQuad(const DrawingFrame& frame, const TextureDrawQuad* quad)
{
TexTransformTextureProgramBinding binding;
@@ -984,7 +1081,7 @@ void GLRenderer::drawTextureQuad(const DrawingFrame& frame, const TextureDrawQua
binding.set(textureProgramFlip(), context());
else
binding.set(textureProgram(), context());
- GLC(context(), context()->useProgram(binding.programId));
+ setUseProgram(binding.programId);
GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
const gfx::RectF& uvRect = quad->uv_rect;
GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height()));
@@ -1016,7 +1113,7 @@ void GLRenderer::drawIOSurfaceQuad(const DrawingFrame& frame, const IOSurfaceDra
TexTransformTextureProgramBinding binding;
binding.set(textureIOSurfaceProgram(), context());
- GLC(context(), context()->useProgram(binding.programId));
+ setUseProgram(binding.programId);
GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
if (quad->orientation == IOSurfaceDrawQuad::FLIPPED)
GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, quad->io_surface_size.height(), quad->io_surface_size.width(), quad->io_surface_size.height() * -1.0));
@@ -1037,6 +1134,12 @@ void GLRenderer::finishDrawingFrame(DrawingFrame& frame)
m_swapBufferRect.Union(gfx::ToEnclosingRect(frame.rootDamageRect));
GLC(m_context, m_context->disable(GL_BLEND));
+ m_blendShadow = false;
+}
+
+void GLRenderer::finishDrawingQuadList()
+{
+ flushTextureQuadCache();
}
bool GLRenderer::flippedFramebuffer() const
@@ -1049,6 +1152,7 @@ void GLRenderer::ensureScissorTestEnabled()
if (m_isScissorEnabled)
return;
+ flushTextureQuadCache();
GLC(m_context, m_context->enable(GL_SCISSOR_TEST));
m_isScissorEnabled = true;
}
@@ -1058,6 +1162,7 @@ void GLRenderer::ensureScissorTestDisabled()
if (!m_isScissorEnabled)
return;
+ flushTextureQuadCache();
GLC(m_context, m_context->disable(GL_SCISSOR_TEST));
m_isScissorEnabled = false;
}
@@ -1090,6 +1195,26 @@ void GLRenderer::setShaderOpacity(float opacity, int alphaLocation)
GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
}
+void GLRenderer::setBlendEnabled(bool enabled)
+{
+ if (enabled == m_blendShadow)
+ return;
+
+ if (enabled)
+ GLC(m_context, m_context->enable(GL_BLEND));
+ else
+ GLC(m_context, m_context->disable(GL_BLEND));
+ m_blendShadow = enabled;
+}
+
+void GLRenderer::setUseProgram(unsigned program)
+{
+ if (program == m_programShadow)
+ return;
+ GLC(m_context, m_context->useProgram(program));
+ m_programShadow = program;
+}
+
void GLRenderer::drawQuadGeometry(const DrawingFrame& frame, const gfx::Transform& drawTransform, const gfx::RectF& quadRect, int matrixLocation)
{
gfx::Transform quadRectMatrix;
@@ -1107,7 +1232,7 @@ void GLRenderer::copyTextureToFramebuffer(const DrawingFrame& frame, int texture
GLC(context(), context()->bindTexture(GL_TEXTURE_2D, textureId));
- GLC(context(), context()->useProgram(program->program()));
+ setUseProgram(program->program());
GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
setShaderOpacity(1, program->fragmentShader().alphaLocation());
drawQuadGeometry(frame, drawMatrix, rect, program->vertexShader().matrixLocation());
@@ -1358,6 +1483,7 @@ void GLRenderer::setScissorTestRect(const gfx::Rect& scissorRect)
return;
m_scissorRect = scissorRect;
+ flushTextureQuadCache();
GLC(m_context, m_context->scissor(scissorRect.x(), scissorRect.y(), scissorRect.width(), scissorRect.height()));
}
@@ -1527,6 +1653,7 @@ const GLRenderer::TextureProgram* GLRenderer::textureProgram()
if (!m_textureProgram->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::textureProgram::initialize");
m_textureProgram->initialize(m_context, m_isUsingBindUniform);
+ GLC(context(), context()->uniform1i(m_textureProgram.get()->fragmentShader().samplerLocation(), 0));
}
return m_textureProgram.get();
}
@@ -1538,6 +1665,7 @@ const GLRenderer::TextureProgramFlip* GLRenderer::textureProgramFlip()
if (!m_textureProgramFlip->initialized()) {
TRACE_EVENT0("cc", "GLRenderer::textureProgramFlip::initialize");
m_textureProgramFlip->initialize(m_context, m_isUsingBindUniform);
+ GLC(context(), context()->uniform1i(m_textureProgramFlip.get()->fragmentShader().samplerLocation(), 0));
}
return m_textureProgramFlip.get();
}
« no previous file with comments | « cc/gl_renderer.h ('k') | cc/gl_renderer_draw_cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698