| 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 |