Index: cc/output/gl_renderer.cc |
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc |
index 6b15faf4c8f1c9dee3218684b5089464dadf0396..24e9f3097348cfca1d38b08d199347e6d77c7c50 100644 |
--- a/cc/output/gl_renderer.cc |
+++ b/cc/output/gl_renderer.cc |
@@ -123,6 +123,44 @@ SamplerType SamplerTypeFromTextureTarget(GLenum target) { |
} |
} |
+BlendMode BlendModeFromSkXfermode(SkXfermode::Mode mode) { |
+ switch (mode) { |
+ case SkXfermode::kSrcOver_Mode: |
+ return BlendModeNormal; |
+ case SkXfermode::kOverlay_Mode: |
+ return BlendModeOverlay; |
+ case SkXfermode::kDarken_Mode: |
+ return BlendModeDarken; |
+ case SkXfermode::kLighten_Mode: |
+ return BlendModeLighten; |
+ case SkXfermode::kColorDodge_Mode: |
+ return BlendModeColorDodge; |
+ case SkXfermode::kColorBurn_Mode: |
+ return BlendModeColorBurn; |
+ case SkXfermode::kHardLight_Mode: |
+ return BlendModeHardLight; |
+ case SkXfermode::kSoftLight_Mode: |
+ return BlendModeSoftLight; |
+ case SkXfermode::kDifference_Mode: |
+ return BlendModeDifference; |
+ case SkXfermode::kExclusion_Mode: |
+ return BlendModeExclusion; |
+ case SkXfermode::kMultiply_Mode: |
+ return BlendModeMultiply; |
+ case SkXfermode::kHue_Mode: |
+ return BlendModeHue; |
+ case SkXfermode::kSaturation_Mode: |
+ return BlendModeSaturation; |
+ case SkXfermode::kColor_Mode: |
+ return BlendModeColor; |
+ case SkXfermode::kLuminosity_Mode: |
+ return BlendModeLuminosity; |
+ default: |
+ NOTREACHED(); |
+ return BlendModeNormal; |
+ } |
+} |
+ |
// Smallest unit that impact anti-aliasing output. We use this to |
// determine when anti-aliasing is unnecessary. |
const float kAntiAliasingEpsilon = 1.0f / 1024.0f; |
@@ -723,140 +761,6 @@ void GLRenderer::RestoreBlendFuncToDefault(SkXfermode::Mode blend_mode) { |
GLC(gl_, gl_->BlendEquation(GL_FUNC_ADD)); |
} |
-static skia::RefPtr<SkImage> ApplyBlendModeWithBackdrop( |
- scoped_ptr<GLRenderer::ScopedUseGrContext> use_gr_context, |
- ResourceProvider* resource_provider, |
- skia::RefPtr<SkImage> source_bitmap_with_filters, |
- ScopedResource* source_texture_resource, |
- ScopedResource* background_texture_resource, |
- SkXfermode::Mode blend_mode) { |
- if (!use_gr_context) |
- return source_bitmap_with_filters; |
- |
- DCHECK(background_texture_resource); |
- DCHECK(source_texture_resource); |
- |
- gfx::Size source_size = source_texture_resource->size(); |
- gfx::Size background_size = background_texture_resource->size(); |
- |
- DCHECK_LE(background_size.width(), source_size.width()); |
- DCHECK_LE(background_size.height(), source_size.height()); |
- |
- int source_texture_with_filters_id; |
- scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; |
- if (source_bitmap_with_filters) { |
- DCHECK_EQ(source_size.width(), source_bitmap_with_filters->width()); |
- DCHECK_EQ(source_size.height(), source_bitmap_with_filters->height()); |
- GrTexture* texture = |
- reinterpret_cast<GrTexture*>(source_bitmap_with_filters->getTexture()); |
- source_texture_with_filters_id = texture->getTextureHandle(); |
- } else { |
- lock.reset(new ResourceProvider::ScopedReadLockGL( |
- resource_provider, source_texture_resource->id())); |
- source_texture_with_filters_id = lock->texture_id(); |
- } |
- |
- ResourceProvider::ScopedReadLockGL lock_background( |
- resource_provider, background_texture_resource->id()); |
- |
- // Wrap the source texture in a Ganesh platform texture. |
- GrBackendTextureDesc backend_texture_description; |
- backend_texture_description.fConfig = kSkia8888_GrPixelConfig; |
- backend_texture_description.fOrigin = kBottomLeft_GrSurfaceOrigin; |
- |
- backend_texture_description.fWidth = source_size.width(); |
- backend_texture_description.fHeight = source_size.height(); |
- backend_texture_description.fTextureHandle = source_texture_with_filters_id; |
- skia::RefPtr<GrTexture> source_texture = |
- skia::AdoptRef(use_gr_context->context()->wrapBackendTexture( |
- backend_texture_description)); |
- if (!source_texture) { |
- TRACE_EVENT_INSTANT0( |
- "cc", |
- "ApplyBlendModeWithBackdrop wrap source texture failed", |
- TRACE_EVENT_SCOPE_THREAD); |
- return skia::RefPtr<SkImage>(); |
- } |
- |
- backend_texture_description.fWidth = background_size.width(); |
- backend_texture_description.fHeight = background_size.height(); |
- backend_texture_description.fTextureHandle = lock_background.texture_id(); |
- skia::RefPtr<GrTexture> background_texture = |
- skia::AdoptRef(use_gr_context->context()->wrapBackendTexture( |
- backend_texture_description)); |
- if (!background_texture) { |
- TRACE_EVENT_INSTANT0( |
- "cc", |
- "ApplyBlendModeWithBackdrop wrap background texture failed", |
- TRACE_EVENT_SCOPE_THREAD); |
- return skia::RefPtr<SkImage>(); |
- } |
- |
- SkImageInfo source_info = |
- SkImageInfo::MakeN32Premul(source_size.width(), source_size.height()); |
- // Place the platform texture inside an SkBitmap. |
- SkBitmap source; |
- source.setInfo(source_info); |
- skia::RefPtr<SkGrPixelRef> source_pixel_ref = |
- skia::AdoptRef(new SkGrPixelRef(source_info, source_texture.get())); |
- source.setPixelRef(source_pixel_ref.get()); |
- |
- SkImageInfo background_info = SkImageInfo::MakeN32Premul( |
- background_size.width(), background_size.height()); |
- |
- SkBitmap background; |
- background.setInfo(background_info); |
- skia::RefPtr<SkGrPixelRef> background_pixel_ref = |
- skia::AdoptRef(new SkGrPixelRef( |
- background_info, background_texture.get())); |
- background.setPixelRef(background_pixel_ref.get()); |
- |
- // Create a scratch texture for backing store. |
- GrTextureDesc desc; |
- desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; |
- desc.fSampleCnt = 0; |
- desc.fWidth = source.width(); |
- desc.fHeight = source.height(); |
- desc.fConfig = kSkia8888_GrPixelConfig; |
- desc.fOrigin = kBottomLeft_GrSurfaceOrigin; |
- skia::RefPtr<GrTexture> backing_store = |
- skia::AdoptRef(use_gr_context->context()->refScratchTexture( |
- desc, GrContext::kExact_ScratchTexMatch)); |
- if (!backing_store) { |
- TRACE_EVENT_INSTANT0( |
- "cc", |
- "ApplyBlendModeWithBackdrop scratch texture allocation failed", |
- TRACE_EVENT_SCOPE_THREAD); |
- return source_bitmap_with_filters; |
- } |
- |
- // Create a device and canvas using that backing store. |
- skia::RefPtr<SkSurface> surface = skia::AdoptRef( |
- SkSurface::NewRenderTargetDirect(backing_store->asRenderTarget())); |
- if (!surface) |
- return skia::RefPtr<SkImage>(); |
- skia::RefPtr<SkCanvas> canvas = skia::SharePtr(surface->getCanvas()); |
- |
- // Draw the source bitmap through the filter to the canvas. |
- canvas->clear(SK_ColorTRANSPARENT); |
- canvas->drawSprite(background, 0, 0); |
- SkPaint paint; |
- paint.setXfermodeMode(blend_mode); |
- canvas->drawSprite(source, 0, 0, &paint); |
- |
- skia::RefPtr<SkImage> image = skia::AdoptRef(surface->newImageSnapshot()); |
- if (!image || !image->getTexture()) { |
- return skia::RefPtr<SkImage>(); |
- } |
- |
- // Flush the GrContext to ensure all buffered GL calls are drawn to the |
- // backing store before we access and return it, and have cc begin using the |
- // GL context again. |
- canvas->flush(); |
- |
- return image; |
-} |
- |
bool GLRenderer::ShouldApplyBackgroundFilters(DrawingFrame* frame, |
const RenderPassDrawQuad* quad) { |
if (quad->background_filters.IsEmpty()) |
@@ -878,7 +782,8 @@ bool GLRenderer::ShouldApplyBackgroundFilters(DrawingFrame* frame, |
gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad( |
DrawingFrame* frame, |
const RenderPassDrawQuad* quad, |
- const gfx::Transform& contents_device_transform) { |
+ const gfx::Transform& contents_device_transform, |
+ bool use_aa) { |
gfx::Rect backdrop_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( |
contents_device_transform, SharedGeometryQuad().BoundingBox())); |
@@ -888,6 +793,11 @@ gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad( |
backdrop_rect.Inset(-left, -top, -right, -bottom); |
} |
+ if (!backdrop_rect.IsEmpty() && use_aa) { |
+ const int kOutsetForAntialiasing = 1; |
+ backdrop_rect.Inset(-kOutsetForAntialiasing, -kOutsetForAntialiasing); |
+ } |
+ |
backdrop_rect.Intersect( |
MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); |
return backdrop_rect; |
@@ -932,7 +842,6 @@ GLRenderer::ApplyInverseTransformForBackgroundFilters( |
DrawingFrame* frame, |
const RenderPassDrawQuad* quad, |
const gfx::Transform& contents_device_transform_inverse, |
- ScopedResource* device_background_texture, |
skia::RefPtr<SkImage> filtered_device_background, |
const gfx::Rect& backdrop_bounding_rect) { |
// This method draws a background filter, which applies a filter to any pixels |
@@ -959,18 +868,9 @@ GLRenderer::ApplyInverseTransformForBackgroundFilters( |
// TODO(danakj): When this algorithm changes, update |
// LayerTreeHost::PrioritizeTextures() accordingly. |
- DCHECK(device_background_texture); |
+ DCHECK(filtered_device_background); |
- int filtered_device_background_texture_id = 0; |
- scoped_ptr<ResourceProvider::ScopedReadLockGL> lock; |
- if (filtered_device_background) { |
- GrTexture* texture = filtered_device_background->getTexture(); |
- filtered_device_background_texture_id = texture->getTextureHandle(); |
- } else { |
- lock.reset(new ResourceProvider::ScopedReadLockGL( |
- resource_provider_, device_background_texture->id())); |
- filtered_device_background_texture_id = lock->texture_id(); |
- } |
+ GrTexture* texture = filtered_device_background->getTexture(); |
scoped_ptr<ScopedResource> background_texture = |
ScopedResource::Create(resource_provider_); |
@@ -1004,7 +904,7 @@ GLRenderer::ApplyInverseTransformForBackgroundFilters( |
bool flip_vertically = false; |
CopyTextureToFramebuffer(frame, |
- filtered_device_background_texture_id, |
+ texture->getTextureHandle(), |
backdrop_bounding_rect, |
device_to_framebuffer_transform, |
flip_vertically); |
@@ -1020,9 +920,9 @@ GLRenderer::ApplyInverseTransformForBackgroundFilters( |
void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
const RenderPassDrawQuad* quad) { |
SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode; |
- SetBlendEnabled(quad->ShouldDrawWithBlending() || |
- (!IsDefaultBlendMode(blend_mode) && |
- CanApplyBlendModeUsingBlendFunc(blend_mode))); |
+ SetBlendEnabled( |
+ CanApplyBlendModeUsingBlendFunc(blend_mode) && |
+ (quad->ShouldDrawWithBlending() || !IsDefaultBlendMode(blend_mode))); |
ScopedResource* contents_texture = |
render_pass_textures_.get(quad->render_pass_id); |
@@ -1041,44 +941,70 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
if (!contents_device_transform.GetInverse(&contents_device_transform_inverse)) |
return; |
+ bool clipped = false; |
+ gfx::QuadF device_quad = MathUtil::MapQuad( |
+ contents_device_transform, SharedGeometryQuad(), &clipped); |
+ // Use anti-aliasing programs only when necessary. |
+ bool use_aa = |
+ !clipped && |
+ (settings_->force_antialiasing || !device_quad.IsRectilinear() || |
+ !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(), |
+ kAntiAliasingEpsilon)); |
+ |
bool need_background_texture = !CanApplyBlendModeUsingBlendFunc(blend_mode) || |
ShouldApplyBackgroundFilters(frame, quad); |
scoped_ptr<ScopedResource> background_texture; |
+ skia::RefPtr<SkImage> background_image; |
+ gfx::Rect background_rect; |
if (need_background_texture) { |
+ // Compute a bounding box around the pixels that will be visible through |
+ // the quad. |
+ background_rect = GetBackdropBoundingBoxForRenderPassQuad( |
+ frame, quad, contents_device_transform, use_aa); |
+ } |
+ |
+ if (!background_rect.IsEmpty()) { |
// The pixels from the filtered background should completely replace the |
// current pixel values. |
bool disable_blending = blend_enabled(); |
if (disable_blending) |
SetBlendEnabled(false); |
- // Compute a bounding box around the pixels that will be visible through |
- // the quad. |
- gfx::Rect backdrop_rect = GetBackdropBoundingBoxForRenderPassQuad( |
- frame, quad, contents_device_transform); |
- |
// Read the pixels in the bounding box into a buffer R. |
scoped_ptr<ScopedResource> scoped_background_texture = |
- GetBackdropTexture(backdrop_rect); |
+ GetBackdropTexture(background_rect); |
skia::RefPtr<SkImage> background_with_filters; |
- if (ShouldApplyBackgroundFilters(frame, quad)) { |
+ if (ShouldApplyBackgroundFilters(frame, quad) && |
+ scoped_background_texture) { |
// Apply the background filters to R, so that it is applied in the pixels' |
// coordinate space. |
background_with_filters = |
ApplyBackgroundFilters(frame, quad, scoped_background_texture.get()); |
} |
- // Apply the quad's inverse transform to map the pixels in R into the |
- // quad's content space. This implicitly clips R by the content bounds of |
- // the quad since the destination texture has bounds matching the quad's |
- // content. |
- background_texture = ApplyInverseTransformForBackgroundFilters( |
- frame, |
- quad, |
- contents_device_transform_inverse, |
- scoped_background_texture.get(), |
- background_with_filters, |
- backdrop_rect); |
+ |
+ if (CanApplyBlendModeUsingBlendFunc(blend_mode) && |
+ background_with_filters) { |
+ // The background with filters will be copied to the frame buffer. |
+ // Apply the quad's inverse transform to map the pixels in R into the |
+ // quad's content space. This implicitly clips R by the content bounds of |
+ // the quad since the destination texture has bounds matching the quad's |
+ // content. |
+ background_texture = ApplyInverseTransformForBackgroundFilters( |
+ frame, |
+ quad, |
+ contents_device_transform_inverse, |
+ background_with_filters, |
+ background_rect); |
+ } else if (!CanApplyBlendModeUsingBlendFunc(blend_mode)) { |
+ if (background_with_filters) { |
+ // The background with filters will be used as backdrop for blending. |
+ background_image = background_with_filters; |
+ } else { |
+ background_texture = scoped_background_texture.Pass(); |
+ } |
+ } |
if (disable_blending) |
SetBlendEnabled(true); |
@@ -1116,49 +1042,27 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
} |
} |
- if (background_texture) { |
- if (CanApplyBlendModeUsingBlendFunc(blend_mode)) { |
- // Draw the background texture if it has some filters applied. |
- DCHECK(ShouldApplyBackgroundFilters(frame, quad)); |
- DCHECK(background_texture->size() == quad->rect.size()); |
- ResourceProvider::ScopedReadLockGL lock(resource_provider_, |
- background_texture->id()); |
- |
- // The background_texture is oriented the same as the frame buffer. The |
- // transform we are copying with has a vertical flip, so flip the contents |
- // in the shader to maintain orientation |
- bool flip_vertically = true; |
- |
- CopyTextureToFramebuffer(frame, |
- lock.texture_id(), |
- quad->rect, |
- quad->quadTransform(), |
- flip_vertically); |
- } else { |
- // If blending is applied using shaders, the background texture with |
- // filters will be used as backdrop for blending operation, so we don't |
- // need to copy it to the frame buffer. |
- filter_image = |
- ApplyBlendModeWithBackdrop(ScopedUseGrContext::Create(this, frame), |
- resource_provider_, |
- filter_image, |
- contents_texture, |
- background_texture.get(), |
- quad->shared_quad_state->blend_mode); |
- } |
+ if (background_texture && ShouldApplyBackgroundFilters(frame, quad)) { |
+ // Draw the background texture if it has some filters applied. |
+ DCHECK(CanApplyBlendModeUsingBlendFunc(blend_mode)); |
+ DCHECK(background_texture->size() == quad->rect.size()); |
+ ResourceProvider::ScopedReadLockGL lock(resource_provider_, |
+ background_texture->id()); |
+ |
+ // The background_texture is oriented the same as the frame buffer. The |
+ // transform we are copying with has a vertical flip, so flip the contents |
+ // in the shader to maintain orientation |
+ bool flip_vertically = true; |
+ |
+ CopyTextureToFramebuffer(frame, |
+ lock.texture_id(), |
+ quad->rect, |
+ quad->quadTransform(), |
+ flip_vertically); |
} |
- bool clipped = false; |
- gfx::QuadF device_quad = MathUtil::MapQuad( |
- contents_device_transform, SharedGeometryQuad(), &clipped); |
LayerQuad device_layer_bounds(gfx::QuadF(device_quad.BoundingBox())); |
LayerQuad device_layer_edges(device_quad); |
- |
- // Use anti-aliasing programs only when necessary. |
- bool use_aa = |
- !clipped && (!device_quad.IsRectilinear() || |
- !gfx::IsNearestRectWithinDistance(device_quad.BoundingBox(), |
- kAntiAliasingEpsilon)); |
if (use_aa) { |
device_layer_bounds.InflateAntiAliasingDistance(); |
device_layer_edges.InflateAntiAliasingDistance(); |
@@ -1210,10 +1114,17 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
int shader_color_matrix_location = -1; |
int shader_color_offset_location = -1; |
int shader_tex_transform_location = -1; |
+ int shader_backdrop_location = -1; |
+ int shader_backdrop_rect_location = -1; |
+ |
+ BlendMode shader_blend_mode = ((background_texture || background_image) && |
+ !CanApplyBlendModeUsingBlendFunc(blend_mode)) |
+ ? BlendModeFromSkXfermode(blend_mode) |
+ : BlendModeNormal; |
if (use_aa && mask_texture_id && !use_color_matrix) { |
const RenderPassMaskProgramAA* program = |
- GetRenderPassMaskProgramAA(tex_coord_precision); |
+ GetRenderPassMaskProgramAA(tex_coord_precision, shader_blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1230,9 +1141,12 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
shader_alpha_location = program->fragment_shader().alpha_location(); |
shader_tex_transform_location = |
program->vertex_shader().tex_transform_location(); |
+ shader_backdrop_location = program->fragment_shader().backdrop_location(); |
+ shader_backdrop_rect_location = |
+ program->fragment_shader().backdrop_rect_location(); |
} else if (!use_aa && mask_texture_id && !use_color_matrix) { |
const RenderPassMaskProgram* program = |
- GetRenderPassMaskProgram(tex_coord_precision); |
+ GetRenderPassMaskProgram(tex_coord_precision, shader_blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1246,9 +1160,12 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
shader_alpha_location = program->fragment_shader().alpha_location(); |
shader_tex_transform_location = |
program->vertex_shader().tex_transform_location(); |
+ shader_backdrop_location = program->fragment_shader().backdrop_location(); |
+ shader_backdrop_rect_location = |
+ program->fragment_shader().backdrop_rect_location(); |
} else if (use_aa && !mask_texture_id && !use_color_matrix) { |
const RenderPassProgramAA* program = |
- GetRenderPassProgramAA(tex_coord_precision); |
+ GetRenderPassProgramAA(tex_coord_precision, shader_blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1259,9 +1176,13 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
shader_alpha_location = program->fragment_shader().alpha_location(); |
shader_tex_transform_location = |
program->vertex_shader().tex_transform_location(); |
+ shader_backdrop_location = program->fragment_shader().backdrop_location(); |
+ shader_backdrop_rect_location = |
+ program->fragment_shader().backdrop_rect_location(); |
} else if (use_aa && mask_texture_id && use_color_matrix) { |
const RenderPassMaskColorMatrixProgramAA* program = |
- GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision); |
+ GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision, |
+ shader_blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1282,9 +1203,13 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
program->fragment_shader().color_matrix_location(); |
shader_color_offset_location = |
program->fragment_shader().color_offset_location(); |
+ shader_backdrop_location = program->fragment_shader().backdrop_location(); |
+ shader_backdrop_rect_location = |
+ program->fragment_shader().backdrop_rect_location(); |
} else if (use_aa && !mask_texture_id && use_color_matrix) { |
const RenderPassColorMatrixProgramAA* program = |
- GetRenderPassColorMatrixProgramAA(tex_coord_precision); |
+ GetRenderPassColorMatrixProgramAA(tex_coord_precision, |
+ shader_blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1299,9 +1224,13 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
program->fragment_shader().color_matrix_location(); |
shader_color_offset_location = |
program->fragment_shader().color_offset_location(); |
+ shader_backdrop_location = program->fragment_shader().backdrop_location(); |
+ shader_backdrop_rect_location = |
+ program->fragment_shader().backdrop_rect_location(); |
} else if (!use_aa && mask_texture_id && use_color_matrix) { |
const RenderPassMaskColorMatrixProgram* program = |
- GetRenderPassMaskColorMatrixProgram(tex_coord_precision); |
+ GetRenderPassMaskColorMatrixProgram(tex_coord_precision, |
+ shader_blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1319,9 +1248,12 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
program->fragment_shader().color_matrix_location(); |
shader_color_offset_location = |
program->fragment_shader().color_offset_location(); |
+ shader_backdrop_location = program->fragment_shader().backdrop_location(); |
+ shader_backdrop_rect_location = |
+ program->fragment_shader().backdrop_rect_location(); |
} else if (!use_aa && !mask_texture_id && use_color_matrix) { |
const RenderPassColorMatrixProgram* program = |
- GetRenderPassColorMatrixProgram(tex_coord_precision); |
+ GetRenderPassColorMatrixProgram(tex_coord_precision, shader_blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1333,9 +1265,12 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
program->fragment_shader().color_matrix_location(); |
shader_color_offset_location = |
program->fragment_shader().color_offset_location(); |
+ shader_backdrop_location = program->fragment_shader().backdrop_location(); |
+ shader_backdrop_rect_location = |
+ program->fragment_shader().backdrop_rect_location(); |
} else { |
const RenderPassProgram* program = |
- GetRenderPassProgram(tex_coord_precision); |
+ GetRenderPassProgram(tex_coord_precision, shader_blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1343,6 +1278,9 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
shader_alpha_location = program->fragment_shader().alpha_location(); |
shader_tex_transform_location = |
program->vertex_shader().tex_transform_location(); |
+ shader_backdrop_location = program->fragment_shader().backdrop_location(); |
+ shader_backdrop_rect_location = |
+ program->fragment_shader().backdrop_rect_location(); |
} |
float tex_scale_x = |
quad->rect.width() / static_cast<float>(contents_texture->size().width()); |
@@ -1362,6 +1300,7 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
tex_scale_x, |
-tex_scale_y)); |
+ GLint last_texture_unit = 0; |
scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_mask_sampler_lock; |
if (shader_mask_sampler_location != -1) { |
DCHECK_NE(shader_mask_tex_coord_scale_location, 1); |
@@ -1382,6 +1321,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
gl_->Uniform2f(shader_mask_tex_coord_scale_location, |
mask_uv_rect.width() / tex_scale_x, |
-mask_uv_rect.height() / tex_scale_y)); |
+ |
+ last_texture_unit = 1; |
} |
if (shader_edge_location != -1) { |
@@ -1417,6 +1358,37 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
GLC(gl_, gl_->Uniform4fv(shader_color_offset_location, 1, offset)); |
} |
+ scoped_ptr<ResourceProvider::ScopedSamplerGL> shader_background_sampler_lock; |
+ if (shader_backdrop_location != -1) { |
+ DCHECK(background_texture || background_image); |
+ DCHECK_NE(shader_backdrop_location, 0); |
+ DCHECK_NE(shader_backdrop_rect_location, 0); |
+ |
+ GLC(gl_, gl_->Uniform1i(shader_backdrop_location, ++last_texture_unit)); |
+ |
+ GLC(gl_, |
+ gl_->Uniform4f(shader_backdrop_rect_location, |
+ background_rect.x(), |
+ background_rect.y(), |
+ background_rect.width(), |
+ background_rect.height())); |
+ |
+ if (background_image) { |
+ GrTexture* texture = background_image->getTexture(); |
+ GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0 + last_texture_unit)); |
+ gl_->BindTexture(GL_TEXTURE_2D, texture->getTextureHandle()); |
+ GLC(gl_, gl_->ActiveTexture(GL_TEXTURE0)); |
+ } else { |
+ shader_background_sampler_lock = make_scoped_ptr( |
+ new ResourceProvider::ScopedSamplerGL(resource_provider_, |
+ background_texture->id(), |
+ GL_TEXTURE0 + last_texture_unit, |
+ GL_LINEAR)); |
+ DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), |
+ shader_background_sampler_lock->target()); |
+ } |
+ } |
+ |
// Map device space quad to surface space. contents_device_transform has no 3d |
// component since it was flattened, so we don't need to project. |
gfx::QuadF surface_quad = MathUtil::MapQuad(contents_device_transform_inverse, |
@@ -2352,7 +2324,8 @@ void GLRenderer::CopyTextureToFramebuffer(const DrawingFrame* frame, |
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( |
gl_, &highp_threshold_cache_, highp_threshold_min_, rect.bottom_right()); |
- const RenderPassProgram* program = GetRenderPassProgram(tex_coord_precision); |
+ const RenderPassProgram* program = |
+ GetRenderPassProgram(tex_coord_precision, BlendModeNormal); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -2831,112 +2804,155 @@ const GLRenderer::SolidColorProgramAA* GLRenderer::GetSolidColorProgramAA() { |
} |
const GLRenderer::RenderPassProgram* GLRenderer::GetRenderPassProgram( |
- TexCoordPrecision precision) { |
+ TexCoordPrecision precision, |
+ BlendMode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
- RenderPassProgram* program = &render_pass_program_[precision]; |
+ DCHECK_GE(blend_mode, 0); |
+ DCHECK_LT(blend_mode, NumBlendModes); |
+ RenderPassProgram* program = &render_pass_program_[precision][blend_mode]; |
if (!program->initialized()) { |
TRACE_EVENT0("cc", "GLRenderer::renderPassProgram::initialize"); |
- program->Initialize( |
- output_surface_->context_provider(), precision, SamplerType2D); |
+ program->Initialize(output_surface_->context_provider(), |
+ precision, |
+ SamplerType2D, |
+ blend_mode); |
} |
return program; |
} |
const GLRenderer::RenderPassProgramAA* GLRenderer::GetRenderPassProgramAA( |
- TexCoordPrecision precision) { |
+ TexCoordPrecision precision, |
+ BlendMode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
- RenderPassProgramAA* program = &render_pass_program_aa_[precision]; |
+ DCHECK_GE(blend_mode, 0); |
+ DCHECK_LT(blend_mode, NumBlendModes); |
+ RenderPassProgramAA* program = |
+ &render_pass_program_aa_[precision][blend_mode]; |
if (!program->initialized()) { |
TRACE_EVENT0("cc", "GLRenderer::renderPassProgramAA::initialize"); |
- program->Initialize( |
- output_surface_->context_provider(), precision, SamplerType2D); |
+ program->Initialize(output_surface_->context_provider(), |
+ precision, |
+ SamplerType2D, |
+ blend_mode); |
} |
return program; |
} |
const GLRenderer::RenderPassMaskProgram* GLRenderer::GetRenderPassMaskProgram( |
- TexCoordPrecision precision) { |
+ TexCoordPrecision precision, |
+ BlendMode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
- RenderPassMaskProgram* program = &render_pass_mask_program_[precision]; |
+ DCHECK_GE(blend_mode, 0); |
+ DCHECK_LT(blend_mode, NumBlendModes); |
+ RenderPassMaskProgram* program = |
+ &render_pass_mask_program_[precision][blend_mode]; |
if (!program->initialized()) { |
TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgram::initialize"); |
- program->Initialize( |
- output_surface_->context_provider(), precision, SamplerType2D); |
+ program->Initialize(output_surface_->context_provider(), |
+ precision, |
+ SamplerType2D, |
+ blend_mode); |
} |
return program; |
} |
const GLRenderer::RenderPassMaskProgramAA* |
-GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision) { |
+GLRenderer::GetRenderPassMaskProgramAA(TexCoordPrecision precision, |
+ BlendMode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
- RenderPassMaskProgramAA* program = &render_pass_mask_program_aa_[precision]; |
+ DCHECK_GE(blend_mode, 0); |
+ DCHECK_LT(blend_mode, NumBlendModes); |
+ RenderPassMaskProgramAA* program = |
+ &render_pass_mask_program_aa_[precision][blend_mode]; |
if (!program->initialized()) { |
TRACE_EVENT0("cc", "GLRenderer::renderPassMaskProgramAA::initialize"); |
- program->Initialize( |
- output_surface_->context_provider(), precision, SamplerType2D); |
+ program->Initialize(output_surface_->context_provider(), |
+ precision, |
+ SamplerType2D, |
+ blend_mode); |
} |
return program; |
} |
const GLRenderer::RenderPassColorMatrixProgram* |
-GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision) { |
+GLRenderer::GetRenderPassColorMatrixProgram(TexCoordPrecision precision, |
+ BlendMode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
+ DCHECK_GE(blend_mode, 0); |
+ DCHECK_LT(blend_mode, NumBlendModes); |
RenderPassColorMatrixProgram* program = |
- &render_pass_color_matrix_program_[precision]; |
+ &render_pass_color_matrix_program_[precision][blend_mode]; |
if (!program->initialized()) { |
TRACE_EVENT0("cc", "GLRenderer::renderPassColorMatrixProgram::initialize"); |
- program->Initialize( |
- output_surface_->context_provider(), precision, SamplerType2D); |
+ program->Initialize(output_surface_->context_provider(), |
+ precision, |
+ SamplerType2D, |
+ blend_mode); |
} |
return program; |
} |
const GLRenderer::RenderPassColorMatrixProgramAA* |
-GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision) { |
+GLRenderer::GetRenderPassColorMatrixProgramAA(TexCoordPrecision precision, |
+ BlendMode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
+ DCHECK_GE(blend_mode, 0); |
+ DCHECK_LT(blend_mode, NumBlendModes); |
RenderPassColorMatrixProgramAA* program = |
- &render_pass_color_matrix_program_aa_[precision]; |
+ &render_pass_color_matrix_program_aa_[precision][blend_mode]; |
if (!program->initialized()) { |
TRACE_EVENT0("cc", |
"GLRenderer::renderPassColorMatrixProgramAA::initialize"); |
- program->Initialize( |
- output_surface_->context_provider(), precision, SamplerType2D); |
+ program->Initialize(output_surface_->context_provider(), |
+ precision, |
+ SamplerType2D, |
+ blend_mode); |
} |
return program; |
} |
const GLRenderer::RenderPassMaskColorMatrixProgram* |
-GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) { |
+GLRenderer::GetRenderPassMaskColorMatrixProgram(TexCoordPrecision precision, |
+ BlendMode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
+ DCHECK_GE(blend_mode, 0); |
+ DCHECK_LT(blend_mode, NumBlendModes); |
RenderPassMaskColorMatrixProgram* program = |
- &render_pass_mask_color_matrix_program_[precision]; |
+ &render_pass_mask_color_matrix_program_[precision][blend_mode]; |
if (!program->initialized()) { |
TRACE_EVENT0("cc", |
"GLRenderer::renderPassMaskColorMatrixProgram::initialize"); |
- program->Initialize( |
- output_surface_->context_provider(), precision, SamplerType2D); |
+ program->Initialize(output_surface_->context_provider(), |
+ precision, |
+ SamplerType2D, |
+ blend_mode); |
} |
return program; |
} |
const GLRenderer::RenderPassMaskColorMatrixProgramAA* |
-GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) { |
+GLRenderer::GetRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision, |
+ BlendMode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
+ DCHECK_GE(blend_mode, 0); |
+ DCHECK_LT(blend_mode, NumBlendModes); |
RenderPassMaskColorMatrixProgramAA* program = |
- &render_pass_mask_color_matrix_program_aa_[precision]; |
+ &render_pass_mask_color_matrix_program_aa_[precision][blend_mode]; |
if (!program->initialized()) { |
TRACE_EVENT0("cc", |
"GLRenderer::renderPassMaskColorMatrixProgramAA::initialize"); |
- program->Initialize( |
- output_surface_->context_provider(), precision, SamplerType2D); |
+ program->Initialize(output_surface_->context_provider(), |
+ precision, |
+ SamplerType2D, |
+ blend_mode); |
} |
return program; |
} |
@@ -3162,15 +3178,16 @@ void GLRenderer::CleanupSharedObjects() { |
tile_program_aa_[i][j].Cleanup(gl_); |
tile_program_swizzle_aa_[i][j].Cleanup(gl_); |
} |
- |
- render_pass_mask_program_[i].Cleanup(gl_); |
- render_pass_program_[i].Cleanup(gl_); |
- render_pass_mask_program_aa_[i].Cleanup(gl_); |
- render_pass_program_aa_[i].Cleanup(gl_); |
- render_pass_color_matrix_program_[i].Cleanup(gl_); |
- render_pass_mask_color_matrix_program_aa_[i].Cleanup(gl_); |
- render_pass_color_matrix_program_aa_[i].Cleanup(gl_); |
- render_pass_mask_color_matrix_program_[i].Cleanup(gl_); |
+ for (int j = 0; j < NumBlendModes; j++) { |
+ render_pass_mask_program_[i][j].Cleanup(gl_); |
+ render_pass_program_[i][j].Cleanup(gl_); |
+ render_pass_mask_program_aa_[i][j].Cleanup(gl_); |
+ render_pass_program_aa_[i][j].Cleanup(gl_); |
+ render_pass_color_matrix_program_[i][j].Cleanup(gl_); |
+ render_pass_mask_color_matrix_program_aa_[i][j].Cleanup(gl_); |
+ render_pass_color_matrix_program_aa_[i][j].Cleanup(gl_); |
+ render_pass_mask_color_matrix_program_[i][j].Cleanup(gl_); |
+ } |
texture_program_[i].Cleanup(gl_); |
nonpremultiplied_texture_program_[i].Cleanup(gl_); |