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" | 12 #include "base/debug/trace_event.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
15 #include "base/strings/string_split.h" | 15 #include "base/strings/string_split.h" |
16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
17 #include "cc/output/compositor_frame.h" | 17 #include "cc/output/compositor_frame.h" |
18 #include "cc/output/managed_memory_policy.h" | 18 #include "cc/output/managed_memory_policy.h" |
19 #include "cc/output/output_surface_client.h" | 19 #include "cc/output/output_surface_client.h" |
20 #include "cc/scheduler/delay_based_time_source.h" | 20 #include "cc/scheduler/delay_based_time_source.h" |
21 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" | 21 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" |
22 #include "third_party/WebKit/public/platform/WebGraphicsMemoryAllocation.h" | |
23 #include "third_party/khronos/GLES2/gl2.h" | 22 #include "third_party/khronos/GLES2/gl2.h" |
24 #include "third_party/khronos/GLES2/gl2ext.h" | 23 #include "third_party/khronos/GLES2/gl2ext.h" |
25 #include "ui/gfx/rect.h" | 24 #include "ui/gfx/rect.h" |
26 #include "ui/gfx/size.h" | 25 #include "ui/gfx/size.h" |
27 | 26 |
28 using std::set; | 27 using std::set; |
29 using std::string; | 28 using std::string; |
30 using std::vector; | 29 using std::vector; |
31 | 30 |
32 namespace cc { | 31 namespace cc { |
33 namespace { | |
34 | |
35 ManagedMemoryPolicy::PriorityCutoff ConvertPriorityCutoff( | |
36 WebKit::WebGraphicsMemoryAllocation::PriorityCutoff priority_cutoff) { | |
37 // This is simple a 1:1 map, the names differ only because the WebKit names | |
38 // should be to match the cc names. | |
39 switch (priority_cutoff) { | |
40 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowNothing: | |
41 return ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING; | |
42 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleOnly: | |
43 return ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY; | |
44 case WebKit::WebGraphicsMemoryAllocation:: | |
45 PriorityCutoffAllowVisibleAndNearby: | |
46 return ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE; | |
47 case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything: | |
48 return ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING; | |
49 } | |
50 NOTREACHED(); | |
51 return ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING; | |
52 } | |
53 | |
54 } // anonymous namespace | |
55 | |
56 class OutputSurfaceCallbacks | |
57 : public WebKit::WebGraphicsContext3D:: | |
58 WebGraphicsSwapBuffersCompleteCallbackCHROMIUM, | |
59 public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback, | |
60 public WebKit::WebGraphicsContext3D:: | |
61 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM { | |
62 public: | |
63 explicit OutputSurfaceCallbacks(OutputSurface* client) | |
64 : client_(client) { | |
65 DCHECK(client_); | |
66 } | |
67 | |
68 // WK:WGC3D::WGSwapBuffersCompleteCallbackCHROMIUM implementation. | |
69 virtual void onSwapBuffersComplete() { client_->OnSwapBuffersComplete(NULL); } | |
70 | |
71 // WK:WGC3D::WGContextLostCallback implementation. | |
72 virtual void onContextLost() { client_->DidLoseOutputSurface(); } | |
73 | |
74 // WK:WGC3D::WGMemoryAllocationChangedCallbackCHROMIUM implementation. | |
75 virtual void onMemoryAllocationChanged( | |
76 WebKit::WebGraphicsMemoryAllocation allocation) { | |
77 ManagedMemoryPolicy policy( | |
78 allocation.bytesLimitWhenVisible, | |
79 ConvertPriorityCutoff(allocation.priorityCutoffWhenVisible), | |
80 allocation.bytesLimitWhenNotVisible, | |
81 ConvertPriorityCutoff(allocation.priorityCutoffWhenNotVisible), | |
82 ManagedMemoryPolicy::kDefaultNumResourcesLimit); | |
83 bool discard_backbuffer = !allocation.suggestHaveBackbuffer; | |
84 client_->SetMemoryPolicy(policy, discard_backbuffer); | |
85 } | |
86 | |
87 private: | |
88 OutputSurface* client_; | |
89 }; | |
90 | 32 |
91 OutputSurface::OutputSurface( | 33 OutputSurface::OutputSurface( |
92 scoped_ptr<WebKit::WebGraphicsContext3D> context3d) | 34 scoped_refptr<ContextProvider> context_provider) |
93 : context3d_(context3d.Pass()), | 35 : context_provider_(context_provider), |
94 has_gl_discard_backbuffer_(false), | 36 has_gl_discard_backbuffer_(false), |
95 has_swap_buffers_complete_callback_(false), | 37 has_swap_buffers_complete_callback_(false), |
96 device_scale_factor_(-1), | 38 device_scale_factor_(-1), |
97 weak_ptr_factory_(this), | 39 weak_ptr_factory_(this), |
98 max_frames_pending_(0), | 40 max_frames_pending_(0), |
99 pending_swap_buffers_(0), | 41 pending_swap_buffers_(0), |
100 needs_begin_frame_(false), | 42 needs_begin_frame_(false), |
101 begin_frame_pending_(false), | 43 begin_frame_pending_(false), |
102 client_(NULL), | 44 client_(NULL), |
103 check_for_retroactive_begin_frame_pending_(false) { | 45 check_for_retroactive_begin_frame_pending_(false) { |
104 } | 46 } |
105 | 47 |
106 OutputSurface::OutputSurface( | 48 OutputSurface::OutputSurface( |
107 scoped_ptr<cc::SoftwareOutputDevice> software_device) | 49 scoped_ptr<cc::SoftwareOutputDevice> software_device) |
108 : software_device_(software_device.Pass()), | 50 : software_device_(software_device.Pass()), |
109 has_gl_discard_backbuffer_(false), | 51 has_gl_discard_backbuffer_(false), |
110 has_swap_buffers_complete_callback_(false), | 52 has_swap_buffers_complete_callback_(false), |
111 device_scale_factor_(-1), | 53 device_scale_factor_(-1), |
112 weak_ptr_factory_(this), | 54 weak_ptr_factory_(this), |
113 max_frames_pending_(0), | 55 max_frames_pending_(0), |
114 pending_swap_buffers_(0), | 56 pending_swap_buffers_(0), |
115 needs_begin_frame_(false), | 57 needs_begin_frame_(false), |
116 begin_frame_pending_(false), | 58 begin_frame_pending_(false), |
117 client_(NULL), | 59 client_(NULL), |
118 check_for_retroactive_begin_frame_pending_(false) { | 60 check_for_retroactive_begin_frame_pending_(false) { |
119 } | 61 } |
120 | 62 |
121 OutputSurface::OutputSurface( | 63 OutputSurface::OutputSurface( |
122 scoped_ptr<WebKit::WebGraphicsContext3D> context3d, | 64 scoped_refptr<ContextProvider> context_provider, |
123 scoped_ptr<cc::SoftwareOutputDevice> software_device) | 65 scoped_ptr<cc::SoftwareOutputDevice> software_device) |
124 : context3d_(context3d.Pass()), | 66 : context_provider_(context_provider), |
125 software_device_(software_device.Pass()), | 67 software_device_(software_device.Pass()), |
126 has_gl_discard_backbuffer_(false), | 68 has_gl_discard_backbuffer_(false), |
127 has_swap_buffers_complete_callback_(false), | 69 has_swap_buffers_complete_callback_(false), |
128 device_scale_factor_(-1), | 70 device_scale_factor_(-1), |
129 weak_ptr_factory_(this), | 71 weak_ptr_factory_(this), |
130 max_frames_pending_(0), | 72 max_frames_pending_(0), |
131 pending_swap_buffers_(0), | 73 pending_swap_buffers_(0), |
132 needs_begin_frame_(false), | 74 needs_begin_frame_(false), |
133 begin_frame_pending_(false), | 75 begin_frame_pending_(false), |
134 client_(NULL), | 76 client_(NULL), |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 } | 224 } |
283 | 225 |
284 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform, | 226 void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform, |
285 gfx::Rect viewport) { | 227 gfx::Rect viewport) { |
286 client_->SetExternalDrawConstraints(transform, viewport); | 228 client_->SetExternalDrawConstraints(transform, viewport); |
287 } | 229 } |
288 | 230 |
289 OutputSurface::~OutputSurface() { | 231 OutputSurface::~OutputSurface() { |
290 if (frame_rate_controller_) | 232 if (frame_rate_controller_) |
291 frame_rate_controller_->SetActive(false); | 233 frame_rate_controller_->SetActive(false); |
292 | 234 ResetContext3d(); |
293 if (context3d_) { | |
294 context3d_->setSwapBuffersCompleteCallbackCHROMIUM(NULL); | |
295 context3d_->setContextLostCallback(NULL); | |
296 context3d_->setMemoryAllocationChangedCallbackCHROMIUM(NULL); | |
297 } | |
298 } | 235 } |
299 | 236 |
300 bool OutputSurface::ForcedDrawToSoftwareDevice() const { | 237 bool OutputSurface::ForcedDrawToSoftwareDevice() const { |
301 return false; | 238 return false; |
302 } | 239 } |
303 | 240 |
304 bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) { | 241 bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) { |
305 DCHECK(client); | 242 DCHECK(client); |
306 client_ = client; | 243 client_ = client; |
307 bool success = true; | 244 bool success = true; |
308 | 245 |
309 if (context3d_) { | 246 if (context_provider_) { |
310 success = context3d_->makeContextCurrent(); | 247 success = context_provider_->BindToCurrentThread(); |
311 if (success) | 248 if (success) |
312 SetContext3D(context3d_.Pass()); | 249 SetUpContext3d(); |
313 } | 250 } |
314 | 251 |
315 if (!success) | 252 if (!success) |
316 client_ = NULL; | 253 client_ = NULL; |
317 | 254 |
318 return success; | 255 return success; |
319 } | 256 } |
320 | 257 |
321 bool OutputSurface::InitializeAndSetContext3D( | 258 bool OutputSurface::InitializeAndSetContext3d( |
322 scoped_ptr<WebKit::WebGraphicsContext3D> context3d, | 259 scoped_refptr<ContextProvider> context_provider, |
323 scoped_refptr<ContextProvider> offscreen_context_provider) { | 260 scoped_refptr<ContextProvider> offscreen_context_provider) { |
324 DCHECK(!context3d_); | 261 DCHECK(!context_provider_); |
325 DCHECK(context3d); | 262 DCHECK(context_provider); |
326 DCHECK(client_); | 263 DCHECK(client_); |
327 | 264 |
328 bool success = false; | 265 bool success = false; |
329 if (context3d->makeContextCurrent()) { | 266 if (context_provider->BindToCurrentThread()) { |
330 SetContext3D(context3d.Pass()); | 267 context_provider_ = context_provider; |
| 268 SetUpContext3d(); |
331 if (client_->DeferredInitialize(offscreen_context_provider)) | 269 if (client_->DeferredInitialize(offscreen_context_provider)) |
332 success = true; | 270 success = true; |
333 } | 271 } |
334 | 272 |
335 if (!success) | 273 if (!success) |
336 ResetContext3D(); | 274 ResetContext3d(); |
337 | 275 |
338 return success; | 276 return success; |
339 } | 277 } |
340 | 278 |
341 void OutputSurface::ReleaseGL() { | 279 void OutputSurface::ReleaseGL() { |
342 DCHECK(client_); | 280 DCHECK(client_); |
343 DCHECK(context3d_); | 281 DCHECK(context_provider_); |
344 client_->ReleaseGL(); | 282 client_->ReleaseGL(); |
345 ResetContext3D(); | 283 ResetContext3d(); |
346 } | 284 } |
347 | 285 |
348 void OutputSurface::SetContext3D( | 286 void OutputSurface::SetUpContext3d() { |
349 scoped_ptr<WebKit::WebGraphicsContext3D> context3d) { | 287 DCHECK(context_provider_); |
350 DCHECK(!context3d_); | |
351 DCHECK(context3d); | |
352 DCHECK(client_); | 288 DCHECK(client_); |
353 | 289 |
354 string extensions_string = UTF16ToASCII(context3d->getString(GL_EXTENSIONS)); | 290 WebKit::WebGraphicsContext3D* context3d = context_provider_->Context3d(); |
| 291 |
| 292 string extensions_string = |
| 293 UTF16ToASCII(context3d->getString(GL_EXTENSIONS)); |
355 vector<string> extensions_list; | 294 vector<string> extensions_list; |
356 base::SplitString(extensions_string, ' ', &extensions_list); | 295 base::SplitString(extensions_string, ' ', &extensions_list); |
357 set<string> extensions(extensions_list.begin(), extensions_list.end()); | 296 set<string> extensions(extensions_list.begin(), extensions_list.end()); |
358 has_gl_discard_backbuffer_ = | 297 has_gl_discard_backbuffer_ = |
359 extensions.count("GL_CHROMIUM_discard_backbuffer") > 0; | 298 extensions.count("GL_CHROMIUM_discard_backbuffer") > 0; |
360 has_swap_buffers_complete_callback_ = | 299 has_swap_buffers_complete_callback_ = |
361 extensions.count("GL_CHROMIUM_swapbuffers_complete_callback") > 0; | 300 extensions.count("GL_CHROMIUM_swapbuffers_complete_callback") > 0; |
362 | 301 |
363 | 302 context_provider_->SetLostContextCallback( |
364 context3d_ = context3d.Pass(); | 303 base::Bind(&OutputSurface::DidLoseOutputSurface, |
365 callbacks_.reset(new OutputSurfaceCallbacks(this)); | 304 base::Unretained(this))); |
366 context3d_->setSwapBuffersCompleteCallbackCHROMIUM(callbacks_.get()); | 305 context_provider_->SetSwapBuffersCompleteCallback( |
367 context3d_->setContextLostCallback(callbacks_.get()); | 306 base::Bind(&OutputSurface::OnSwapBuffersComplete, |
368 context3d_->setMemoryAllocationChangedCallbackCHROMIUM(callbacks_.get()); | 307 base::Unretained(this), |
| 308 static_cast<CompositorFrameAck*>(NULL))); |
| 309 context_provider_->SetMemoryPolicyChangedCallback( |
| 310 base::Bind(&OutputSurface::SetMemoryPolicy, |
| 311 base::Unretained(this))); |
369 } | 312 } |
370 | 313 |
371 void OutputSurface::ResetContext3D() { | 314 void OutputSurface::ResetContext3d() { |
372 context3d_.reset(); | 315 if (context_provider_.get()) { |
373 callbacks_.reset(); | 316 context_provider_->SetLostContextCallback( |
| 317 ContextProvider::LostContextCallback()); |
| 318 context_provider_->SetSwapBuffersCompleteCallback( |
| 319 ContextProvider::SwapBuffersCompleteCallback()); |
| 320 context_provider_->SetMemoryPolicyChangedCallback( |
| 321 ContextProvider::MemoryPolicyChangedCallback()); |
| 322 } |
| 323 context_provider_ = NULL; |
374 } | 324 } |
375 | 325 |
376 void OutputSurface::EnsureBackbuffer() { | 326 void OutputSurface::EnsureBackbuffer() { |
377 DCHECK(context3d_); | 327 DCHECK(context_provider_); |
378 if (has_gl_discard_backbuffer_) | 328 if (has_gl_discard_backbuffer_) |
379 context3d_->ensureBackbufferCHROMIUM(); | 329 context_provider_->Context3d()->ensureBackbufferCHROMIUM(); |
380 } | 330 } |
381 | 331 |
382 void OutputSurface::DiscardBackbuffer() { | 332 void OutputSurface::DiscardBackbuffer() { |
383 DCHECK(context3d_); | 333 DCHECK(context_provider_); |
384 if (has_gl_discard_backbuffer_) | 334 if (has_gl_discard_backbuffer_) |
385 context3d_->discardBackbufferCHROMIUM(); | 335 context_provider_->Context3d()->discardBackbufferCHROMIUM(); |
386 } | 336 } |
387 | 337 |
388 void OutputSurface::Reshape(gfx::Size size, float scale_factor) { | 338 void OutputSurface::Reshape(gfx::Size size, float scale_factor) { |
389 if (size == surface_size_ && scale_factor == device_scale_factor_) | 339 if (size == surface_size_ && scale_factor == device_scale_factor_) |
390 return; | 340 return; |
391 | 341 |
392 surface_size_ = size; | 342 surface_size_ = size; |
393 device_scale_factor_ = scale_factor; | 343 device_scale_factor_ = scale_factor; |
394 if (context3d_) { | 344 if (context_provider_) { |
395 context3d_->reshapeWithScaleFactor( | 345 context_provider_->Context3d()->reshapeWithScaleFactor( |
396 size.width(), size.height(), scale_factor); | 346 size.width(), size.height(), scale_factor); |
397 } | 347 } |
398 if (software_device_) | 348 if (software_device_) |
399 software_device_->Resize(size); | 349 software_device_->Resize(size); |
400 } | 350 } |
401 | 351 |
402 gfx::Size OutputSurface::SurfaceSize() const { | 352 gfx::Size OutputSurface::SurfaceSize() const { |
403 return surface_size_; | 353 return surface_size_; |
404 } | 354 } |
405 | 355 |
406 void OutputSurface::BindFramebuffer() { | 356 void OutputSurface::BindFramebuffer() { |
407 DCHECK(context3d_); | 357 DCHECK(context_provider_); |
408 context3d_->bindFramebuffer(GL_FRAMEBUFFER, 0); | 358 context_provider_->Context3d()->bindFramebuffer(GL_FRAMEBUFFER, 0); |
409 } | 359 } |
410 | 360 |
411 void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) { | 361 void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) { |
412 if (frame->software_frame_data) { | 362 if (frame->software_frame_data) { |
413 PostSwapBuffersComplete(); | 363 PostSwapBuffersComplete(); |
414 DidSwapBuffers(); | 364 DidSwapBuffers(); |
415 return; | 365 return; |
416 } | 366 } |
417 | 367 |
418 DCHECK(context3d_); | 368 DCHECK(context_provider_); |
419 DCHECK(frame->gl_frame_data); | 369 DCHECK(frame->gl_frame_data); |
420 | 370 |
421 if (frame->gl_frame_data->sub_buffer_rect == | 371 if (frame->gl_frame_data->sub_buffer_rect == |
422 gfx::Rect(frame->gl_frame_data->size)) { | 372 gfx::Rect(frame->gl_frame_data->size)) { |
423 // Note that currently this has the same effect as SwapBuffers; we should | 373 // Note that currently this has the same effect as SwapBuffers; we should |
424 // consider exposing a different entry point on WebGraphicsContext3D. | 374 // consider exposing a different entry point on WebGraphicsContext3D. |
425 context3d()->prepareTexture(); | 375 context_provider_->Context3d()->prepareTexture(); |
426 } else { | 376 } else { |
427 gfx::Rect sub_buffer_rect = frame->gl_frame_data->sub_buffer_rect; | 377 gfx::Rect sub_buffer_rect = frame->gl_frame_data->sub_buffer_rect; |
428 context3d()->postSubBufferCHROMIUM(sub_buffer_rect.x(), | 378 context_provider_->Context3d()->postSubBufferCHROMIUM( |
429 sub_buffer_rect.y(), | 379 sub_buffer_rect.x(), |
430 sub_buffer_rect.width(), | 380 sub_buffer_rect.y(), |
431 sub_buffer_rect.height()); | 381 sub_buffer_rect.width(), |
| 382 sub_buffer_rect.height()); |
432 } | 383 } |
433 | 384 |
434 if (!has_swap_buffers_complete_callback_) | 385 if (!has_swap_buffers_complete_callback_) |
435 PostSwapBuffersComplete(); | 386 PostSwapBuffersComplete(); |
436 | 387 |
437 DidSwapBuffers(); | 388 DidSwapBuffers(); |
438 } | 389 } |
439 | 390 |
440 void OutputSurface::PostSwapBuffersComplete() { | 391 void OutputSurface::PostSwapBuffersComplete() { |
441 base::MessageLoop::current()->PostTask( | 392 base::MessageLoop::current()->PostTask( |
(...skipping 10 matching lines...) Expand all Loading... |
452 "discard_backbuffer", discard_backbuffer); | 403 "discard_backbuffer", discard_backbuffer); |
453 // Just ignore the memory manager when it says to set the limit to zero | 404 // Just ignore the memory manager when it says to set the limit to zero |
454 // bytes. This will happen when the memory manager thinks that the renderer | 405 // bytes. This will happen when the memory manager thinks that the renderer |
455 // is not visible (which the renderer knows better). | 406 // is not visible (which the renderer knows better). |
456 if (policy.bytes_limit_when_visible) | 407 if (policy.bytes_limit_when_visible) |
457 client_->SetMemoryPolicy(policy); | 408 client_->SetMemoryPolicy(policy); |
458 client_->SetDiscardBackBufferWhenNotVisible(discard_backbuffer); | 409 client_->SetDiscardBackBufferWhenNotVisible(discard_backbuffer); |
459 } | 410 } |
460 | 411 |
461 } // namespace cc | 412 } // namespace cc |
OLD | NEW |