Add remoting and PPAPI tests to GN build
[chromium-blink-merge.git] / content / browser / android / in_process / synchronous_compositor_output_surface.cc
blob48c2bf1e7720576df20fcc126a9b96e6dc5bf490
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/gles2_interface.h"
20 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
21 #include "third_party/skia/include/core/SkCanvas.h"
22 #include "ui/gfx/geometry/rect_conversions.h"
23 #include "ui/gfx/skia_util.h"
24 #include "ui/gfx/transform.h"
26 namespace content {
28 namespace {
30 // Do not limit number of resources, so use an unrealistically high value.
31 const size_t kNumResourcesLimit = 10 * 1000 * 1000;
33 } // namespace
35 class SynchronousCompositorOutputSurface::SoftwareDevice
36 : public cc::SoftwareOutputDevice {
37 public:
38 SoftwareDevice(SynchronousCompositorOutputSurface* surface)
39 : surface_(surface) {
41 void Resize(const gfx::Size& pixel_size, float scale_factor) override {
42 // Intentional no-op: canvas size is controlled by the embedder.
44 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
45 if (!surface_->current_sw_canvas_) {
46 NOTREACHED() << "BeginPaint with no canvas set";
47 return &null_canvas_;
49 LOG_IF(WARNING, surface_->frame_holder_.get())
50 << "Mutliple calls to BeginPaint per frame";
51 return surface_->current_sw_canvas_;
53 void EndPaint(cc::SoftwareFrameData* frame_data) override {}
54 void CopyToPixels(const gfx::Rect& rect, void* pixels) override {
55 NOTIMPLEMENTED();
58 private:
59 SynchronousCompositorOutputSurface* surface_;
60 SkCanvas null_canvas_;
62 DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
65 SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
66 int routing_id,
67 scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
68 : cc::OutputSurface(
69 scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
70 routing_id_(routing_id),
71 registered_(false),
72 current_sw_canvas_(nullptr),
73 memory_policy_(0),
74 output_surface_client_(nullptr),
75 frame_swap_message_queue_(frame_swap_message_queue),
76 begin_frame_source_(nullptr) {
77 capabilities_.deferred_gl_initialization = true;
78 capabilities_.draw_and_swap_full_viewport_every_frame = true;
79 capabilities_.adjust_deadline_for_parent = false;
80 capabilities_.delegated_rendering = true;
81 capabilities_.max_frames_pending = 1;
82 memory_policy_.priority_cutoff_when_visible =
83 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
86 SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {
87 DCHECK(CalledOnValidThread());
88 if (registered_) {
89 SynchronousCompositorRegistry::GetInstance()->UnregisterOutputSurface(
90 routing_id_, this);
92 DCHECK(!begin_frame_source_);
95 bool SynchronousCompositorOutputSurface::BindToClient(
96 cc::OutputSurfaceClient* surface_client) {
97 DCHECK(CalledOnValidThread());
98 if (!cc::OutputSurface::BindToClient(surface_client))
99 return false;
101 output_surface_client_ = surface_client;
102 output_surface_client_->SetMemoryPolicy(memory_policy_);
104 SynchronousCompositorRegistry::GetInstance()->RegisterOutputSurface(
105 routing_id_, this);
106 registered_ = true;
108 return true;
111 void SynchronousCompositorOutputSurface::Reshape(
112 const gfx::Size& size, float scale_factor) {
113 // Intentional no-op: surface size is controlled by the embedder.
116 void SynchronousCompositorOutputSurface::SwapBuffers(
117 cc::CompositorFrame* frame) {
118 DCHECK(CalledOnValidThread());
120 frame_holder_.reset(new cc::CompositorFrame);
121 frame->AssignTo(frame_holder_.get());
123 client_->DidSwapBuffers();
126 void SynchronousCompositorOutputSurface::SetBeginFrameSource(
127 SynchronousCompositorExternalBeginFrameSource* begin_frame_source) {
128 begin_frame_source_ = begin_frame_source;
131 namespace {
132 void AdjustTransform(gfx::Transform* transform, gfx::Rect viewport) {
133 // CC's draw origin starts at the viewport.
134 transform->matrix().postTranslate(-viewport.x(), -viewport.y(), 0);
136 } // namespace
138 bool SynchronousCompositorOutputSurface::InitializeHwDraw(
139 scoped_refptr<cc::ContextProvider> onscreen_context_provider,
140 scoped_refptr<cc::ContextProvider> worker_context_provider) {
141 DCHECK(CalledOnValidThread());
142 DCHECK(HasClient());
143 DCHECK(!context_provider_.get());
145 return InitializeAndSetContext3d(onscreen_context_provider,
146 worker_context_provider);
149 void SynchronousCompositorOutputSurface::ReleaseHwDraw() {
150 DCHECK(CalledOnValidThread());
151 cc::OutputSurface::ReleaseGL();
154 scoped_ptr<cc::CompositorFrame>
155 SynchronousCompositorOutputSurface::DemandDrawHw(
156 gfx::Size surface_size,
157 const gfx::Transform& transform,
158 gfx::Rect viewport,
159 gfx::Rect clip,
160 gfx::Rect viewport_rect_for_tile_priority,
161 const gfx::Transform& transform_for_tile_priority) {
162 DCHECK(CalledOnValidThread());
163 DCHECK(HasClient());
164 DCHECK(context_provider_.get());
166 surface_size_ = surface_size;
167 InvokeComposite(transform,
168 viewport,
169 clip,
170 viewport_rect_for_tile_priority,
171 transform_for_tile_priority,
172 true);
174 return frame_holder_.Pass();
177 scoped_ptr<cc::CompositorFrame>
178 SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
179 DCHECK(CalledOnValidThread());
180 DCHECK(canvas);
181 DCHECK(!current_sw_canvas_);
182 base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas);
184 SkIRect canvas_clip;
185 canvas->getClipDeviceBounds(&canvas_clip);
186 gfx::Rect clip = gfx::SkIRectToRect(canvas_clip);
188 gfx::Transform transform(gfx::Transform::kSkipInitialization);
189 transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4.
191 surface_size_ = gfx::Size(canvas->getDeviceSize().width(),
192 canvas->getDeviceSize().height());
194 // Pass in the cached hw viewport and transform for tile priority to avoid
195 // tile thrashing when the WebView is alternating between hardware and
196 // software draws.
197 InvokeComposite(transform,
198 clip,
199 clip,
200 cached_hw_viewport_rect_for_tile_priority_,
201 cached_hw_transform_for_tile_priority_,
202 false);
204 return frame_holder_.Pass();
207 void SynchronousCompositorOutputSurface::InvokeComposite(
208 const gfx::Transform& transform,
209 gfx::Rect viewport,
210 gfx::Rect clip,
211 gfx::Rect viewport_rect_for_tile_priority,
212 gfx::Transform transform_for_tile_priority,
213 bool hardware_draw) {
214 DCHECK(!frame_holder_.get());
215 DCHECK(begin_frame_source_);
217 gfx::Transform adjusted_transform = transform;
218 AdjustTransform(&adjusted_transform, viewport);
219 SetExternalDrawConstraints(adjusted_transform,
220 viewport,
221 clip,
222 viewport_rect_for_tile_priority,
223 transform_for_tile_priority,
224 !hardware_draw);
225 SetNeedsRedrawRect(gfx::Rect(viewport.size()));
227 begin_frame_source_->BeginFrame();
229 // After software draws (which might move the viewport arbitrarily), restore
230 // the previous hardware viewport to allow CC's tile manager to prioritize
231 // properly.
232 if (hardware_draw) {
233 cached_hw_transform_ = adjusted_transform;
234 cached_hw_viewport_ = viewport;
235 cached_hw_clip_ = clip;
236 cached_hw_viewport_rect_for_tile_priority_ =
237 viewport_rect_for_tile_priority;
238 cached_hw_transform_for_tile_priority_ = transform_for_tile_priority;
239 } else {
240 bool resourceless_software_draw = false;
241 SetExternalDrawConstraints(cached_hw_transform_,
242 cached_hw_viewport_,
243 cached_hw_clip_,
244 cached_hw_viewport_rect_for_tile_priority_,
245 cached_hw_transform_for_tile_priority_,
246 resourceless_software_draw);
249 if (frame_holder_.get())
250 client_->DidSwapBuffersComplete();
253 void SynchronousCompositorOutputSurface::ReturnResources(
254 const cc::CompositorFrameAck& frame_ack) {
255 ReclaimResources(&frame_ack);
258 void SynchronousCompositorOutputSurface::SetMemoryPolicy(size_t bytes_limit) {
259 DCHECK(CalledOnValidThread());
260 memory_policy_.bytes_limit_when_visible = bytes_limit;
261 memory_policy_.num_resources_limit = kNumResourcesLimit;
263 if (output_surface_client_)
264 output_surface_client_->SetMemoryPolicy(memory_policy_);
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