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

Unified Diff: cc/output/gl_renderer.cc

Issue 2205133003: Implement new RPDQ copy logic for CALayer promotion. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@temp60_more_refactor
Patch Set: Fix vertical flip. Created 4 years, 4 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 bc635b52a43e3b78af8e14d53e392316a0ff0d57..2dcfc10c1d0bf3f97eabce6d1f73db0ad5c9f2ec 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -67,6 +67,28 @@ using gpu::gles2::GLES2Interface;
namespace cc {
namespace {
+class ScopedTextureDeleter {
+ public:
+ ScopedTextureDeleter(GLuint texture, gpu::gles2::GLES2Interface* gl)
+ : texture_(texture), gl_(gl) {}
+ ~ScopedTextureDeleter() { gl_->DeleteTextures(1, &texture_); }
+
+ private:
+ GLuint texture_;
+ gpu::gles2::GLES2Interface* gl_;
+};
+
+class ScopedFramebufferDeleter {
+ public:
+ ScopedFramebufferDeleter(GLuint fbo, gpu::gles2::GLES2Interface* gl)
+ : fbo_(fbo), gl_(gl) {}
+ ~ScopedFramebufferDeleter() { gl_->DeleteFramebuffers(1, &fbo_); }
+
+ private:
+ GLuint fbo_;
+ gpu::gles2::GLES2Interface* gl_;
+};
+
Float4 UVTransform(const TextureDrawQuad* quad) {
gfx::PointF uv0 = quad->uv_top_left;
gfx::PointF uv1 = quad->uv_bottom_right;
@@ -165,7 +187,8 @@ struct DrawRenderPassDrawQuadParams {
gfx::Transform window_matrix;
gfx::Transform projection_matrix;
- // |frame| is needed for background effects.
+ // |frame| is used to restore the current render pass. |frame| is also needed
+ // for background effects. If |frame| is not present, nothing happens.
DirectRenderer::DrawingFrame* frame = nullptr;
// Whether the texture to be sampled from needs to be flipped.
@@ -2697,6 +2720,8 @@ void GLRenderer::FinishDrawingQuadList() {
}
bool GLRenderer::FlippedFramebuffer(const DrawingFrame* frame) const {
+ if (frame == force_drawing_frame_framebuffer_flipped_)
+ return true;
if (frame->current_render_pass != frame->root_render_pass)
return true;
return FlippedRootFramebuffer();
@@ -3745,7 +3770,7 @@ bool GLRenderer::IsContextLost() {
void GLRenderer::ScheduleCALayers(DrawingFrame* frame) {
scoped_refptr<CALayerOverlaySharedState> shared_state;
size_t copied_render_pass_count = 0;
- for (const CALayerOverlay& ca_layer_overlay : frame->ca_layer_overlay_list) {
+ for (CALayerOverlay& ca_layer_overlay : frame->ca_layer_overlay_list) {
if (!overlay_resource_pool_) {
overlay_resource_pool_ = ResourcePool::CreateForGpuMemoryBufferResources(
resource_provider_, base::ThreadTaskRunnerHandle::Get().get(),
@@ -3755,11 +3780,13 @@ void GLRenderer::ScheduleCALayers(DrawingFrame* frame) {
ResourceId contents_resource_id = ca_layer_overlay.contents_resource_id;
Resource* resource = nullptr;
// Some CALayers require a final round of processing.
- if (ca_layer_overlay.render_pass_id.IsValid()) {
- CopyRenderPassToOverlayResource(ca_layer_overlay.render_pass_id,
- &resource);
- contents_resource_id = resource->id();
- ++copied_render_pass_count;
+ if (ca_layer_overlay.rpdq.get()) {
+ CopyRenderPassDrawQuadToOverlayResource(&ca_layer_overlay, &resource,
+ frame);
ccameron 2016/08/04 01:46:01 Rather than updating the CALayerOverlay parameters
erikchen 2016/08/05 17:15:06 Done.
+ if (resource) {
+ contents_resource_id = resource->id();
+ ++copied_render_pass_count;
+ }
}
unsigned texture_id = 0;
@@ -3820,7 +3847,11 @@ void GLRenderer::ScheduleCALayers(DrawingFrame* frame) {
static_cast<GLuint>(filter_effect.drop_shadow_color);
}
- gl_->ScheduleCALayerFilterEffectsCHROMIUM(effects.size(), effects.data());
+ // TODO(erikchen): Remove all logic associated with
+ // ScheduleCALayerFilterEffectsCHROMIUM once the implementation of filter
+ // effects for CA is fully functional. https://crbug.com/581526.
+ // gl_->ScheduleCALayerFilterEffectsCHROMIUM(effects.size(),
+ // effects.data());
}
gl_->ScheduleCALayerCHROMIUM(
texture_id, contents_rect, ca_layer_overlay.background_color,
@@ -3886,4 +3917,137 @@ void GLRenderer::CopyRenderPassToOverlayResource(
GL_FALSE, GL_FALSE);
}
+// This function draws the RenderPassDrawQuad into a temporary
+// texture/framebuffer, and then copies the result into an IOSurface.
+void GLRenderer::CopyRenderPassDrawQuadToOverlayResource(
+ CALayerOverlay* ca_layer_overlay,
+ Resource** resource,
+ DrawingFrame* external_frame) {
+ ScopedResource* contents_texture =
+ render_pass_textures_[ca_layer_overlay->rpdq->render_pass_id].get();
+ DCHECK(contents_texture);
+
+ // The intermediary texture may need to be larger than the original content,
+ // since the BLUR and DROP_SHADOW filter effects affect pixels outside the
+ // original content. The exact size is computed within Skia, along with the
+ // creation of |filter_image|. That computation requires that the |dst_rect|
+ // parameter be configured.
+ DrawRenderPassDrawQuadParams params;
+ params.quad = ca_layer_overlay->rpdq.get();
+ params.flip_texture = true;
+ params.contents_texture = contents_texture;
+
+ SkMatrix scale_matrix;
+ scale_matrix.setScale(params.quad->filters_scale.x(),
+ params.quad->filters_scale.y());
+ gfx::Rect dst_rect =
+ params.quad->filters.MapRect(params.quad->rect, scale_matrix);
+ params.dst_rect.SetRect(static_cast<float>(dst_rect.x()),
+ static_cast<float>(dst_rect.y()),
+ static_cast<float>(dst_rect.width()),
+ static_cast<float>(dst_rect.height()));
+
+ if (!UpdateRPDQWithSkiaFilters(&params)) {
+ return;
+ }
+
+ // |params.dst_rect| and |params.src_offset| now contain values that reflect a
+ // potentially increased-size content area.
+ gfx::RectF updated_dst_rect = params.dst_rect;
+ gfx::Point updated_src_offset = params.src_offset;
+
+ // Establish temp texture and fbo.
+ GLuint temp_texture;
+ GLuint temp_fbo;
+
+ gl_->GenTextures(1, &temp_texture);
+ ScopedTextureDeleter texture_deleter(temp_texture, gl_);
+ gl_->BindTexture(GL_TEXTURE_2D, temp_texture);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, updated_dst_rect.width(),
+ updated_dst_rect.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ nullptr);
+
+ gl_->GenFramebuffers(1, &temp_fbo);
+ ScopedFramebufferDeleter framebuffer_deleter(temp_fbo, gl_);
+ gl_->BindFramebuffer(GL_FRAMEBUFFER, temp_fbo);
+ gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ temp_texture, 0);
+ DCHECK(gl_->CheckFramebufferStatus(GL_FRAMEBUFFER) ==
+ GL_FRAMEBUFFER_COMPLETE);
+
+ // Clear to 0 to ensure the background is transparent.
+ gl_->ClearColor(0, 0, 0, 0);
+ gl_->Clear(GL_COLOR_BUFFER_BIT);
+
+ // Set up a new drawing context. The viewport should be the same size as
+ // |temp_fbo|. Update the viewport using InitializeViewport(). This requires
+ // creating a dummy DrawingFrame. This also calculates the projection and
+ // window matrices.
+ DrawingFrame frame;
+ force_drawing_frame_framebuffer_flipped_ = &frame;
+ gfx::Rect frame_rect =
+ gfx::Rect(0, 0, updated_dst_rect.width(), updated_dst_rect.height());
+ InitializeViewport(&frame, frame_rect, frame_rect, frame_rect.size());
+ force_drawing_frame_framebuffer_flipped_ = nullptr;
+ SetViewport();
+ params.projection_matrix = frame.projection_matrix;
+ params.window_matrix = frame.window_matrix;
+
+ // The SharedQuadState for the RenderPassDrawQuad needs to be updated to
+ // reflect the new viewport.
+ SharedQuadState sqs = *(ca_layer_overlay->rpdq->shared_quad_state);
+ ca_layer_overlay->rpdq->shared_quad_state = &sqs;
+ sqs.quad_to_target_transform = gfx::Transform();
+ sqs.quad_to_target_transform.Translate(-updated_dst_rect.x(),
+ -updated_dst_rect.y());
+
+ // Perform basic initialization in the new viewport.
+ if (!InitializeRPDQParameters(&params))
+ return;
+
+ // Update |dst_rect| and |src_offset| with the values originally calculated
+ // from Skia.
+ params.dst_rect = updated_dst_rect;
+ params.src_offset = updated_src_offset;
+
+ UpdateRPDQTexturesForSampling(&params);
+ UpdateRPDQBlendMode(&params);
+ ChooseRPDQProgram(&params);
+ UpdateRPDQUniforms(&params);
+
+ // Prior to drawing, set up the destination framebuffer.
+ gl_->BindFramebuffer(GL_FRAMEBUFFER, temp_fbo);
+ DrawRPDQ(params);
ccameron 2016/08/04 01:46:01 I'll need to understand this a bit better, but, my
erikchen 2016/08/05 17:15:06 Your suggestion is sound. The new PS implements yo
+
+ // Copy from the temporary framebuffer into an overlay.
+ *resource = overlay_resource_pool_->AcquireResource(
+ gfx::Size(updated_dst_rect.width(), updated_dst_rect.height()),
+ ResourceFormat::RGBA_8888);
+ ResourceProvider::ScopedWriteLockGL destination(resource_provider_,
+ (*resource)->id(), false);
+ gl_->CopySubTextureCHROMIUM(temp_texture, destination.texture_id(), 0, 0, 0,
+ 0, updated_dst_rect.width(),
+ updated_dst_rect.height(), GL_TRUE, GL_FALSE,
+ GL_FALSE);
+
+ // Update the CALayerOverlaySharedState to reflect the new size and translate
+ // of the overlay.
+ ca_layer_overlay->bounds_rect =
+ gfx::RectF(0, 0, updated_dst_rect.width(), updated_dst_rect.height());
+ scoped_refptr<CALayerOverlaySharedState> shared_state =
+ (new CALayerOverlaySharedState);
+ *shared_state = *ca_layer_overlay->shared_state;
+ ca_layer_overlay->shared_state = shared_state;
ccameron 2016/08/04 01:46:01 This doesn't strike me as correct. What if shared_
erikchen 2016/08/05 17:15:06 Right. This should have been preTranslate.
+ float x_translate = shared_state->transform.getFloat(0, 3);
+ float y_translate = shared_state->transform.getFloat(1, 3);
+ float z_translate = shared_state->transform.getFloat(2, 3);
+ shared_state->transform.setTranslate(x_translate + updated_dst_rect.x(),
+ y_translate + updated_dst_rect.y(),
+ z_translate);
+}
+
} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698