Add missing OWNERS for chrome_android.gypi
[chromium-blink-merge.git] / cc / output / output_surface.cc
blob2ffcf95901f8885463802adeb584ef27c739847b
1 // Copyright (c) 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 "cc/output/output_surface.h"
7 #include <set>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/debug/trace_event.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/strings/string_split.h"
16 #include "base/strings/string_util.h"
17 #include "cc/output/compositor_frame.h"
18 #include "cc/output/managed_memory_policy.h"
19 #include "cc/output/output_surface_client.h"
20 #include "cc/scheduler/delay_based_time_source.h"
21 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
22 #include "third_party/khronos/GLES2/gl2.h"
23 #include "third_party/khronos/GLES2/gl2ext.h"
24 #include "ui/gfx/rect.h"
25 #include "ui/gfx/size.h"
27 using std::set;
28 using std::string;
29 using std::vector;
31 namespace cc {
33 OutputSurface::OutputSurface(scoped_refptr<ContextProvider> context_provider)
34 : context_provider_(context_provider),
35 has_gl_discard_backbuffer_(false),
36 has_swap_buffers_complete_callback_(false),
37 device_scale_factor_(-1),
38 weak_ptr_factory_(this),
39 max_frames_pending_(0),
40 pending_swap_buffers_(0),
41 needs_begin_frame_(false),
42 begin_frame_pending_(false),
43 client_(NULL),
44 check_for_retroactive_begin_frame_pending_(false),
45 external_stencil_test_enabled_(false) {}
47 OutputSurface::OutputSurface(
48 scoped_ptr<cc::SoftwareOutputDevice> software_device)
49 : software_device_(software_device.Pass()),
50 has_gl_discard_backbuffer_(false),
51 has_swap_buffers_complete_callback_(false),
52 device_scale_factor_(-1),
53 weak_ptr_factory_(this),
54 max_frames_pending_(0),
55 pending_swap_buffers_(0),
56 needs_begin_frame_(false),
57 begin_frame_pending_(false),
58 client_(NULL),
59 check_for_retroactive_begin_frame_pending_(false),
60 external_stencil_test_enabled_(false) {}
62 OutputSurface::OutputSurface(
63 scoped_refptr<ContextProvider> context_provider,
64 scoped_ptr<cc::SoftwareOutputDevice> software_device)
65 : context_provider_(context_provider),
66 software_device_(software_device.Pass()),
67 has_gl_discard_backbuffer_(false),
68 has_swap_buffers_complete_callback_(false),
69 device_scale_factor_(-1),
70 weak_ptr_factory_(this),
71 max_frames_pending_(0),
72 pending_swap_buffers_(0),
73 needs_begin_frame_(false),
74 begin_frame_pending_(false),
75 client_(NULL),
76 check_for_retroactive_begin_frame_pending_(false),
77 external_stencil_test_enabled_(false) {}
79 void OutputSurface::InitializeBeginFrameEmulation(
80 base::SingleThreadTaskRunner* task_runner,
81 bool throttle_frame_production,
82 base::TimeDelta interval) {
83 if (throttle_frame_production) {
84 frame_rate_controller_.reset(
85 new FrameRateController(
86 DelayBasedTimeSource::Create(interval, task_runner)));
87 } else {
88 frame_rate_controller_.reset(new FrameRateController(task_runner));
91 frame_rate_controller_->SetClient(this);
92 frame_rate_controller_->SetMaxSwapsPending(max_frames_pending_);
93 frame_rate_controller_->SetDeadlineAdjustment(
94 capabilities_.adjust_deadline_for_parent ?
95 BeginFrameArgs::DefaultDeadlineAdjustment() : base::TimeDelta());
97 // The new frame rate controller will consume the swap acks of the old
98 // frame rate controller, so we set that expectation up here.
99 for (int i = 0; i < pending_swap_buffers_; i++)
100 frame_rate_controller_->DidSwapBuffers();
103 void OutputSurface::SetMaxFramesPending(int max_frames_pending) {
104 if (frame_rate_controller_)
105 frame_rate_controller_->SetMaxSwapsPending(max_frames_pending);
106 max_frames_pending_ = max_frames_pending;
109 void OutputSurface::OnVSyncParametersChanged(base::TimeTicks timebase,
110 base::TimeDelta interval) {
111 TRACE_EVENT2("cc", "OutputSurface::OnVSyncParametersChanged",
112 "timebase", (timebase - base::TimeTicks()).InSecondsF(),
113 "interval", interval.InSecondsF());
114 if (frame_rate_controller_)
115 frame_rate_controller_->SetTimebaseAndInterval(timebase, interval);
118 void OutputSurface::FrameRateControllerTick(bool throttled,
119 const BeginFrameArgs& args) {
120 DCHECK(frame_rate_controller_);
121 if (throttled)
122 skipped_begin_frame_args_ = args;
123 else
124 BeginFrame(args);
127 // Forwarded to OutputSurfaceClient
128 void OutputSurface::SetNeedsRedrawRect(gfx::Rect damage_rect) {
129 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect");
130 client_->SetNeedsRedrawRect(damage_rect);
133 void OutputSurface::SetNeedsBeginFrame(bool enable) {
134 TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable);
135 needs_begin_frame_ = enable;
136 begin_frame_pending_ = false;
137 if (frame_rate_controller_) {
138 BeginFrameArgs skipped = frame_rate_controller_->SetActive(enable);
139 if (skipped.IsValid())
140 skipped_begin_frame_args_ = skipped;
142 if (needs_begin_frame_)
143 PostCheckForRetroactiveBeginFrame();
146 void OutputSurface::BeginFrame(const BeginFrameArgs& args) {
147 TRACE_EVENT2("cc", "OutputSurface::BeginFrame",
148 "begin_frame_pending_", begin_frame_pending_,
149 "pending_swap_buffers_", pending_swap_buffers_);
150 if (!needs_begin_frame_ || begin_frame_pending_ ||
151 (pending_swap_buffers_ >= max_frames_pending_ &&
152 max_frames_pending_ > 0)) {
153 skipped_begin_frame_args_ = args;
154 } else {
155 begin_frame_pending_ = true;
156 client_->BeginFrame(args);
157 // args might be an alias for skipped_begin_frame_args_.
158 // Do not reset it before calling BeginFrame!
159 skipped_begin_frame_args_ = BeginFrameArgs();
163 base::TimeDelta OutputSurface::AlternateRetroactiveBeginFramePeriod() {
164 return BeginFrameArgs::DefaultRetroactiveBeginFramePeriod();
167 void OutputSurface::PostCheckForRetroactiveBeginFrame() {
168 if (!skipped_begin_frame_args_.IsValid() ||
169 check_for_retroactive_begin_frame_pending_)
170 return;
172 base::MessageLoop::current()->PostTask(
173 FROM_HERE,
174 base::Bind(&OutputSurface::CheckForRetroactiveBeginFrame,
175 weak_ptr_factory_.GetWeakPtr()));
176 check_for_retroactive_begin_frame_pending_ = true;
179 void OutputSurface::CheckForRetroactiveBeginFrame() {
180 TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginFrame");
181 check_for_retroactive_begin_frame_pending_ = false;
182 base::TimeTicks now = base::TimeTicks::Now();
183 // TODO(brianderson): Remove the alternative deadline once we have better
184 // deadline estimations.
185 base::TimeTicks alternative_deadline =
186 skipped_begin_frame_args_.frame_time +
187 AlternateRetroactiveBeginFramePeriod();
188 if (now < skipped_begin_frame_args_.deadline ||
189 now < alternative_deadline) {
190 BeginFrame(skipped_begin_frame_args_);
194 void OutputSurface::DidSwapBuffers() {
195 begin_frame_pending_ = false;
196 pending_swap_buffers_++;
197 TRACE_EVENT1("cc", "OutputSurface::DidSwapBuffers",
198 "pending_swap_buffers_", pending_swap_buffers_);
199 if (frame_rate_controller_)
200 frame_rate_controller_->DidSwapBuffers();
201 PostCheckForRetroactiveBeginFrame();
204 void OutputSurface::OnSwapBuffersComplete(const CompositorFrameAck* ack) {
205 pending_swap_buffers_--;
206 TRACE_EVENT1("cc", "OutputSurface::OnSwapBuffersComplete",
207 "pending_swap_buffers_", pending_swap_buffers_);
208 client_->OnSwapBuffersComplete(ack);
209 if (frame_rate_controller_)
210 frame_rate_controller_->DidSwapBuffersComplete();
211 PostCheckForRetroactiveBeginFrame();
214 void OutputSurface::DidLoseOutputSurface() {
215 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
216 begin_frame_pending_ = false;
217 pending_swap_buffers_ = 0;
218 client_->DidLoseOutputSurface();
221 void OutputSurface::SetExternalStencilTest(bool enabled) {
222 external_stencil_test_enabled_ = enabled;
225 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform,
226 gfx::Rect viewport,
227 gfx::Rect clip,
228 bool valid_for_tile_management) {
229 client_->SetExternalDrawConstraints(
230 transform, viewport, clip, valid_for_tile_management);
233 OutputSurface::~OutputSurface() {
234 if (frame_rate_controller_)
235 frame_rate_controller_->SetActive(false);
236 ResetContext3d();
239 bool OutputSurface::HasExternalStencilTest() const {
240 return external_stencil_test_enabled_;
243 bool OutputSurface::ForcedDrawToSoftwareDevice() const { return false; }
245 bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) {
246 DCHECK(client);
247 client_ = client;
248 bool success = true;
250 if (context_provider_) {
251 success = context_provider_->BindToCurrentThread();
252 if (success)
253 SetUpContext3d();
256 if (!success)
257 client_ = NULL;
259 return success;
262 bool OutputSurface::InitializeAndSetContext3d(
263 scoped_refptr<ContextProvider> context_provider,
264 scoped_refptr<ContextProvider> offscreen_context_provider) {
265 DCHECK(!context_provider_);
266 DCHECK(context_provider);
267 DCHECK(client_);
269 bool success = false;
270 if (context_provider->BindToCurrentThread()) {
271 context_provider_ = context_provider;
272 SetUpContext3d();
273 if (client_->DeferredInitialize(offscreen_context_provider))
274 success = true;
277 if (!success)
278 ResetContext3d();
280 return success;
283 void OutputSurface::ReleaseGL() {
284 DCHECK(client_);
285 DCHECK(context_provider_);
286 client_->ReleaseGL();
287 ResetContext3d();
290 void OutputSurface::SetUpContext3d() {
291 DCHECK(context_provider_);
292 DCHECK(client_);
294 const ContextProvider::Capabilities& caps =
295 context_provider_->ContextCapabilities();
297 has_gl_discard_backbuffer_ = caps.discard_backbuffer;
298 has_swap_buffers_complete_callback_ = caps.swapbuffers_complete_callback;
300 context_provider_->SetLostContextCallback(
301 base::Bind(&OutputSurface::DidLoseOutputSurface,
302 base::Unretained(this)));
303 context_provider_->SetSwapBuffersCompleteCallback(
304 base::Bind(&OutputSurface::OnSwapBuffersComplete,
305 base::Unretained(this),
306 static_cast<CompositorFrameAck*>(NULL)));
307 context_provider_->SetMemoryPolicyChangedCallback(
308 base::Bind(&OutputSurface::SetMemoryPolicy,
309 base::Unretained(this)));
312 void OutputSurface::ResetContext3d() {
313 if (context_provider_.get()) {
314 context_provider_->SetLostContextCallback(
315 ContextProvider::LostContextCallback());
316 context_provider_->SetSwapBuffersCompleteCallback(
317 ContextProvider::SwapBuffersCompleteCallback());
318 context_provider_->SetMemoryPolicyChangedCallback(
319 ContextProvider::MemoryPolicyChangedCallback());
321 context_provider_ = NULL;
324 void OutputSurface::EnsureBackbuffer() {
325 if (context_provider_ && has_gl_discard_backbuffer_)
326 context_provider_->Context3d()->ensureBackbufferCHROMIUM();
329 void OutputSurface::DiscardBackbuffer() {
330 if (context_provider_ && has_gl_discard_backbuffer_)
331 context_provider_->Context3d()->discardBackbufferCHROMIUM();
334 void OutputSurface::Reshape(gfx::Size size, float scale_factor) {
335 if (size == surface_size_ && scale_factor == device_scale_factor_)
336 return;
338 surface_size_ = size;
339 device_scale_factor_ = scale_factor;
340 if (context_provider_) {
341 context_provider_->Context3d()->reshapeWithScaleFactor(
342 size.width(), size.height(), scale_factor);
344 if (software_device_)
345 software_device_->Resize(size);
348 gfx::Size OutputSurface::SurfaceSize() const {
349 return surface_size_;
352 void OutputSurface::BindFramebuffer() {
353 DCHECK(context_provider_);
354 context_provider_->Context3d()->bindFramebuffer(GL_FRAMEBUFFER, 0);
357 void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
358 if (frame->software_frame_data) {
359 PostSwapBuffersComplete();
360 DidSwapBuffers();
361 return;
364 DCHECK(context_provider_);
365 DCHECK(frame->gl_frame_data);
367 if (frame->gl_frame_data->sub_buffer_rect ==
368 gfx::Rect(frame->gl_frame_data->size)) {
369 // Note that currently this has the same effect as SwapBuffers; we should
370 // consider exposing a different entry point on WebGraphicsContext3D.
371 context_provider_->Context3d()->prepareTexture();
372 } else {
373 gfx::Rect sub_buffer_rect = frame->gl_frame_data->sub_buffer_rect;
374 context_provider_->Context3d()->postSubBufferCHROMIUM(
375 sub_buffer_rect.x(),
376 sub_buffer_rect.y(),
377 sub_buffer_rect.width(),
378 sub_buffer_rect.height());
381 if (!has_swap_buffers_complete_callback_)
382 PostSwapBuffersComplete();
384 DidSwapBuffers();
387 void OutputSurface::PostSwapBuffersComplete() {
388 base::MessageLoop::current()->PostTask(
389 FROM_HERE,
390 base::Bind(&OutputSurface::OnSwapBuffersComplete,
391 weak_ptr_factory_.GetWeakPtr(),
392 static_cast<CompositorFrameAck*>(NULL)));
395 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy,
396 bool discard_backbuffer) {
397 TRACE_EVENT2("cc", "OutputSurface::SetMemoryPolicy",
398 "bytes_limit_when_visible", policy.bytes_limit_when_visible,
399 "discard_backbuffer", discard_backbuffer);
400 // Just ignore the memory manager when it says to set the limit to zero
401 // bytes. This will happen when the memory manager thinks that the renderer
402 // is not visible (which the renderer knows better).
403 if (policy.bytes_limit_when_visible)
404 client_->SetMemoryPolicy(policy);
405 client_->SetDiscardBackBufferWhenNotVisible(discard_backbuffer);
408 } // namespace cc