Chromium Code Reviews| 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_); |