Index: cc/output/gl_renderer.cc |
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc |
index e039947695c967740fc7ba88ba0e7df11abea869..5c21e9c3b9aa1eaf2eb7bac0f7f1560378104124 100644 |
--- a/cc/output/gl_renderer.cc |
+++ b/cc/output/gl_renderer.cc |
@@ -616,7 +616,7 @@ static skia::RefPtr<SkImage> ApplyImageFilter( |
const gfx::Point& origin, |
const gfx::Vector2dF& scale, |
SkImageFilter* filter, |
- ScopedResource* source_texture_resource) { |
+ const ScopedResource* source_texture_resource) { |
if (!filter) |
return skia::RefPtr<SkImage>(); |
@@ -694,133 +694,98 @@ static skia::RefPtr<SkImage> ApplyImageFilter( |
return image; |
} |
-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)); |
+bool GLRenderer::ShouldApplyBackgroundFilters(DrawingFrame* frame, |
+ const RenderPassDrawQuad* quad) { |
+ if (quad->background_filters.IsEmpty()) |
+ return false; |
- 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)); |
+ // TODO(danakj): We only allow background filters on an opaque render surface |
+ // because other surfaces may contain translucent pixels, and the contents |
+ // behind those translucent pixels wouldn't have the filter applied. |
+ if (frame->current_render_pass->has_transparent_background) |
+ return false; |
- 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()); |
+ // TODO(ajuma): Add support for reference filters once |
+ // FilterOperations::GetOutsets supports reference filters. |
+ if (quad->background_filters.HasReferenceFilter()) |
+ return false; |
+ return true; |
+} |
- SkImageInfo background_info = SkImageInfo::MakeN32Premul( |
- background_size.width(), background_size.height()); |
+bool GLRenderer::ShouldApplyBlendModeUsingBlendFunc(const DrawQuad* quad) { |
+ SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode; |
+ return blend_mode == SkXfermode::kScreen_Mode || |
+ blend_mode == SkXfermode::kLighten_Mode; |
+} |
- 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()); |
+bool GLRenderer::ShouldApplyBlendModeUsingShaders(const DrawQuad* quad) { |
+ SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode; |
+ return blend_mode != SkXfermode::kSrcOver_Mode && |
+ !ShouldApplyBlendModeUsingBlendFunc(quad); |
+} |
- // 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; |
- GrAutoScratchTexture scratch_texture( |
- use_gr_context->context(), desc, GrContext::kExact_ScratchTexMatch); |
- skia::RefPtr<GrTexture> backing_store = |
- skia::AdoptRef(scratch_texture.detach()); |
- if (backing_store.get() == NULL) { |
- TRACE_EVENT_INSTANT0( |
- "cc", |
- "ApplyBlendModeWithBackdrop scratch texture allocation failed", |
- TRACE_EVENT_SCOPE_THREAD); |
- return source_bitmap_with_filters; |
+void GLRenderer::ApplyBlendModeUsingBlendFunc(const DrawQuad* quad) { |
+ DCHECK(ShouldApplyBlendModeUsingBlendFunc(quad)); |
+ SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode; |
+ if (blend_mode == SkXfermode::kLighten_Mode) { |
+ GLC(gl_, gl_->BlendFunc(GL_ONE, GL_ONE)); |
+ GLC(gl_, gl_->BlendEquation(GL_MAX_EXT)); |
+ } else if (blend_mode == SkXfermode::kMultiply_Mode) { |
+ GLC(gl_, gl_->BlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA)); |
+ } else if (blend_mode == SkXfermode::kScreen_Mode) { |
+ GLC(gl_, gl_->BlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE)); |
} |
+} |
- // 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()); |
+void GLRenderer::RestoreBlendFuncToDefault(const DrawQuad* quad) { |
+ DCHECK(ShouldApplyBlendModeUsingBlendFunc(quad)); |
+ GLC(gl_, gl_->BlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); |
+ SkXfermode::Mode blend_mode = quad->shared_quad_state->blend_mode; |
+ if (blend_mode == SkXfermode::kLighten_Mode) { |
+ GLC(gl_, gl_->BlendEquation(GL_FUNC_ADD)); |
+ } |
+} |
- // 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); |
+gfx::Rect GLRenderer::GetBackdropBoundingBox( |
+ DrawingFrame* frame, |
+ const RenderPassDrawQuad* quad, |
+ const gfx::Transform& contents_device_transform) { |
+ gfx::Rect backdrop_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( |
+ contents_device_transform, SharedGeometryQuad().BoundingBox())); |
- skia::RefPtr<SkImage> image = skia::AdoptRef(surface->newImageSnapshot()); |
- if (!image || !image->getTexture()) { |
- return skia::RefPtr<SkImage>(); |
+ if (ShouldApplyBackgroundFilters(frame, quad)) { |
+ int top, right, bottom, left; |
+ quad->background_filters.GetOutsets(&top, &right, &bottom, &left); |
+ backdrop_rect.Inset(-left, -top, -right, -bottom); |
} |
- // 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(); |
+ backdrop_rect.Intersect( |
+ MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); |
+ return backdrop_rect; |
+} |
- return image; |
+scoped_ptr<ScopedResource> GLRenderer::GetBackdrop( |
+ const gfx::Rect& bounding_rect) { |
+ scoped_ptr<ScopedResource> device_background_texture = |
+ ScopedResource::Create(resource_provider_); |
+ // CopyTexImage2D fails when called on a texture having immutable storage. |
+ device_background_texture->Allocate( |
+ bounding_rect.size(), ResourceProvider::TextureHintDefault, RGBA_8888); |
+ { |
+ ResourceProvider::ScopedWriteLockGL lock(resource_provider_, |
+ device_background_texture->id()); |
+ GetFramebufferTexture( |
+ lock.texture_id(), device_background_texture->format(), bounding_rect); |
+ } |
+ return device_background_texture.Pass(); |
} |
scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters( |
DrawingFrame* frame, |
const RenderPassDrawQuad* quad, |
- const gfx::Transform& contents_device_transform, |
const gfx::Transform& contents_device_transform_inverse, |
- bool* background_changed) { |
+ const ScopedResource* backdrop_texture, |
+ const gfx::Rect& backdrop_bounding_rect) { |
// This method draws a background filter, which applies a filter to any pixels |
// behind the quad and seen through its background. The algorithm works as |
// follows: |
@@ -844,67 +809,21 @@ scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters( |
// TODO(danakj): When this algorithm changes, update |
// LayerTreeHost::PrioritizeTextures() accordingly. |
- // TODO(danakj): We only allow background filters on an opaque render surface |
- // because other surfaces may contain translucent pixels, and the contents |
- // behind those translucent pixels wouldn't have the filter applied. |
- bool apply_background_filters = |
- !frame->current_render_pass->has_transparent_background; |
- DCHECK(!frame->current_texture); |
- |
- // TODO(ajuma): Add support for reference filters once |
- // FilterOperations::GetOutsets supports reference filters. |
- if (apply_background_filters && quad->background_filters.HasReferenceFilter()) |
- apply_background_filters = false; |
- |
- // TODO(danakj): Do a single readback for both the surface and replica and |
- // cache the filtered results (once filter textures are not reused). |
- gfx::Rect window_rect = gfx::ToEnclosingRect(MathUtil::MapClippedRect( |
- contents_device_transform, SharedGeometryQuad().BoundingBox())); |
- |
- int top, right, bottom, left; |
- quad->background_filters.GetOutsets(&top, &right, &bottom, &left); |
- window_rect.Inset(-left, -top, -right, -bottom); |
+ skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( |
+ quad->background_filters, backdrop_texture->size()); |
- window_rect.Intersect( |
- MoveFromDrawToWindowSpace(frame->current_render_pass->output_rect)); |
+ skia::RefPtr<SkImage> filtered_device_background = |
+ ApplyImageFilter(ScopedUseGrContext::Create(this, frame), |
+ resource_provider_, |
+ quad->rect.origin(), |
+ quad->filters_scale, |
+ filter.get(), |
+ backdrop_texture); |
- scoped_ptr<ScopedResource> device_background_texture = |
- ScopedResource::Create(resource_provider_); |
- // CopyTexImage2D fails when called on a texture having immutable storage. |
- device_background_texture->Allocate( |
- window_rect.size(), ResourceProvider::TextureHintDefault, RGBA_8888); |
- { |
- ResourceProvider::ScopedWriteLockGL lock(resource_provider_, |
- device_background_texture->id()); |
- GetFramebufferTexture( |
- lock.texture_id(), device_background_texture->format(), window_rect); |
- } |
+ if (!filtered_device_background) |
+ return scoped_ptr<ScopedResource>(); |
- skia::RefPtr<SkImageFilter> filter = RenderSurfaceFilters::BuildImageFilter( |
- quad->background_filters, device_background_texture->size()); |
- |
- skia::RefPtr<SkImage> filtered_device_background; |
- if (apply_background_filters) { |
- filtered_device_background = |
- ApplyImageFilter(ScopedUseGrContext::Create(this, frame), |
- resource_provider_, |
- quad->rect.origin(), |
- quad->filters_scale, |
- filter.get(), |
- device_background_texture.get()); |
- } |
- *background_changed = (filtered_device_background != NULL); |
- |
- 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_); |
@@ -938,8 +857,8 @@ scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters( |
bool flip_vertically = false; |
CopyTextureToFramebuffer(frame, |
- filtered_device_background_texture_id, |
- window_rect, |
+ texture->getTextureHandle(), |
+ backdrop_bounding_rect, |
device_to_framebuffer_transform, |
flip_vertically); |
} |
@@ -953,7 +872,8 @@ scoped_ptr<ScopedResource> GLRenderer::GetBackgroundWithFilters( |
void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
const RenderPassDrawQuad* quad) { |
- SetBlendEnabled(quad->ShouldDrawWithBlending()); |
+ SetBlendEnabled(quad->ShouldDrawWithBlending() || |
+ ShouldApplyBlendModeUsingBlendFunc(quad)); |
ScopedResource* contents_texture = |
render_pass_textures_.get(quad->render_pass_id); |
@@ -972,24 +892,31 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
if (!contents_device_transform.GetInverse(&contents_device_transform_inverse)) |
return; |
- bool need_background_texture = |
- quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode || |
- !quad->background_filters.IsEmpty(); |
- bool background_changed = false; |
- scoped_ptr<ScopedResource> background_texture; |
- if (need_background_texture) { |
+ bool need_backdrop_texture = ShouldApplyBlendModeUsingShaders(quad) || |
+ ShouldApplyBackgroundFilters(frame, quad); |
+ |
+ scoped_ptr<ScopedResource> backdrop_texture; |
+ gfx::Rect backdrop_rect; |
+ if (need_backdrop_texture) { |
+ backdrop_rect = |
+ GetBackdropBoundingBox(frame, quad, contents_device_transform); |
+ backdrop_texture = GetBackdrop(backdrop_rect); |
+ } |
+ |
+ scoped_ptr<ScopedResource> filtered_background_texture; |
+ if (backdrop_texture && ShouldApplyBackgroundFilters(frame, quad)) { |
// The pixels from the filtered background should completely replace the |
// current pixel values. |
bool disable_blending = blend_enabled(); |
if (disable_blending) |
SetBlendEnabled(false); |
- background_texture = |
+ filtered_background_texture = |
GetBackgroundWithFilters(frame, |
quad, |
- contents_device_transform, |
contents_device_transform_inverse, |
- &background_changed); |
+ backdrop_texture.get(), |
+ backdrop_rect); |
if (disable_blending) |
SetBlendEnabled(true); |
@@ -1028,24 +955,14 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
} |
} |
- if (quad->shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode && |
- background_texture) { |
- filter_bitmap = |
- ApplyBlendModeWithBackdrop(ScopedUseGrContext::Create(this, frame), |
- resource_provider_, |
- filter_bitmap, |
- contents_texture, |
- background_texture.get(), |
- quad->shared_quad_state->blend_mode); |
- } |
- |
// Draw the background texture if it has some filters applied. |
- if (background_texture && background_changed) { |
- DCHECK(background_texture->size() == quad->rect.size()); |
+ if (filtered_background_texture) { |
+ DCHECK(filtered_background_texture->size() == quad->rect.size()); |
ResourceProvider::ScopedReadLockGL lock(resource_provider_, |
- background_texture->id()); |
+ filtered_background_texture->id()); |
- // The background_texture is oriented the same as the frame buffer. The |
+ // The filtered_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; |
@@ -1096,6 +1013,8 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), |
contents_resource_lock->target()); |
} |
+ if (ShouldApplyBlendModeUsingBlendFunc(quad)) |
+ ApplyBlendModeUsingBlendFunc(quad); |
TexCoordPrecision tex_coord_precision = TexCoordPrecisionRequired( |
gl_, |
@@ -1115,9 +1034,18 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
int shader_color_offset_location = -1; |
int shader_tex_transform_location = -1; |
+ // We implemented the difference blend mode only for RenderPassProgram |
+ // and RenderPassProgramAA, this should be enough to play animations. |
+ int shader_backdrop_location = -1; |
+ int shader_backdrop_rect_location = -1; |
+ SkXfermode::Mode blend_mode = |
+ (backdrop_texture && ShouldApplyBlendModeUsingShaders(quad)) |
+ ? quad->shared_quad_state->blend_mode |
+ : SkXfermode::kSrcOver_Mode; |
+ |
if (use_aa && mask_texture_id && !use_color_matrix) { |
const RenderPassMaskProgramAA* program = |
- GetRenderPassMaskProgramAA(tex_coord_precision); |
+ GetRenderPassMaskProgramAA(tex_coord_precision, blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1134,9 +1062,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, blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1150,9 +1081,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, blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1163,9 +1097,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 RenderPassMaskColorMatrixProgramAA* program = |
- GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision); |
+ GetRenderPassMaskColorMatrixProgramAA(tex_coord_precision, blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1186,9 +1123,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 RenderPassColorMatrixProgramAA* program = |
- GetRenderPassColorMatrixProgramAA(tex_coord_precision); |
+ GetRenderPassColorMatrixProgramAA(tex_coord_precision, blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1203,9 +1143,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 RenderPassMaskColorMatrixProgram* program = |
- GetRenderPassMaskColorMatrixProgram(tex_coord_precision); |
+ GetRenderPassMaskColorMatrixProgram(tex_coord_precision, blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1223,9 +1166,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, blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1237,9 +1183,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, blend_mode); |
SetUseProgram(program->program()); |
GLC(gl_, gl_->Uniform1i(program->fragment_shader().sampler_location(), 0)); |
@@ -1247,6 +1196,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()); |
@@ -1328,6 +1280,27 @@ 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(backdrop_texture); |
+ DCHECK_NE(shader_backdrop_location, 0); |
+ GLC(gl_, gl_->Uniform1i(shader_backdrop_location, 1)); |
+ |
+ GLC(gl_, |
+ gl_->Uniform4f(shader_backdrop_rect_location, |
+ backdrop_rect.x(), |
+ backdrop_rect.y(), |
+ backdrop_rect.width(), |
+ backdrop_rect.height())); |
+ shader_background_sampler_lock = make_scoped_ptr( |
+ new ResourceProvider::ScopedSamplerGL(resource_provider_, |
+ backdrop_texture->id(), |
+ GL_TEXTURE1, |
+ 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, |
@@ -1343,6 +1316,9 @@ void GLRenderer::DrawRenderPassQuad(DrawingFrame* frame, |
// scope, so the draw gets processed before the filter texture gets deleted. |
if (filter_bitmap) |
GLC(gl_, gl_->Flush()); |
+ |
+ if (ShouldApplyBlendModeUsingBlendFunc(quad)) |
+ RestoreBlendFuncToDefault(quad); |
} |
struct SolidColorProgramUniforms { |
@@ -2740,113 +2716,194 @@ const GLRenderer::SolidColorProgramAA* GLRenderer::GetSolidColorProgramAA() { |
return &solid_color_program_aa_; |
} |
+int GLRenderer::GetBlendModeIndex(SkXfermode::Mode blend_mode) { |
+ static const int blend_mode_to_index_mapping[] = { |
+ 0, // kClear_Mode |
+ 0, // kSrc_Mode |
+ 0, // kDst_Mode |
+ 0, // kSrcOver_Mode |
+ 0, // kDstOver_Mode |
+ 0, // kSrcIn_Mode |
+ 0, // kDstIn_Mode |
+ 0, // kSrcOut_Mode |
+ 0, // kDstOut_Mode |
+ 0, // kSrcATop_Mode |
+ 0, // kDstATop_Mode |
+ 0, // kXor_Mode |
+ 0, // kPlus_Mode |
+ 0, // kModulate_Mode |
+ 1, // kScreen_Mode |
enne (OOO)
2014/09/24 22:07:56
Why do you need this array? Why not just blend_mod
|
+ 2, // kOverlay_Mode |
+ 3, // kDarken_Mode |
+ 4, // kLighten_Mode |
+ 5, // kColorDodge_Mode |
+ 6, // kColorBurn_Mode |
+ 7, // kHardLight_Mode |
+ 8, // kSoftLight_Mode |
+ 9, // kDifference_Mode |
+ 10, // kExclusion_Mode |
+ 11, // kMultiply_Mode |
+ 12, // kHue_Mode |
+ 13, // kSaturation_Mode |
+ 14, // kColor_Mode |
+ 15, // kLuminosity_Mode |
+ }; |
+ |
+ DCHECK_EQ( |
+ blend_mode_to_index_mapping[arraysize(blend_mode_to_index_mapping) - 1], |
+ kNumBlendModes - 1); |
+ DCHECK_EQ(arraysize(blend_mode_to_index_mapping), |
+ static_cast<size_t>(SkXfermode::kLastMode) + 1); |
+ |
+ if (static_cast<size_t>(blend_mode) >= arraysize(blend_mode_to_index_mapping)) |
+ return 0; |
+ |
+ return blend_mode_to_index_mapping[blend_mode]; |
+} |
+ |
const GLRenderer::RenderPassProgram* GLRenderer::GetRenderPassProgram( |
- TexCoordPrecision precision) { |
+ TexCoordPrecision precision, |
+ SkXfermode::Mode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
- RenderPassProgram* program = &render_pass_program_[precision]; |
+ int blend_mode_index = GetBlendModeIndex(blend_mode); |
+ RenderPassProgram* program = |
+ &render_pass_program_[blend_mode_index][precision]; |
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, |
+ SkXfermode::Mode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
- RenderPassProgramAA* program = &render_pass_program_aa_[precision]; |
+ int blend_mode_index = GetBlendModeIndex(blend_mode); |
+ RenderPassProgramAA* program = |
+ &render_pass_program_aa_[blend_mode_index][precision]; |
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, |
+ SkXfermode::Mode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
- RenderPassMaskProgram* program = &render_pass_mask_program_[precision]; |
+ int blend_mode_index = GetBlendModeIndex(blend_mode); |
+ RenderPassMaskProgram* program = |
+ &render_pass_mask_program_[blend_mode_index][precision]; |
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, |
+ SkXfermode::Mode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
- RenderPassMaskProgramAA* program = &render_pass_mask_program_aa_[precision]; |
+ int blend_mode_index = GetBlendModeIndex(blend_mode); |
+ RenderPassMaskProgramAA* program = |
+ &render_pass_mask_program_aa_[blend_mode_index][precision]; |
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, |
+ SkXfermode::Mode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
+ int blend_mode_index = GetBlendModeIndex(blend_mode); |
RenderPassColorMatrixProgram* program = |
- &render_pass_color_matrix_program_[precision]; |
+ &render_pass_color_matrix_program_[blend_mode_index][precision]; |
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, |
+ SkXfermode::Mode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
+ int blend_mode_index = GetBlendModeIndex(blend_mode); |
RenderPassColorMatrixProgramAA* program = |
- &render_pass_color_matrix_program_aa_[precision]; |
+ &render_pass_color_matrix_program_aa_[blend_mode_index][precision]; |
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, |
+ SkXfermode::Mode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
+ int blend_mode_index = GetBlendModeIndex(blend_mode); |
RenderPassMaskColorMatrixProgram* program = |
- &render_pass_mask_color_matrix_program_[precision]; |
+ &render_pass_mask_color_matrix_program_[blend_mode_index][precision]; |
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, |
+ SkXfermode::Mode blend_mode) { |
DCHECK_GE(precision, 0); |
DCHECK_LT(precision, NumTexCoordPrecisions); |
+ int blend_mode_index = GetBlendModeIndex(blend_mode); |
RenderPassMaskColorMatrixProgramAA* program = |
- &render_pass_mask_color_matrix_program_aa_[precision]; |
+ &render_pass_mask_color_matrix_program_aa_[blend_mode_index][precision]; |
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; |
} |
@@ -3073,14 +3130,16 @@ void GLRenderer::CleanupSharedObjects() { |
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 k = 0; k < kNumBlendModes; ++k) { |
+ render_pass_program_[k][i].Cleanup(gl_); |
+ render_pass_program_aa_[k][i].Cleanup(gl_); |
+ render_pass_mask_program_[k][i].Cleanup(gl_); |
+ render_pass_mask_program_aa_[k][i].Cleanup(gl_); |
+ render_pass_color_matrix_program_[k][i].Cleanup(gl_); |
+ render_pass_mask_color_matrix_program_aa_[k][i].Cleanup(gl_); |
+ render_pass_color_matrix_program_aa_[k][i].Cleanup(gl_); |
+ render_pass_mask_color_matrix_program_[k][i].Cleanup(gl_); |
+ } |
texture_program_[i].Cleanup(gl_); |
nonpremultiplied_texture_program_[i].Cleanup(gl_); |