Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / android / in_process / synchronous_compositor_output_surface.cc
blob682c530dc3938d61d0557ddb5e439a1998102c00
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/begin_frame_args.h"
10 #include "cc/output/compositor_frame.h"
11 #include "cc/output/context_provider.h"
12 #include "cc/output/output_surface_client.h"
13 #include "cc/output/software_output_device.h"
14 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
15 #include "content/browser/gpu/compositor_util.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/renderer/gpu/frame_swap_message_queue.h"
18 #include "gpu/command_buffer/client/gles2_interface.h"
19 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
20 #include "third_party/skia/include/core/SkCanvas.h"
21 #include "ui/gfx/rect_conversions.h"
22 #include "ui/gfx/skia_util.h"
23 #include "ui/gfx/transform.h"
25 namespace content {
27 namespace {
29 void DidActivatePendingTree(int routing_id) {
30 SynchronousCompositorOutputSurfaceDelegate* delegate =
31 SynchronousCompositorImpl::FromRoutingID(routing_id);
32 if (delegate)
33 delegate->DidActivatePendingTree();
36 } // namespace
38 class SynchronousCompositorOutputSurface::SoftwareDevice
39 : public cc::SoftwareOutputDevice {
40 public:
41 SoftwareDevice(SynchronousCompositorOutputSurface* surface)
42 : surface_(surface) {
44 virtual void Resize(const gfx::Size& pixel_size,
45 float scale_factor) OVERRIDE {
46 // Intentional no-op: canvas size is controlled by the embedder.
48 virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
49 if (!surface_->current_sw_canvas_) {
50 NOTREACHED() << "BeginPaint with no canvas set";
51 return &null_canvas_;
53 LOG_IF(WARNING, surface_->frame_holder_.get())
54 << "Mutliple calls to BeginPaint per frame";
55 return surface_->current_sw_canvas_;
57 virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE {
59 virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) OVERRIDE {
60 NOTIMPLEMENTED();
63 private:
64 SynchronousCompositorOutputSurface* surface_;
65 SkCanvas null_canvas_;
67 DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
70 SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
71 int routing_id,
72 scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
73 : cc::OutputSurface(
74 scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
75 routing_id_(routing_id),
76 needs_begin_frame_(false),
77 invoking_composite_(false),
78 current_sw_canvas_(NULL),
79 memory_policy_(0),
80 output_surface_client_(NULL),
81 frame_swap_message_queue_(frame_swap_message_queue) {
82 capabilities_.deferred_gl_initialization = true;
83 capabilities_.draw_and_swap_full_viewport_every_frame = true;
84 capabilities_.adjust_deadline_for_parent = false;
85 capabilities_.delegated_rendering = true;
86 capabilities_.max_frames_pending = 1;
87 // Cannot call out to GetDelegate() here as the output surface is not
88 // constructed on the correct thread.
90 memory_policy_.priority_cutoff_when_visible =
91 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
94 SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {
95 DCHECK(CalledOnValidThread());
96 SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate();
97 if (delegate)
98 delegate->DidDestroySynchronousOutputSurface(this);
101 bool SynchronousCompositorOutputSurface::BindToClient(
102 cc::OutputSurfaceClient* surface_client) {
103 DCHECK(CalledOnValidThread());
104 if (!cc::OutputSurface::BindToClient(surface_client))
105 return false;
107 output_surface_client_ = surface_client;
108 output_surface_client_->SetTreeActivationCallback(
109 base::Bind(&DidActivatePendingTree, routing_id_));
110 output_surface_client_->SetMemoryPolicy(memory_policy_);
112 SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate();
113 if (delegate)
114 delegate->DidBindOutputSurface(this);
116 return true;
119 void SynchronousCompositorOutputSurface::Reshape(
120 const gfx::Size& size, float scale_factor) {
121 // Intentional no-op: surface size is controlled by the embedder.
124 void SynchronousCompositorOutputSurface::SetNeedsBeginFrame(bool enable) {
125 DCHECK(CalledOnValidThread());
126 needs_begin_frame_ = enable;
127 SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate();
128 if (delegate && !invoking_composite_)
129 delegate->SetContinuousInvalidate(needs_begin_frame_);
132 void SynchronousCompositorOutputSurface::SwapBuffers(
133 cc::CompositorFrame* frame) {
134 DCHECK(CalledOnValidThread());
136 frame_holder_.reset(new cc::CompositorFrame);
137 frame->AssignTo(frame_holder_.get());
139 client_->DidSwapBuffers();
142 namespace {
143 void AdjustTransform(gfx::Transform* transform, gfx::Rect viewport) {
144 // CC's draw origin starts at the viewport.
145 transform->matrix().postTranslate(-viewport.x(), -viewport.y(), 0);
147 } // namespace
149 bool SynchronousCompositorOutputSurface::InitializeHwDraw(
150 scoped_refptr<cc::ContextProvider> onscreen_context_provider) {
151 DCHECK(CalledOnValidThread());
152 DCHECK(HasClient());
153 DCHECK(!context_provider_);
155 return InitializeAndSetContext3d(onscreen_context_provider);
158 void SynchronousCompositorOutputSurface::ReleaseHwDraw() {
159 DCHECK(CalledOnValidThread());
160 cc::OutputSurface::ReleaseGL();
163 scoped_ptr<cc::CompositorFrame>
164 SynchronousCompositorOutputSurface::DemandDrawHw(
165 gfx::Size surface_size,
166 const gfx::Transform& transform,
167 gfx::Rect viewport,
168 gfx::Rect clip,
169 gfx::Rect viewport_rect_for_tile_priority,
170 const gfx::Transform& transform_for_tile_priority) {
171 DCHECK(CalledOnValidThread());
172 DCHECK(HasClient());
173 DCHECK(context_provider_);
175 surface_size_ = surface_size;
176 InvokeComposite(transform,
177 viewport,
178 clip,
179 viewport_rect_for_tile_priority,
180 transform_for_tile_priority,
181 true);
183 return frame_holder_.Pass();
186 scoped_ptr<cc::CompositorFrame>
187 SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
188 DCHECK(CalledOnValidThread());
189 DCHECK(canvas);
190 DCHECK(!current_sw_canvas_);
191 base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas);
193 SkIRect canvas_clip;
194 canvas->getClipDeviceBounds(&canvas_clip);
195 gfx::Rect clip = gfx::SkIRectToRect(canvas_clip);
197 gfx::Transform transform(gfx::Transform::kSkipInitialization);
198 transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4.
200 surface_size_ = gfx::Size(canvas->getDeviceSize().width(),
201 canvas->getDeviceSize().height());
203 // Resourceless software draw does not need viewport_for_tiling.
204 gfx::Rect empty;
205 InvokeComposite(transform, clip, clip, empty, gfx::Transform(), false);
207 return frame_holder_.Pass();
210 void SynchronousCompositorOutputSurface::InvokeComposite(
211 const gfx::Transform& transform,
212 gfx::Rect viewport,
213 gfx::Rect clip,
214 gfx::Rect viewport_rect_for_tile_priority,
215 gfx::Transform transform_for_tile_priority,
216 bool hardware_draw) {
217 DCHECK(!invoking_composite_);
218 DCHECK(!frame_holder_.get());
219 base::AutoReset<bool> invoking_composite_resetter(&invoking_composite_, true);
221 gfx::Transform adjusted_transform = transform;
222 AdjustTransform(&adjusted_transform, viewport);
223 SetExternalDrawConstraints(adjusted_transform,
224 viewport,
225 clip,
226 viewport_rect_for_tile_priority,
227 transform_for_tile_priority,
228 !hardware_draw);
229 SetNeedsRedrawRect(gfx::Rect(viewport.size()));
230 client_->BeginFrame(cc::BeginFrameArgs::CreateForSynchronousCompositor());
232 // After software draws (which might move the viewport arbitrarily), restore
233 // the previous hardware viewport to allow CC's tile manager to prioritize
234 // properly.
235 if (hardware_draw) {
236 cached_hw_transform_ = adjusted_transform;
237 cached_hw_viewport_ = viewport;
238 cached_hw_clip_ = clip;
239 cached_hw_viewport_rect_for_tile_priority_ =
240 viewport_rect_for_tile_priority;
241 cached_hw_transform_for_tile_priority_ = transform_for_tile_priority;
242 } else {
243 bool resourceless_software_draw = false;
244 SetExternalDrawConstraints(cached_hw_transform_,
245 cached_hw_viewport_,
246 cached_hw_clip_,
247 cached_hw_viewport_rect_for_tile_priority_,
248 cached_hw_transform_for_tile_priority_,
249 resourceless_software_draw);
252 if (frame_holder_.get())
253 client_->DidSwapBuffersComplete();
255 SynchronousCompositorOutputSurfaceDelegate* delegate = GetDelegate();
256 if (delegate)
257 delegate->SetContinuousInvalidate(needs_begin_frame_);
260 void SynchronousCompositorOutputSurface::ReturnResources(
261 const cc::CompositorFrameAck& frame_ack) {
262 ReclaimResources(&frame_ack);
265 void SynchronousCompositorOutputSurface::SetMemoryPolicy(
266 const SynchronousCompositorMemoryPolicy& policy) {
267 DCHECK(CalledOnValidThread());
268 memory_policy_.bytes_limit_when_visible = policy.bytes_limit;
269 memory_policy_.num_resources_limit = policy.num_resources_limit;
271 if (output_surface_client_)
272 output_surface_client_->SetMemoryPolicy(memory_policy_);
275 void SynchronousCompositorOutputSurface::GetMessagesToDeliver(
276 ScopedVector<IPC::Message>* messages) {
277 DCHECK(CalledOnValidThread());
278 scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
279 frame_swap_message_queue_->AcquireSendMessageScope();
280 frame_swap_message_queue_->DrainMessages(messages);
283 // Not using base::NonThreadSafe as we want to enforce a more exacting threading
284 // requirement: SynchronousCompositorOutputSurface() must only be used on the UI
285 // thread.
286 bool SynchronousCompositorOutputSurface::CalledOnValidThread() const {
287 return BrowserThread::CurrentlyOn(BrowserThread::UI);
290 SynchronousCompositorOutputSurfaceDelegate*
291 SynchronousCompositorOutputSurface::GetDelegate() {
292 return SynchronousCompositorImpl::FromRoutingID(routing_id_);
295 } // namespace content