OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/output/output_surface.h" | 5 #include "cc/output/output_surface.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/debug/trace_event.h" | |
13 #include "base/logging.h" | 12 #include "base/logging.h" |
14 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
15 #include "base/strings/string_split.h" | 14 #include "base/strings/string_split.h" |
16 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
17 #include "cc/output/compositor_frame.h" | 16 #include "cc/output/compositor_frame.h" |
18 #include "cc/output/output_surface_client.h" | 17 #include "cc/output/output_surface_client.h" |
19 #include "cc/scheduler/delay_based_time_source.h" | |
20 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" | 18 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" |
21 #include "third_party/khronos/GLES2/gl2.h" | 19 #include "third_party/khronos/GLES2/gl2.h" |
22 #include "third_party/khronos/GLES2/gl2ext.h" | 20 #include "third_party/khronos/GLES2/gl2ext.h" |
23 #include "ui/gfx/rect.h" | 21 #include "ui/gfx/rect.h" |
24 #include "ui/gfx/size.h" | 22 #include "ui/gfx/size.h" |
25 | 23 |
26 using std::set; | 24 using std::set; |
27 using std::string; | 25 using std::string; |
28 using std::vector; | 26 using std::vector; |
29 | 27 |
30 namespace cc { | 28 namespace cc { |
31 | 29 |
32 class OutputSurfaceCallbacks | 30 class OutputSurfaceCallbacks |
33 : public WebKit::WebGraphicsContext3D:: | 31 : public WebKit::WebGraphicsContext3D:: |
34 WebGraphicsSwapBuffersCompleteCallbackCHROMIUM, | 32 WebGraphicsSwapBuffersCompleteCallbackCHROMIUM, |
35 public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback { | 33 public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback { |
36 public: | 34 public: |
37 explicit OutputSurfaceCallbacks(OutputSurface* client) | 35 explicit OutputSurfaceCallbacks(OutputSurfaceClient* client) |
38 : client_(client) { | 36 : client_(client) { |
39 DCHECK(client_); | 37 DCHECK(client_); |
40 } | 38 } |
41 | 39 |
42 // WK:WGC3D::WGSwapBuffersCompleteCallbackCHROMIUM implementation. | 40 // WK:WGC3D::WGSwapBuffersCompleteCallbackCHROMIUM implementation. |
43 virtual void onSwapBuffersComplete() { client_->OnSwapBuffersComplete(NULL); } | 41 virtual void onSwapBuffersComplete() { client_->OnSwapBuffersComplete(NULL); } |
44 | 42 |
45 // WK:WGC3D::WGContextLostCallback implementation. | 43 // WK:WGC3D::WGContextLostCallback implementation. |
46 virtual void onContextLost() { client_->DidLoseOutputSurface(); } | 44 virtual void onContextLost() { client_->DidLoseOutputSurface(); } |
47 | 45 |
48 private: | 46 private: |
49 OutputSurface* client_; | 47 OutputSurfaceClient* client_; |
50 }; | 48 }; |
51 | 49 |
52 OutputSurface::OutputSurface( | 50 OutputSurface::OutputSurface( |
53 scoped_ptr<WebKit::WebGraphicsContext3D> context3d) | 51 scoped_ptr<WebKit::WebGraphicsContext3D> context3d) |
54 : context3d_(context3d.Pass()), | 52 : client_(NULL), |
| 53 context3d_(context3d.Pass()), |
55 has_gl_discard_backbuffer_(false), | 54 has_gl_discard_backbuffer_(false), |
56 has_swap_buffers_complete_callback_(false), | 55 has_swap_buffers_complete_callback_(false), |
57 device_scale_factor_(-1), | 56 device_scale_factor_(-1), |
58 weak_ptr_factory_(this), | 57 weak_ptr_factory_(this) { |
59 max_frames_pending_(0), | |
60 pending_swap_buffers_(0), | |
61 begin_frame_pending_(false), | |
62 client_(NULL) { | |
63 } | 58 } |
64 | 59 |
65 OutputSurface::OutputSurface( | 60 OutputSurface::OutputSurface( |
66 scoped_ptr<cc::SoftwareOutputDevice> software_device) | 61 scoped_ptr<cc::SoftwareOutputDevice> software_device) |
67 : software_device_(software_device.Pass()), | 62 : client_(NULL), |
| 63 software_device_(software_device.Pass()), |
68 has_gl_discard_backbuffer_(false), | 64 has_gl_discard_backbuffer_(false), |
69 has_swap_buffers_complete_callback_(false), | 65 has_swap_buffers_complete_callback_(false), |
70 device_scale_factor_(-1), | 66 device_scale_factor_(-1), |
71 weak_ptr_factory_(this), | 67 weak_ptr_factory_(this) { |
72 max_frames_pending_(0), | |
73 pending_swap_buffers_(0), | |
74 begin_frame_pending_(false), | |
75 client_(NULL) { | |
76 } | 68 } |
77 | 69 |
78 OutputSurface::OutputSurface( | 70 OutputSurface::OutputSurface( |
79 scoped_ptr<WebKit::WebGraphicsContext3D> context3d, | 71 scoped_ptr<WebKit::WebGraphicsContext3D> context3d, |
80 scoped_ptr<cc::SoftwareOutputDevice> software_device) | 72 scoped_ptr<cc::SoftwareOutputDevice> software_device) |
81 : context3d_(context3d.Pass()), | 73 : client_(NULL), |
| 74 context3d_(context3d.Pass()), |
82 software_device_(software_device.Pass()), | 75 software_device_(software_device.Pass()), |
83 has_gl_discard_backbuffer_(false), | 76 has_gl_discard_backbuffer_(false), |
84 has_swap_buffers_complete_callback_(false), | 77 has_swap_buffers_complete_callback_(false), |
85 device_scale_factor_(-1), | 78 device_scale_factor_(-1), |
86 weak_ptr_factory_(this), | 79 weak_ptr_factory_(this) { |
87 max_frames_pending_(0), | |
88 pending_swap_buffers_(0), | |
89 begin_frame_pending_(false), | |
90 client_(NULL) { | |
91 } | |
92 | |
93 void OutputSurface::InitializeBeginFrameEmulation( | |
94 Thread* thread, | |
95 bool throttle_frame_production, | |
96 base::TimeDelta interval) { | |
97 if (throttle_frame_production){ | |
98 frame_rate_controller_.reset( | |
99 new FrameRateController( | |
100 DelayBasedTimeSource::Create(interval, thread))); | |
101 } else { | |
102 frame_rate_controller_.reset(new FrameRateController(thread)); | |
103 } | |
104 | |
105 frame_rate_controller_->SetClient(this); | |
106 frame_rate_controller_->SetMaxSwapsPending(max_frames_pending_); | |
107 | |
108 // The new frame rate controller will consume the swap acks of the old | |
109 // frame rate controller, so we set that expectation up here. | |
110 for (int i = 0; i < pending_swap_buffers_; i++) | |
111 frame_rate_controller_->DidSwapBuffers(); | |
112 } | |
113 | |
114 void OutputSurface::SetMaxFramesPending(int max_frames_pending) { | |
115 if (frame_rate_controller_) | |
116 frame_rate_controller_->SetMaxSwapsPending(max_frames_pending); | |
117 max_frames_pending_ = max_frames_pending; | |
118 } | |
119 | |
120 void OutputSurface::OnVSyncParametersChanged(base::TimeTicks timebase, | |
121 base::TimeDelta interval) { | |
122 TRACE_EVENT2("cc", "OutputSurface::OnVSyncParametersChanged", | |
123 "timebase", (timebase - base::TimeTicks()).InSecondsF(), | |
124 "interval", interval.InSecondsF()); | |
125 if (frame_rate_controller_) | |
126 frame_rate_controller_->SetTimebaseAndInterval(timebase, interval); | |
127 } | |
128 | |
129 void OutputSurface::FrameRateControllerTick(bool throttled) { | |
130 DCHECK(frame_rate_controller_); | |
131 if (!throttled) | |
132 BeginFrame(frame_rate_controller_->LastTickTime()); | |
133 } | |
134 | |
135 // Forwarded to OutputSurfaceClient | |
136 void OutputSurface::SetNeedsRedrawRect(gfx::Rect damage_rect) { | |
137 TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect"); | |
138 client_->SetNeedsRedrawRect(damage_rect); | |
139 } | |
140 | |
141 void OutputSurface::SetNeedsBeginFrame(bool enable) { | |
142 TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable); | |
143 begin_frame_pending_ = false; | |
144 if (frame_rate_controller_) | |
145 frame_rate_controller_->SetActive(enable); | |
146 } | |
147 | |
148 void OutputSurface::BeginFrame(base::TimeTicks frame_time) { | |
149 if (begin_frame_pending_ || | |
150 (pending_swap_buffers_ >= max_frames_pending_ && max_frames_pending_ > 0)) | |
151 return; | |
152 TRACE_EVENT1("cc", "OutputSurface::BeginFrame", | |
153 "pending_swap_buffers_", pending_swap_buffers_); | |
154 begin_frame_pending_ = true; | |
155 client_->BeginFrame(frame_time); | |
156 } | |
157 | |
158 void OutputSurface::DidSwapBuffers() { | |
159 begin_frame_pending_ = false; | |
160 pending_swap_buffers_++; | |
161 TRACE_EVENT1("cc", "OutputSurface::DidSwapBuffers", | |
162 "pending_swap_buffers_", pending_swap_buffers_); | |
163 if (frame_rate_controller_) | |
164 frame_rate_controller_->DidSwapBuffers(); | |
165 } | |
166 | |
167 void OutputSurface::OnSwapBuffersComplete(const CompositorFrameAck* ack) { | |
168 pending_swap_buffers_--; | |
169 TRACE_EVENT1("cc", "OutputSurface::OnSwapBuffersComplete", | |
170 "pending_swap_buffers_", pending_swap_buffers_); | |
171 client_->OnSwapBuffersComplete(ack); | |
172 if (frame_rate_controller_) | |
173 frame_rate_controller_->DidSwapBuffersComplete(); | |
174 } | |
175 | |
176 void OutputSurface::DidLoseOutputSurface() { | |
177 TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface"); | |
178 begin_frame_pending_ = false; | |
179 pending_swap_buffers_ = 0; | |
180 client_->DidLoseOutputSurface(); | |
181 } | |
182 | |
183 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform, | |
184 gfx::Rect viewport) { | |
185 client_->SetExternalDrawConstraints(transform, viewport); | |
186 } | 80 } |
187 | 81 |
188 OutputSurface::~OutputSurface() { | 82 OutputSurface::~OutputSurface() { |
189 if (frame_rate_controller_) | |
190 frame_rate_controller_->SetActive(false); | |
191 } | 83 } |
192 | 84 |
193 bool OutputSurface::ForcedDrawToSoftwareDevice() const { | 85 bool OutputSurface::ForcedDrawToSoftwareDevice() const { |
194 return false; | 86 return false; |
195 } | 87 } |
196 | 88 |
197 bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) { | 89 bool OutputSurface::BindToClient( |
| 90 cc::OutputSurfaceClient* client) { |
198 DCHECK(client); | 91 DCHECK(client); |
199 client_ = client; | 92 client_ = client; |
200 bool success = true; | 93 bool success = true; |
201 | 94 |
202 if (context3d_) { | 95 if (context3d_) { |
203 success = context3d_->makeContextCurrent(); | 96 success = context3d_->makeContextCurrent(); |
204 if (success) | 97 if (success) |
205 SetContext3D(context3d_.Pass()); | 98 SetContext3D(context3d_.Pass()); |
206 } | 99 } |
207 | 100 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 vector<string> extensions_list; | 136 vector<string> extensions_list; |
244 base::SplitString(extensions_string, ' ', &extensions_list); | 137 base::SplitString(extensions_string, ' ', &extensions_list); |
245 set<string> extensions(extensions_list.begin(), extensions_list.end()); | 138 set<string> extensions(extensions_list.begin(), extensions_list.end()); |
246 has_gl_discard_backbuffer_ = | 139 has_gl_discard_backbuffer_ = |
247 extensions.count("GL_CHROMIUM_discard_backbuffer") > 0; | 140 extensions.count("GL_CHROMIUM_discard_backbuffer") > 0; |
248 has_swap_buffers_complete_callback_ = | 141 has_swap_buffers_complete_callback_ = |
249 extensions.count("GL_CHROMIUM_swapbuffers_complete_callback") > 0; | 142 extensions.count("GL_CHROMIUM_swapbuffers_complete_callback") > 0; |
250 | 143 |
251 | 144 |
252 context3d_ = context3d.Pass(); | 145 context3d_ = context3d.Pass(); |
253 callbacks_.reset(new OutputSurfaceCallbacks(this)); | 146 callbacks_.reset(new OutputSurfaceCallbacks(client_)); |
254 context3d_->setSwapBuffersCompleteCallbackCHROMIUM(callbacks_.get()); | 147 context3d_->setSwapBuffersCompleteCallbackCHROMIUM(callbacks_.get()); |
255 context3d_->setContextLostCallback(callbacks_.get()); | 148 context3d_->setContextLostCallback(callbacks_.get()); |
256 } | 149 } |
257 | 150 |
258 void OutputSurface::EnsureBackbuffer() { | 151 void OutputSurface::EnsureBackbuffer() { |
259 DCHECK(context3d_); | 152 DCHECK(context3d_); |
260 if (has_gl_discard_backbuffer_) | 153 if (has_gl_discard_backbuffer_) |
261 context3d_->ensureBackbufferCHROMIUM(); | 154 context3d_->ensureBackbufferCHROMIUM(); |
262 } | 155 } |
263 | 156 |
(...skipping 22 matching lines...) Expand all Loading... |
286 } | 179 } |
287 | 180 |
288 void OutputSurface::BindFramebuffer() { | 181 void OutputSurface::BindFramebuffer() { |
289 DCHECK(context3d_); | 182 DCHECK(context3d_); |
290 context3d_->bindFramebuffer(GL_FRAMEBUFFER, 0); | 183 context3d_->bindFramebuffer(GL_FRAMEBUFFER, 0); |
291 } | 184 } |
292 | 185 |
293 void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) { | 186 void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) { |
294 if (frame->software_frame_data) { | 187 if (frame->software_frame_data) { |
295 PostSwapBuffersComplete(); | 188 PostSwapBuffersComplete(); |
296 DidSwapBuffers(); | |
297 return; | 189 return; |
298 } | 190 } |
299 | 191 |
300 DCHECK(context3d_); | 192 DCHECK(context3d_); |
301 DCHECK(frame->gl_frame_data); | 193 DCHECK(frame->gl_frame_data); |
302 | 194 |
303 if (frame->gl_frame_data->sub_buffer_rect == | 195 if (frame->gl_frame_data->sub_buffer_rect == |
304 gfx::Rect(frame->gl_frame_data->size)) { | 196 gfx::Rect(frame->gl_frame_data->size)) { |
305 // Note that currently this has the same effect as SwapBuffers; we should | 197 // Note that currently this has the same effect as SwapBuffers; we should |
306 // consider exposing a different entry point on WebGraphicsContext3D. | 198 // consider exposing a different entry point on WebGraphicsContext3D. |
307 context3d()->prepareTexture(); | 199 context3d()->prepareTexture(); |
308 } else { | 200 } else { |
309 gfx::Rect sub_buffer_rect = frame->gl_frame_data->sub_buffer_rect; | 201 gfx::Rect sub_buffer_rect = frame->gl_frame_data->sub_buffer_rect; |
310 context3d()->postSubBufferCHROMIUM(sub_buffer_rect.x(), | 202 context3d()->postSubBufferCHROMIUM(sub_buffer_rect.x(), |
311 sub_buffer_rect.y(), | 203 sub_buffer_rect.y(), |
312 sub_buffer_rect.width(), | 204 sub_buffer_rect.width(), |
313 sub_buffer_rect.height()); | 205 sub_buffer_rect.height()); |
314 } | 206 } |
315 | 207 |
316 if (!has_swap_buffers_complete_callback_) | 208 if (!has_swap_buffers_complete_callback_) |
317 PostSwapBuffersComplete(); | 209 PostSwapBuffersComplete(); |
318 | |
319 DidSwapBuffers(); | |
320 } | 210 } |
321 | 211 |
322 void OutputSurface::PostSwapBuffersComplete() { | 212 void OutputSurface::PostSwapBuffersComplete() { |
323 base::MessageLoop::current()->PostTask( | 213 base::MessageLoop::current()->PostTask( |
324 FROM_HERE, | 214 FROM_HERE, |
325 base::Bind(&OutputSurface::OnSwapBuffersComplete, | 215 base::Bind(&OutputSurface::SwapBuffersComplete, |
326 weak_ptr_factory_.GetWeakPtr(), | 216 weak_ptr_factory_.GetWeakPtr())); |
327 static_cast<CompositorFrameAck*>(NULL))); | 217 } |
| 218 |
| 219 void OutputSurface::SwapBuffersComplete() { |
| 220 if (!client_) |
| 221 return; |
| 222 |
| 223 client_->OnSwapBuffersComplete(NULL); |
328 } | 224 } |
329 | 225 |
330 } // namespace cc | 226 } // namespace cc |
OLD | NEW |