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"
8 #include "base/message_loop/message_loop.h"
9 #include "base/trace_event/trace_event.h"
10 #include "cc/output/managed_memory_policy.h"
11 #include "cc/output/output_surface_client.h"
12 #include "gpu/GLES2/gl2extchromium.h"
13 #include "gpu/command_buffer/client/gles2_interface.h"
14 #include "ui/gfx/geometry/rect.h"
15 #include "ui/gfx/geometry/size.h"
20 OutputSurface::OutputSurface(
21 const scoped_refptr
<ContextProvider
>& context_provider
,
22 const scoped_refptr
<ContextProvider
>& worker_context_provider
,
23 scoped_ptr
<SoftwareOutputDevice
> software_device
)
25 context_provider_(context_provider
),
26 worker_context_provider_(worker_context_provider
),
27 software_device_(software_device
.Pass()),
28 device_scale_factor_(-1),
29 external_stencil_test_enabled_(false),
30 weak_ptr_factory_(this) {
33 OutputSurface::OutputSurface(
34 const scoped_refptr
<ContextProvider
>& context_provider
)
35 : OutputSurface(context_provider
, nullptr, nullptr) {
38 OutputSurface::OutputSurface(
39 const scoped_refptr
<ContextProvider
>& context_provider
,
40 const scoped_refptr
<ContextProvider
>& worker_context_provider
)
41 : OutputSurface(context_provider
, worker_context_provider
, nullptr) {
44 OutputSurface::OutputSurface(scoped_ptr
<SoftwareOutputDevice
> software_device
)
45 : OutputSurface(nullptr, nullptr, software_device
.Pass()) {
48 OutputSurface::OutputSurface(
49 const scoped_refptr
<ContextProvider
>& context_provider
,
50 scoped_ptr
<SoftwareOutputDevice
> software_device
)
51 : OutputSurface(context_provider
, nullptr, software_device
.Pass()) {
54 void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase
,
55 base::TimeDelta interval
) {
57 "OutputSurface::CommitVSyncParameters",
59 (timebase
- base::TimeTicks()).InSecondsF(),
61 interval
.InSecondsF());
62 client_
->CommitVSyncParameters(timebase
, interval
);
65 // Forwarded to OutputSurfaceClient
66 void OutputSurface::SetNeedsRedrawRect(const gfx::Rect
& damage_rect
) {
67 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect");
68 client_
->SetNeedsRedrawRect(damage_rect
);
71 void OutputSurface::ReclaimResources(const CompositorFrameAck
* ack
) {
72 client_
->ReclaimResources(ack
);
75 void OutputSurface::DidLoseOutputSurface() {
76 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
77 client_
->DidLoseOutputSurface();
80 void OutputSurface::SetExternalStencilTest(bool enabled
) {
81 external_stencil_test_enabled_
= enabled
;
84 void OutputSurface::SetExternalDrawConstraints(
85 const gfx::Transform
& transform
,
86 const gfx::Rect
& viewport
,
87 const gfx::Rect
& clip
,
88 const gfx::Rect
& viewport_rect_for_tile_priority
,
89 const gfx::Transform
& transform_for_tile_priority
,
90 bool resourceless_software_draw
) {
91 client_
->SetExternalDrawConstraints(transform
,
94 viewport_rect_for_tile_priority
,
95 transform_for_tile_priority
,
96 resourceless_software_draw
);
99 OutputSurface::~OutputSurface() {
103 bool OutputSurface::HasExternalStencilTest() const {
104 return external_stencil_test_enabled_
;
107 bool OutputSurface::BindToClient(OutputSurfaceClient
* client
) {
112 if (context_provider_
.get()) {
113 success
= context_provider_
->BindToCurrentThread();
118 if (success
&& worker_context_provider_
.get()) {
119 success
= worker_context_provider_
->BindToCurrentThread();
121 // The destructor resets the context lost callback, so base::Unretained
122 // is safe, as long as the worker threads stop using the context before
123 // the output surface is destroyed.
124 worker_context_provider_
->SetLostContextCallback(base::Bind(
125 &OutputSurface::DidLoseOutputSurface
, base::Unretained(this)));
135 bool OutputSurface::InitializeAndSetContext3d(
136 scoped_refptr
<ContextProvider
> context_provider
) {
137 DCHECK(!context_provider_
.get());
138 DCHECK(context_provider
.get());
141 bool success
= false;
142 if (context_provider
->BindToCurrentThread()) {
143 context_provider_
= context_provider
;
145 client_
->DeferredInitialize();
155 void OutputSurface::ReleaseGL() {
157 DCHECK(context_provider_
.get());
158 client_
->ReleaseGL();
159 DCHECK(!context_provider_
.get());
162 void OutputSurface::SetUpContext3d() {
163 DCHECK(context_provider_
.get());
166 context_provider_
->SetLostContextCallback(
167 base::Bind(&OutputSurface::DidLoseOutputSurface
,
168 base::Unretained(this)));
169 context_provider_
->SetMemoryPolicyChangedCallback(
170 base::Bind(&OutputSurface::SetMemoryPolicy
,
171 base::Unretained(this)));
174 void OutputSurface::ReleaseContextProvider() {
176 DCHECK(context_provider_
.get());
180 void OutputSurface::ResetContext3d() {
181 if (context_provider_
.get()) {
182 context_provider_
->SetLostContextCallback(
183 ContextProvider::LostContextCallback());
184 context_provider_
->SetMemoryPolicyChangedCallback(
185 ContextProvider::MemoryPolicyChangedCallback());
187 if (worker_context_provider_
.get()) {
188 worker_context_provider_
->SetLostContextCallback(
189 ContextProvider::LostContextCallback());
191 context_provider_
= NULL
;
192 worker_context_provider_
= NULL
;
195 void OutputSurface::EnsureBackbuffer() {
196 if (software_device_
)
197 software_device_
->EnsureBackbuffer();
200 void OutputSurface::DiscardBackbuffer() {
201 if (context_provider_
.get())
202 context_provider_
->ContextGL()->DiscardBackbufferCHROMIUM();
203 if (software_device_
)
204 software_device_
->DiscardBackbuffer();
207 void OutputSurface::Reshape(const gfx::Size
& size
, float scale_factor
) {
208 if (size
== surface_size_
&& scale_factor
== device_scale_factor_
)
211 surface_size_
= size
;
212 device_scale_factor_
= scale_factor
;
213 if (context_provider_
.get()) {
214 context_provider_
->ContextGL()->ResizeCHROMIUM(
215 size
.width(), size
.height(), scale_factor
);
217 if (software_device_
)
218 software_device_
->Resize(size
, scale_factor
);
221 gfx::Size
OutputSurface::SurfaceSize() const {
222 return surface_size_
;
225 void OutputSurface::BindFramebuffer() {
226 DCHECK(context_provider_
.get());
227 context_provider_
->ContextGL()->BindFramebuffer(GL_FRAMEBUFFER
, 0);
230 void OutputSurface::PostSwapBuffersComplete() {
231 base::MessageLoop::current()->PostTask(
233 base::Bind(&OutputSurface::OnSwapBuffersComplete
,
234 weak_ptr_factory_
.GetWeakPtr()));
237 // We don't post tasks bound to the client directly since they might run
238 // after the OutputSurface has been destroyed.
239 void OutputSurface::OnSwapBuffersComplete() {
240 client_
->DidSwapBuffersComplete();
243 void OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy
& policy
) {
244 TRACE_EVENT1("cc", "OutputSurface::SetMemoryPolicy",
245 "bytes_limit_when_visible", policy
.bytes_limit_when_visible
);
246 // Just ignore the memory manager when it says to set the limit to zero
247 // bytes. This will happen when the memory manager thinks that the renderer
248 // is not visible (which the renderer knows better).
249 if (policy
.bytes_limit_when_visible
)
250 client_
->SetMemoryPolicy(policy
);