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

Unified Diff: cc/output/gl_renderer.cc

Issue 555133002: [WIP Experiment] Implement mix-blend-mode in GLRenderer using shaders. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix compile issue on mac Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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_);

Powered by Google App Engine
This is Rietveld 408576698