OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" | |
6 | |
7 #include <OpenGL/gl.h> | |
8 #include <OpenGL/OpenGL.h> | |
9 #include <vector> | |
10 | |
11 #include "base/command_line.h" | |
12 #include "base/debug/trace_event.h" | |
13 #include "base/logging.h" | |
14 #include "content/browser/gpu/gpu_data_manager_impl.h" | |
15 #include "ui/base/ui_base_switches.h" | |
16 #include "ui/gl/gl_switches.h" | |
17 #include "ui/gl/gpu_switching_manager.h" | |
18 | |
19 namespace content { | |
20 | |
21 // static | |
22 scoped_refptr<CompositingIOSurfaceContext> | |
23 CompositingIOSurfaceContext::Get(int window_number) { | |
24 TRACE_EVENT0("browser", "CompositingIOSurfaceContext::Get"); | |
25 | |
26 // Return the context for this window_number, if it exists. | |
27 WindowMap::iterator found = window_map()->find(window_number); | |
28 if (found != window_map()->end()) { | |
29 DCHECK(!found->second->poisoned_); | |
30 return found->second; | |
31 } | |
32 | |
33 base::ScopedTypeRef<CGLContextObj> cgl_context_strong; | |
34 CGLContextObj cgl_context = NULL; | |
35 CGLError error = kCGLNoError; | |
36 | |
37 // Create the pixel format object for the context. | |
38 std::vector<CGLPixelFormatAttribute> attribs; | |
39 attribs.push_back(kCGLPFADepthSize); | |
40 attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); | |
41 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { | |
42 attribs.push_back(kCGLPFAAllowOfflineRenderers); | |
43 attribs.push_back(static_cast<CGLPixelFormatAttribute>(1)); | |
44 } | |
45 attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); | |
46 GLint number_virtual_screens = 0; | |
47 base::ScopedTypeRef<CGLPixelFormatObj> pixel_format; | |
48 error = CGLChoosePixelFormat(&attribs.front(), | |
49 pixel_format.InitializeInto(), | |
50 &number_virtual_screens); | |
51 if (error != kCGLNoError) { | |
52 LOG(ERROR) << "Failed to create pixel format object."; | |
53 return NULL; | |
54 } | |
55 | |
56 // Create all contexts in the same share group so that the textures don't | |
57 // need to be recreated when transitioning contexts. | |
58 CGLContextObj share_context = NULL; | |
59 if (!window_map()->empty()) | |
60 share_context = window_map()->begin()->second->cgl_context(); | |
61 error = CGLCreateContext( | |
62 pixel_format, share_context, cgl_context_strong.InitializeInto()); | |
63 if (error != kCGLNoError) { | |
64 LOG(ERROR) << "Failed to create context object."; | |
65 return NULL; | |
66 } | |
67 cgl_context = cgl_context_strong; | |
68 | |
69 // Note that VSync is ignored because CoreAnimation will automatically | |
70 // rate limit draws. | |
71 | |
72 return new CompositingIOSurfaceContext( | |
73 window_number, | |
74 cgl_context_strong, | |
75 cgl_context); | |
76 } | |
77 | |
78 void CompositingIOSurfaceContext::PoisonContextAndSharegroup() { | |
79 if (poisoned_) | |
80 return; | |
81 | |
82 for (WindowMap::iterator it = window_map()->begin(); | |
83 it != window_map()->end(); | |
84 ++it) { | |
85 it->second->poisoned_ = true; | |
86 } | |
87 window_map()->clear(); | |
88 } | |
89 | |
90 CompositingIOSurfaceContext::CompositingIOSurfaceContext( | |
91 int window_number, | |
92 base::ScopedTypeRef<CGLContextObj> cgl_context_strong, | |
93 CGLContextObj cgl_context) | |
94 : window_number_(window_number), | |
95 cgl_context_strong_(cgl_context_strong), | |
96 cgl_context_(cgl_context), | |
97 poisoned_(false) { | |
98 DCHECK(window_map()->find(window_number_) == window_map()->end()); | |
99 window_map()->insert(std::make_pair(window_number_, this)); | |
100 | |
101 GpuDataManager::GetInstance()->AddObserver(this); | |
102 } | |
103 | |
104 CompositingIOSurfaceContext::~CompositingIOSurfaceContext() { | |
105 GpuDataManager::GetInstance()->RemoveObserver(this); | |
106 | |
107 if (!poisoned_) { | |
108 DCHECK(window_map()->find(window_number_) != window_map()->end()); | |
109 DCHECK(window_map()->find(window_number_)->second == this); | |
110 window_map()->erase(window_number_); | |
111 } else { | |
112 WindowMap::const_iterator found = window_map()->find(window_number_); | |
113 if (found != window_map()->end()) | |
114 DCHECK(found->second != this); | |
115 } | |
116 } | |
117 | |
118 void CompositingIOSurfaceContext::OnGpuSwitching() { | |
119 // Recreate all browser-side GL contexts whenever the GPU switches. If this | |
120 // is not done, performance will suffer. | |
121 // http://crbug.com/361493 | |
122 PoisonContextAndSharegroup(); | |
123 } | |
124 | |
125 // static | |
126 CompositingIOSurfaceContext::WindowMap* | |
127 CompositingIOSurfaceContext::window_map() { | |
128 return window_map_.Pointer(); | |
129 } | |
130 | |
131 // static | |
132 base::LazyInstance<CompositingIOSurfaceContext::WindowMap> | |
133 CompositingIOSurfaceContext::window_map_; | |
134 | |
135 } // namespace content | |
OLD | NEW |