Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / compositor / reflector_impl.cc
bloba3d8f71aaa191112b610efdb404028de33aaacae
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/compositor/reflector_impl.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "content/browser/compositor/browser_compositor_output_surface.h"
10 #include "content/browser/compositor/owned_mailbox.h"
11 #include "content/common/gpu/client/gl_helper.h"
12 #include "ui/compositor/layer.h"
14 namespace content {
16 ReflectorImpl::ReflectorImpl(ui::Compositor* mirrored_compositor,
17 ui::Layer* mirroring_layer)
18 : mirrored_compositor_(mirrored_compositor),
19 mirroring_layer_(mirroring_layer),
20 mirrored_compositor_gl_helper_texture_id_(0),
21 needs_set_mailbox_(false),
22 flip_texture_(false),
23 output_surface_(nullptr) {
26 ReflectorImpl::~ReflectorImpl() {
29 void ReflectorImpl::Shutdown() {
30 if (output_surface_)
31 DetachFromOutputSurface();
32 // Prevent the ReflectorImpl from picking up a new output surface.
33 mirroring_layer_ = nullptr;
36 void ReflectorImpl::DetachFromOutputSurface() {
37 DCHECK(output_surface_);
38 output_surface_->SetReflector(nullptr);
39 DCHECK(mailbox_.get());
40 mailbox_ = nullptr;
41 output_surface_ = nullptr;
42 mirrored_compositor_gl_helper_->DeleteTexture(
43 mirrored_compositor_gl_helper_texture_id_);
44 mirrored_compositor_gl_helper_texture_id_ = 0;
45 mirrored_compositor_gl_helper_ = nullptr;
46 mirroring_layer_->SetShowSolidColorContent();
49 void ReflectorImpl::OnSourceSurfaceReady(
50 BrowserCompositorOutputSurface* output_surface) {
51 if (!mirroring_layer_)
52 return; // Was already Shutdown().
53 if (output_surface == output_surface_)
54 return; // Is already attached.
55 if (output_surface_)
56 DetachFromOutputSurface();
58 // Use the GLHelper from the ImageTransportFactory for our OwnedMailbox so we
59 // don't have to manage the lifetime of the GLHelper relative to the lifetime
60 // of the mailbox.
61 GLHelper* shared_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
62 mailbox_ = new OwnedMailbox(shared_helper);
63 needs_set_mailbox_ = true;
65 // Create a GLHelper attached to the mirrored compositor's output surface for
66 // copying the output of the mirrored compositor.
67 mirrored_compositor_gl_helper_.reset(
68 new GLHelper(output_surface->context_provider()->ContextGL(),
69 output_surface->context_provider()->ContextSupport()));
70 // Create a texture id in the name space of the new GLHelper to update the
71 // mailbox being held by the |mirroring_layer_|.
72 mirrored_compositor_gl_helper_texture_id_ =
73 mirrored_compositor_gl_helper_->ConsumeMailboxToTexture(
74 mailbox_->mailbox(), mailbox_->sync_point());
76 flip_texture_ = !output_surface->capabilities().flipped_output_surface;
78 // The texture doesn't have the data. Request full redraw on mirrored
79 // compositor so that the full content will be copied to mirroring compositor.
80 // This full redraw should land us in OnSourceSwapBuffers() to resize the
81 // texture appropriately.
82 mirrored_compositor_->ScheduleFullRedraw();
84 output_surface_ = output_surface;
85 output_surface_->SetReflector(this);
88 void ReflectorImpl::OnMirroringCompositorResized() {
89 mirroring_layer_->SchedulePaint(mirroring_layer_->bounds());
92 void ReflectorImpl::OnSourceSwapBuffers() {
93 if (!mirroring_layer_)
94 return;
95 // Should be attached to the source output surface already.
96 DCHECK(mailbox_.get());
98 gfx::Size size = output_surface_->SurfaceSize();
99 mirrored_compositor_gl_helper_->CopyTextureFullImage(
100 mirrored_compositor_gl_helper_texture_id_, size);
101 // Insert a barrier to make the copy show up in the mirroring compositor's
102 // mailbox. Since the the compositor contexts and the ImageTransportFactory's
103 // GLHelper are all on the same GPU channel, this is sufficient instead of
104 // plumbing through a sync point.
105 mirrored_compositor_gl_helper_->InsertOrderingBarrier();
107 // Request full redraw on mirroring compositor.
108 UpdateTexture(size, mirroring_layer_->bounds());
111 void ReflectorImpl::OnSourcePostSubBuffer(const gfx::Rect& rect) {
112 if (!mirroring_layer_)
113 return;
114 // Should be attached to the source output surface already.
115 DCHECK(mailbox_.get());
117 gfx::Size size = output_surface_->SurfaceSize();
118 mirrored_compositor_gl_helper_->CopyTextureSubImage(
119 mirrored_compositor_gl_helper_texture_id_, rect);
120 // Insert a barrier to make the copy show up in the mirroring compositor's
121 // mailbox. Since the the compositor contexts and the ImageTransportFactory's
122 // GLHelper are all on the same GPU channel, this is sufficient instead of
123 // plumbing through a sync point.
124 mirrored_compositor_gl_helper_->InsertOrderingBarrier();
126 int y = rect.y();
127 // Flip the coordinates to compositor's one.
128 if (flip_texture_)
129 y = size.height() - rect.y() - rect.height();
130 gfx::Rect mirroring_rect(rect.x(), y, rect.width(), rect.height());
132 // Request redraw of the dirty portion in mirroring compositor.
133 UpdateTexture(size, mirroring_rect);
136 static void ReleaseMailbox(scoped_refptr<OwnedMailbox> mailbox,
137 unsigned int sync_point,
138 bool is_lost) {
139 mailbox->UpdateSyncPoint(sync_point);
142 void ReflectorImpl::UpdateTexture(const gfx::Size& source_size,
143 const gfx::Rect& redraw_rect) {
144 if (needs_set_mailbox_) {
145 mirroring_layer_->SetTextureMailbox(
146 cc::TextureMailbox(mailbox_->holder()),
147 cc::SingleReleaseCallback::Create(base::Bind(ReleaseMailbox, mailbox_)),
148 source_size);
149 needs_set_mailbox_ = false;
150 } else {
151 mirroring_layer_->SetTextureSize(source_size);
153 mirroring_layer_->SetBounds(gfx::Rect(source_size));
154 mirroring_layer_->SetTextureFlipped(flip_texture_);
155 mirroring_layer_->SchedulePaint(redraw_rect);
158 } // namespace content