OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "webkit/gpu/webgraphicscontext3d_in_process_impl.h" | 5 #include "webkit/gpu/webgraphicscontext3d_in_process_impl.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <string> | 10 #include <string> |
11 | 11 |
| 12 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/string_split.h" | 14 #include "base/string_split.h" |
14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/synchronization/lock.h" |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
18 #include "ui/gfx/gl/gl_bindings.h" | 20 #include "ui/gfx/gl/gl_bindings.h" |
19 #include "ui/gfx/gl/gl_bindings_skia_in_process.h" | 21 #include "ui/gfx/gl/gl_bindings_skia_in_process.h" |
20 #include "ui/gfx/gl/gl_context.h" | 22 #include "ui/gfx/gl/gl_context.h" |
21 #include "ui/gfx/gl/gl_implementation.h" | 23 #include "ui/gfx/gl/gl_implementation.h" |
22 #include "ui/gfx/gl/gl_surface.h" | 24 #include "ui/gfx/gl/gl_surface.h" |
23 | 25 |
24 namespace webkit { | 26 namespace webkit { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 bound_texture_(0), | 67 bound_texture_(0), |
66 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 68 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
67 scanline_(0), | 69 scanline_(0), |
68 #endif | 70 #endif |
69 gl_context_(context), | 71 gl_context_(context), |
70 gl_surface_(surface), | 72 gl_surface_(surface), |
71 fragment_compiler_(0), | 73 fragment_compiler_(0), |
72 vertex_compiler_(0) { | 74 vertex_compiler_(0) { |
73 } | 75 } |
74 | 76 |
| 77 // All instances in a process that share resources are in the same share group. |
| 78 static base::LazyInstance< |
| 79 std::set<WebGraphicsContext3DInProcessImpl*> > |
| 80 g_all_shared_contexts = LAZY_INSTANCE_INITIALIZER; |
| 81 static base::LazyInstance<base::Lock>::Leaky |
| 82 g_all_shared_contexts_lock = LAZY_INSTANCE_INITIALIZER; |
| 83 |
75 WebGraphicsContext3DInProcessImpl::~WebGraphicsContext3DInProcessImpl() { | 84 WebGraphicsContext3DInProcessImpl::~WebGraphicsContext3DInProcessImpl() { |
| 85 base::AutoLock a(g_all_shared_contexts_lock.Get()); |
| 86 g_all_shared_contexts.Pointer()->erase(this); |
| 87 |
76 if (!initialized_) | 88 if (!initialized_) |
77 return; | 89 return; |
78 | 90 |
79 makeContextCurrent(); | 91 makeContextCurrent(); |
80 | 92 |
81 if (attributes_.antialias) { | 93 if (attributes_.antialias) { |
82 glDeleteRenderbuffersEXT(1, &multisample_color_buffer_); | 94 glDeleteRenderbuffersEXT(1, &multisample_color_buffer_); |
83 if (attributes_.depth || attributes_.stencil) | 95 if (attributes_.depth || attributes_.stencil) |
84 glDeleteRenderbuffersEXT(1, &multisample_depth_stencil_buffer_); | 96 glDeleteRenderbuffersEXT(1, &multisample_depth_stencil_buffer_); |
85 glDeleteFramebuffersEXT(1, &multisample_fbo_); | 97 glDeleteFramebuffersEXT(1, &multisample_fbo_); |
(...skipping 16 matching lines...) Expand all Loading... |
102 ii != shader_source_map_.end(); ++ii) { | 114 ii != shader_source_map_.end(); ++ii) { |
103 if (ii->second) | 115 if (ii->second) |
104 delete ii->second; | 116 delete ii->second; |
105 } | 117 } |
106 AngleDestroyCompilers(); | 118 AngleDestroyCompilers(); |
107 } | 119 } |
108 | 120 |
109 WebGraphicsContext3DInProcessImpl* | 121 WebGraphicsContext3DInProcessImpl* |
110 WebGraphicsContext3DInProcessImpl::CreateForWebView( | 122 WebGraphicsContext3DInProcessImpl::CreateForWebView( |
111 WebGraphicsContext3D::Attributes attributes, | 123 WebGraphicsContext3D::Attributes attributes, |
112 WebView* web_view, | |
113 bool render_directly_to_web_view) { | 124 bool render_directly_to_web_view) { |
114 if (!gfx::GLSurface::InitializeOneOff()) | 125 if (!gfx::GLSurface::InitializeOneOff()) |
115 return NULL; | 126 return NULL; |
116 | 127 |
117 bool is_gles2 = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; | |
118 gfx::GLShareGroup* share_group = 0; | 128 gfx::GLShareGroup* share_group = 0; |
119 if (!render_directly_to_web_view) { | 129 |
120 // Pick up the compositor's context to share resources with. | 130 if (attributes.shareResources) { |
121 WebGraphicsContext3D* view_context = web_view ? | 131 WebGraphicsContext3DInProcessImpl* context_impl = |
122 web_view->graphicsContext3D() : NULL; | 132 g_all_shared_contexts.Pointer()->empty() ? |
123 if (view_context) { | 133 NULL : *g_all_shared_contexts.Pointer()->begin(); |
124 WebGraphicsContext3DInProcessImpl* contextImpl = | 134 share_group = context_impl->gl_context_->share_group(); |
125 static_cast<WebGraphicsContext3DInProcessImpl*>(view_context); | |
126 share_group = contextImpl->gl_context_->share_group(); | |
127 } else { | |
128 // The compositor's context didn't get created | |
129 // successfully, so conceptually there is no way we can | |
130 // render successfully to the WebView. | |
131 render_directly_to_web_view = false; | |
132 } | |
133 } | 135 } |
134 | 136 |
135 // This implementation always renders offscreen regardless of whether | 137 // This implementation always renders offscreen regardless of whether |
136 // render_directly_to_web_view is true. Both DumpRenderTree and test_shell | 138 // render_directly_to_web_view is true. Both DumpRenderTree and test_shell |
137 // paint first to an intermediate offscreen buffer and from there to the | 139 // paint first to an intermediate offscreen buffer and from there to the |
138 // window, and WebViewImpl::paint already correctly handles the case where the | 140 // window, and WebViewImpl::paint already correctly handles the case where the |
139 // compositor is active but the output needs to go to a WebCanvas. | 141 // compositor is active but the output needs to go to a WebCanvas. |
140 scoped_refptr<gfx::GLSurface> gl_surface = | 142 scoped_refptr<gfx::GLSurface> gl_surface = |
141 gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)); | 143 gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)); |
142 | 144 |
143 if (!gl_surface.get()) { | 145 if (!gl_surface.get()) |
144 if (!is_gles2) | 146 return NULL; |
145 return NULL; | |
146 | |
147 // Embedded systems have smaller limit on number of GL contexts. Sometimes | |
148 // failure of GL context creation is because of existing GL contexts | |
149 // referenced by JavaScript garbages. Collect garbage and try again. | |
150 // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving | |
151 // a page unload event, iterate down any live WebGraphicsContext3D instances | |
152 // and force them to drop their contexts, sending a context lost event if | |
153 // necessary. | |
154 if (web_view) web_view->mainFrame()->collectGarbage(); | |
155 | |
156 gl_surface = gfx::GLSurface::CreateOffscreenGLSurface(false, | |
157 gfx::Size(1, 1)); | |
158 if (!gl_surface.get()) | |
159 return NULL; | |
160 } | |
161 | 147 |
162 // TODO(kbr): This implementation doesn't yet support lost contexts | 148 // TODO(kbr): This implementation doesn't yet support lost contexts |
163 // and therefore can't yet properly support GPU switching. | 149 // and therefore can't yet properly support GPU switching. |
164 gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; | 150 gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; |
165 | 151 |
166 scoped_refptr<gfx::GLContext> gl_context = gfx::GLContext::CreateGLContext( | 152 scoped_refptr<gfx::GLContext> gl_context = gfx::GLContext::CreateGLContext( |
167 share_group, | 153 share_group, |
168 gl_surface.get(), | 154 gl_surface.get(), |
169 gpu_preference); | 155 gpu_preference); |
170 | 156 |
171 if (!gl_context.get()) { | 157 if (!gl_context.get()) |
172 if (!is_gles2) | 158 return NULL; |
173 return NULL; | |
174 | 159 |
175 // Embedded systems have smaller limit on number of GL contexts. Sometimes | |
176 // failure of GL context creation is because of existing GL contexts | |
177 // referenced by JavaScript garbages. Collect garbage and try again. | |
178 // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving | |
179 // a page unload event, iterate down any live WebGraphicsContext3D instances | |
180 // and force them to drop their contexts, sending a context lost event if | |
181 // necessary. | |
182 if (web_view) | |
183 web_view->mainFrame()->collectGarbage(); | |
184 | |
185 gl_context = gfx::GLContext::CreateGLContext(share_group, | |
186 gl_surface.get(), | |
187 gpu_preference); | |
188 if (!gl_context.get()) | |
189 return NULL; | |
190 } | |
191 scoped_ptr<WebGraphicsContext3DInProcessImpl> context( | 160 scoped_ptr<WebGraphicsContext3DInProcessImpl> context( |
192 new WebGraphicsContext3DInProcessImpl( | 161 new WebGraphicsContext3DInProcessImpl( |
193 gl_surface.get(), gl_context.get(), render_directly_to_web_view)); | 162 gl_surface.get(), gl_context.get(), render_directly_to_web_view)); |
194 if (!context->Initialize(attributes)) | 163 if (!context->Initialize(attributes)) |
195 return NULL; | 164 return NULL; |
196 return context.release(); | 165 return context.release(); |
197 } | 166 } |
198 | 167 |
199 WebGraphicsContext3DInProcessImpl* | 168 WebGraphicsContext3DInProcessImpl* |
200 WebGraphicsContext3DInProcessImpl::CreateForWindow( | 169 WebGraphicsContext3DInProcessImpl::CreateForWindow( |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 glEnable(GL_POINT_SPRITE); | 234 glEnable(GL_POINT_SPRITE); |
266 } | 235 } |
267 | 236 |
268 if (!AngleCreateCompilers()) { | 237 if (!AngleCreateCompilers()) { |
269 AngleDestroyCompilers(); | 238 AngleDestroyCompilers(); |
270 return false; | 239 return false; |
271 } | 240 } |
272 | 241 |
273 initialized_ = true; | 242 initialized_ = true; |
274 gl_context_->ReleaseCurrent(gl_surface_.get()); | 243 gl_context_->ReleaseCurrent(gl_surface_.get()); |
| 244 |
| 245 if (attributes_.shareResources) |
| 246 g_all_shared_contexts.Pointer()->insert(this); |
| 247 |
275 return true; | 248 return true; |
276 } | 249 } |
277 | 250 |
278 void WebGraphicsContext3DInProcessImpl::ValidateAttributes() { | 251 void WebGraphicsContext3DInProcessImpl::ValidateAttributes() { |
279 const char* extensions = | 252 const char* extensions = |
280 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); | 253 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); |
281 | 254 |
282 if (attributes_.stencil) { | 255 if (attributes_.stencil) { |
283 if (strstr(extensions, "GL_OES_packed_depth_stencil") || | 256 if (strstr(extensions, "GL_OES_packed_depth_stencil") || |
284 strstr(extensions, "GL_EXT_packed_depth_stencil")) { | 257 strstr(extensions, "GL_EXT_packed_depth_stencil")) { |
(...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1740 if (length > 1) { | 1713 if (length > 1) { |
1741 entry->translated_source.reset(new char[length]); | 1714 entry->translated_source.reset(new char[length]); |
1742 ShGetObjectCode(compiler, entry->translated_source.get()); | 1715 ShGetObjectCode(compiler, entry->translated_source.get()); |
1743 } | 1716 } |
1744 entry->is_valid = true; | 1717 entry->is_valid = true; |
1745 return true; | 1718 return true; |
1746 } | 1719 } |
1747 | 1720 |
1748 } // namespace gpu | 1721 } // namespace gpu |
1749 } // namespace webkit | 1722 } // namespace webkit |
OLD | NEW |