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"
12 #include "base/bind.h"
13 #include "base/debug/trace_event.h"
14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/histogram.h"
17 #include "base/strings/string_split.h"
18 #include "base/strings/string_util.h"
19 #include "cc/output/compositor_frame.h"
20 #include "cc/output/compositor_frame_ack.h"
21 #include "cc/output/managed_memory_policy.h"
22 #include "cc/output/output_surface_client.h"
23 #include "cc/scheduler/delay_based_time_source.h"
24 #include "gpu/command_buffer/client/context_support.h"
25 #include "gpu/command_buffer/client/gles2_interface.h"
26 #include "ui/gfx/frame_time.h"
27 #include "ui/gfx/geometry/rect.h"
28 #include "ui/gfx/geometry/size.h"
36 OutputSurface::OutputSurface(
37 const scoped_refptr
<ContextProvider
>& context_provider
)
39 context_provider_(context_provider
),
40 device_scale_factor_(-1),
41 external_stencil_test_enabled_(false),
42 weak_ptr_factory_(this) {
45 OutputSurface::OutputSurface(scoped_ptr
<SoftwareOutputDevice
> software_device
)
47 software_device_(software_device
.Pass()),
48 device_scale_factor_(-1),
49 external_stencil_test_enabled_(false),
50 weak_ptr_factory_(this) {
53 OutputSurface::OutputSurface(
54 const scoped_refptr
<ContextProvider
>& context_provider
,
55 scoped_ptr
<SoftwareOutputDevice
> software_device
)
57 context_provider_(context_provider
),
58 software_device_(software_device
.Pass()),
59 device_scale_factor_(-1),
60 external_stencil_test_enabled_(false),
61 weak_ptr_factory_(this) {
64 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase
,
65 base::TimeDelta interval
) {
67 "OutputSurface::CommitVSyncParameters",
69 (timebase
- base::TimeTicks()).InSecondsF(),
71 interval
.InSecondsF());
72 client_
->CommitVSyncParameters(timebase
, interval
);
75 // Forwarded to OutputSurfaceClient
76 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect
& damage_rect
) {
77 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect");
78 client_
->SetNeedsRedrawRect(damage_rect
);
81 void OutputSurface::ReclaimResources(const CompositorFrameAck
* ack
) {
82 client_
->ReclaimResources(ack
);
85 void OutputSurface::DidLoseOutputSurface() {
86 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
87 client_
->DidLoseOutputSurface();
90 void OutputSurface::SetExternalStencilTest(bool enabled
) {
91 external_stencil_test_enabled_
= enabled
;
94 void OutputSurface::SetExternalDrawConstraints(
95 const gfx::Transform
& transform
,
96 const gfx::Rect
& viewport
,
97 const gfx::Rect
& clip
,
98 const gfx::Rect
& viewport_rect_for_tile_priority
,
99 const gfx::Transform
& transform_for_tile_priority
,
100 bool resourceless_software_draw
) {
101 client_
->SetExternalDrawConstraints(transform
,
104 viewport_rect_for_tile_priority
,
105 transform_for_tile_priority
,
106 resourceless_software_draw
);
109 OutputSurface::~OutputSurface() {
113 bool OutputSurface::HasExternalStencilTest() const {
114 return external_stencil_test_enabled_
;
117 bool OutputSurface::BindToClient(OutputSurfaceClient
* client
) {
122 if (context_provider_
.get()) {
123 success
= context_provider_
->BindToCurrentThread();
134 bool OutputSurface::InitializeAndSetContext3d(
135 scoped_refptr
<ContextProvider
> context_provider
) {
136 DCHECK(!context_provider_
.get());
137 DCHECK(context_provider
.get());
140 bool success
= false;
141 if (context_provider
->BindToCurrentThread()) {
142 context_provider_
= context_provider
;
144 client_
->DeferredInitialize();
154 void OutputSurface::ReleaseGL() {
156 DCHECK(context_provider_
.get());
157 client_
->ReleaseGL();
158 DCHECK(!context_provider_
.get());
161 void OutputSurface::SetUpContext3d() {
162 DCHECK(context_provider_
.get());
165 context_provider_
->SetLostContextCallback(
166 base::Bind(&OutputSurface::DidLoseOutputSurface
,
167 base::Unretained(this)));
168 context_provider_
->ContextSupport()->SetSwapBuffersCompleteCallback(
169 base::Bind(&OutputSurface::OnSwapBuffersComplete
,
170 base::Unretained(this)));
171 context_provider_
->SetMemoryPolicyChangedCallback(
172 base::Bind(&OutputSurface::SetMemoryPolicy
,
173 base::Unretained(this)));
176 void OutputSurface::ReleaseContextProvider() {
178 DCHECK(context_provider_
.get());
182 void OutputSurface::ResetContext3d() {
183 if (context_provider_
.get()) {
184 context_provider_
->SetLostContextCallback(
185 ContextProvider::LostContextCallback());
186 context_provider_
->SetMemoryPolicyChangedCallback(
187 ContextProvider::MemoryPolicyChangedCallback());
188 if (gpu::ContextSupport
* support
= context_provider_
->ContextSupport())
189 support
->SetSwapBuffersCompleteCallback(base::Closure());
191 context_provider_
= NULL
;
194 void OutputSurface::EnsureBackbuffer() {
195 if (software_device_
)
196 software_device_
->EnsureBackbuffer();
199 void OutputSurface::DiscardBackbuffer() {
200 if (context_provider_
.get())
201 context_provider_
->ContextGL()->DiscardBackbufferCHROMIUM();
202 if (software_device_
)
203 software_device_
->DiscardBackbuffer();
206 void OutputSurface::Reshape(const gfx::Size
& size
, float scale_factor
) {
207 if (size
== surface_size_
&& scale_factor
== device_scale_factor_
)
210 surface_size_
= size
;
211 device_scale_factor_
= scale_factor
;
212 if (context_provider_
.get()) {
213 context_provider_
->ContextGL()->ResizeCHROMIUM(
214 size
.width(), size
.height(), scale_factor
);
216 if (software_device_
)
217 software_device_
->Resize(size
, scale_factor
);
220 gfx::Size
OutputSurface::SurfaceSize() const {
221 return surface_size_
;
224 void OutputSurface::BindFramebuffer() {
225 DCHECK(context_provider_
.get());
226 context_provider_
->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER
, 0);
229 void OutputSurface::SwapBuffers(CompositorFrame
* frame
) {
230 if (frame
->software_frame_data
) {
231 PostSwapBuffersComplete();
232 client_
->DidSwapBuffers();
236 DCHECK(context_provider_
.get());
237 DCHECK(frame
->gl_frame_data
);
239 if (frame
->gl_frame_data
->sub_buffer_rect
==
240 gfx::Rect(frame
->gl_frame_data
->size
)) {
241 context_provider_
->ContextSupport()->Swap();
243 context_provider_
->ContextSupport()->PartialSwapBuffers(
244 frame
->gl_frame_data
->sub_buffer_rect
);
247 client_
->DidSwapBuffers();
250 void OutputSurface::PostSwapBuffersComplete() {
251 base::MessageLoop::current()->PostTask(
253 base::Bind(&OutputSurface::OnSwapBuffersComplete
,
254 weak_ptr_factory_
.GetWeakPtr()));
257 // We don't post tasks bound to the client directly since they might run
258 // after the OutputSurface has been destroyed.
259 void OutputSurface::OnSwapBuffersComplete() {
260 client_
->DidSwapBuffersComplete();
263 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy
& policy
) {
264 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy",
265 "bytes_limit_when_visible", policy
.bytes_limit_when_visible
);
266 // Just ignore the memory manager when it says to set the limit to zero
267 // bytes. This will happen when the memory manager thinks that the renderer
268 // is not visible (which the renderer knows better).
269 if (policy
.bytes_limit_when_visible
)
270 client_
->SetMemoryPolicy(policy
);