[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / android / in_process / synchronous_compositor_output_surface.cc
blob85c7bcb3c39832eadbcc9d14bddee0263d070b1a
1 // Copyright 2013 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/android/in_process/synchronous_compositor_output_surface.h"
7 #include "base/auto_reset.h"
8 #include "base/logging.h"
9 #include "cc/output/compositor_frame.h"
10 #include "cc/output/context_provider.h"
11 #include "cc/output/output_surface_client.h"
12 #include "cc/output/software_output_device.h"
13 #include "content/browser/android/in_process/synchronous_compositor_external_begin_frame_source.h"
14 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
15 #include "content/browser/android/in_process/synchronous_compositor_registry.h"
16 #include "content/browser/gpu/compositor_util.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/renderer/gpu/frame_swap_message_queue.h"
19 #include "gpu/command_buffer/client/context_support.h"
20 #include "gpu/command_buffer/client/gles2_interface.h"
21 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
22 #include "third_party/skia/include/core/SkCanvas.h"
23 #include "ui/gfx/geometry/rect_conversions.h"
24 #include "ui/gfx/skia_util.h"
25 #include "ui/gfx/transform.h"
27 namespace content {
29 namespace {
31 // Do not limit number of resources, so use an unrealistically high value.
32 const size_t kNumResourcesLimit = 10 * 1000 * 1000;
34 } // namespace
36 class SynchronousCompositorOutputSurface::SoftwareDevice
37 : public cc::SoftwareOutputDevice {
38 public:
39 SoftwareDevice(SynchronousCompositorOutputSurface* surface)
40 : surface_(surface) {
42 void Resize(const gfx::Size& pixel_size, float scale_factor) override {
43 // Intentional no-op: canvas size is controlled by the embedder.
45 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
46 if (!surface_->current_sw_canvas_) {
47 NOTREACHED() << "BeginPaint with no canvas set";
48 return &null_canvas_;
50 LOG_IF(WARNING, surface_->frame_holder_.get())
51 << "Mutliple calls to BeginPaint per frame";
52 return surface_->current_sw_canvas_;
54 void EndPaint() override {}
56 private:
57 SynchronousCompositorOutputSurface* surface_;
58 SkCanvas null_canvas_;
60 DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
63 SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
64 const scoped_refptr<cc::ContextProvider>& context_provider,
65 const scoped_refptr<cc::ContextProvider>& worker_context_provider,
66 int routing_id,
67 scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
68 : cc::OutputSurface(
69 context_provider,
70 worker_context_provider,
71 scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
72 routing_id_(routing_id),
73 registered_(false),
74 current_sw_canvas_(nullptr),
75 memory_policy_(0),
76 frame_swap_message_queue_(frame_swap_message_queue) {
77 capabilities_.draw_and_swap_full_viewport_every_frame = true;
78 capabilities_.adjust_deadline_for_parent = false;
79 capabilities_.delegated_rendering = true;
80 capabilities_.max_frames_pending = 1;
81 memory_policy_.priority_cutoff_when_visible =
82 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
85 SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {
86 DCHECK(CalledOnValidThread());
87 if (registered_) {
88 SynchronousCompositorRegistry::GetInstance()->UnregisterOutputSurface(
89 routing_id_, this);
93 bool SynchronousCompositorOutputSurface::BindToClient(
94 cc::OutputSurfaceClient* surface_client) {
95 DCHECK(CalledOnValidThread());
96 if (!cc::OutputSurface::BindToClient(surface_client))
97 return false;
99 client_->SetMemoryPolicy(memory_policy_);
101 SynchronousCompositorRegistry::GetInstance()->RegisterOutputSurface(
102 routing_id_, this);
103 registered_ = true;
105 return true;
108 void SynchronousCompositorOutputSurface::SetCompositor(
109 SynchronousCompositorImpl* compositor) {
110 DCHECK(CalledOnValidThread());
111 compositor_ = compositor;
114 void SynchronousCompositorOutputSurface::Reshape(
115 const gfx::Size& size, float scale_factor) {
116 // Intentional no-op: surface size is controlled by the embedder.
119 void SynchronousCompositorOutputSurface::SwapBuffers(
120 cc::CompositorFrame* frame) {
121 DCHECK(CalledOnValidThread());
123 frame_holder_.reset(new cc::CompositorFrame);
124 frame->AssignTo(frame_holder_.get());
126 client_->DidSwapBuffers();
129 void SynchronousCompositorOutputSurface::Invalidate() {
130 DCHECK(CalledOnValidThread());
131 compositor_->PostInvalidate();
134 namespace {
135 void AdjustTransform(gfx::Transform* transform, gfx::Rect viewport) {
136 // CC's draw origin starts at the viewport.
137 transform->matrix().postTranslate(-viewport.x(), -viewport.y(), 0);
139 } // namespace
141 scoped_ptr<cc::CompositorFrame>
142 SynchronousCompositorOutputSurface::DemandDrawHw(
143 gfx::Size surface_size,
144 const gfx::Transform& transform,
145 gfx::Rect viewport,
146 gfx::Rect clip,
147 gfx::Rect viewport_rect_for_tile_priority,
148 const gfx::Transform& transform_for_tile_priority) {
149 DCHECK(CalledOnValidThread());
150 DCHECK(HasClient());
151 DCHECK(context_provider_.get());
153 surface_size_ = surface_size;
154 InvokeComposite(transform,
155 viewport,
156 clip,
157 viewport_rect_for_tile_priority,
158 transform_for_tile_priority,
159 true);
161 return frame_holder_.Pass();
164 scoped_ptr<cc::CompositorFrame>
165 SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
166 DCHECK(CalledOnValidThread());
167 DCHECK(canvas);
168 DCHECK(!current_sw_canvas_);
170 base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas);
172 SkIRect canvas_clip;
173 canvas->getClipDeviceBounds(&canvas_clip);
174 gfx::Rect clip = gfx::SkIRectToRect(canvas_clip);
176 gfx::Transform transform(gfx::Transform::kSkipInitialization);
177 transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4.
179 surface_size_ = gfx::Size(canvas->getDeviceSize().width(),
180 canvas->getDeviceSize().height());
182 // Pass in the cached hw viewport and transform for tile priority to avoid
183 // tile thrashing when the WebView is alternating between hardware and
184 // software draws.
185 InvokeComposite(transform,
186 clip,
187 clip,
188 cached_hw_viewport_rect_for_tile_priority_,
189 cached_hw_transform_for_tile_priority_,
190 false);
192 return frame_holder_.Pass();
195 void SynchronousCompositorOutputSurface::InvokeComposite(
196 const gfx::Transform& transform,
197 gfx::Rect viewport,
198 gfx::Rect clip,
199 gfx::Rect viewport_rect_for_tile_priority,
200 gfx::Transform transform_for_tile_priority,
201 bool hardware_draw) {
202 DCHECK(!frame_holder_.get());
204 gfx::Transform adjusted_transform = transform;
205 AdjustTransform(&adjusted_transform, viewport);
206 SetExternalDrawConstraints(adjusted_transform,
207 viewport,
208 clip,
209 viewport_rect_for_tile_priority,
210 transform_for_tile_priority,
211 !hardware_draw);
212 SetNeedsRedrawRect(gfx::Rect(viewport.size()));
214 client_->OnDraw();
216 // After software draws (which might move the viewport arbitrarily), restore
217 // the previous hardware viewport to allow CC's tile manager to prioritize
218 // properly.
219 if (hardware_draw) {
220 cached_hw_transform_ = adjusted_transform;
221 cached_hw_viewport_ = viewport;
222 cached_hw_clip_ = clip;
223 cached_hw_viewport_rect_for_tile_priority_ =
224 viewport_rect_for_tile_priority;
225 cached_hw_transform_for_tile_priority_ = transform_for_tile_priority;
226 } else {
227 bool resourceless_software_draw = false;
228 SetExternalDrawConstraints(cached_hw_transform_,
229 cached_hw_viewport_,
230 cached_hw_clip_,
231 cached_hw_viewport_rect_for_tile_priority_,
232 cached_hw_transform_for_tile_priority_,
233 resourceless_software_draw);
236 if (frame_holder_.get())
237 client_->DidSwapBuffersComplete();
240 void SynchronousCompositorOutputSurface::ReturnResources(
241 const cc::CompositorFrameAck& frame_ack) {
242 ReclaimResources(&frame_ack);
245 void SynchronousCompositorOutputSurface::SetMemoryPolicy(size_t bytes_limit) {
246 DCHECK(CalledOnValidThread());
247 bool became_zero = memory_policy_.bytes_limit_when_visible && !bytes_limit;
248 bool became_non_zero =
249 !memory_policy_.bytes_limit_when_visible && bytes_limit;
250 memory_policy_.bytes_limit_when_visible = bytes_limit;
251 memory_policy_.num_resources_limit = kNumResourcesLimit;
253 if (client_)
254 client_->SetMemoryPolicy(memory_policy_);
256 if (became_zero) {
257 // This is small hack to drop context resources without destroying it
258 // when this compositor is put into the background.
259 context_provider()->ContextSupport()->SetAggressivelyFreeResources(
260 true /* aggressively_free_resources */);
261 } else if (became_non_zero) {
262 context_provider()->ContextSupport()->SetAggressivelyFreeResources(
263 false /* aggressively_free_resources */);
267 void SynchronousCompositorOutputSurface::SetTreeActivationCallback(
268 const base::Closure& callback) {
269 DCHECK(client_);
270 client_->SetTreeActivationCallback(callback);
273 void SynchronousCompositorOutputSurface::GetMessagesToDeliver(
274 ScopedVector<IPC::Message>* messages) {
275 DCHECK(CalledOnValidThread());
276 scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
277 frame_swap_message_queue_->AcquireSendMessageScope();
278 frame_swap_message_queue_->DrainMessages(messages);
281 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
282 // requirement: SynchronousCompositorOutputSurface() must only be used on the UI
283 // thread.
284 bool SynchronousCompositorOutputSurface::CalledOnValidThread() const {
285 return BrowserThread::CurrentlyOn(BrowserThread::UI);
288 } // namespace content