| 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> |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 } | 37 } |
| 38 | 38 |
| 39 WGC3Denum type; | 39 WGC3Denum type; |
| 40 scoped_array<char> source; | 40 scoped_array<char> source; |
| 41 scoped_array<char> log; | 41 scoped_array<char> log; |
| 42 scoped_array<char> translated_source; | 42 scoped_array<char> translated_source; |
| 43 bool is_valid; | 43 bool is_valid; |
| 44 }; | 44 }; |
| 45 | 45 |
| 46 WebGraphicsContext3DInProcessImpl::WebGraphicsContext3DInProcessImpl( | 46 WebGraphicsContext3DInProcessImpl::WebGraphicsContext3DInProcessImpl( |
| 47 gfx::AcceleratedWidget window, | 47 gfx::GLSurface* surface, |
| 48 gfx::GLShareGroup* share_group) | 48 gfx::GLContext* context, |
| 49 bool render_directly_to_web_view) |
| 49 : initialized_(false), | 50 : initialized_(false), |
| 50 render_directly_to_web_view_(false), | 51 render_directly_to_web_view_(render_directly_to_web_view), |
| 51 is_gles2_(false), | 52 is_gles2_(false), |
| 52 have_ext_framebuffer_object_(false), | 53 have_ext_framebuffer_object_(false), |
| 53 have_ext_framebuffer_multisample_(false), | 54 have_ext_framebuffer_multisample_(false), |
| 54 have_angle_framebuffer_multisample_(false), | 55 have_angle_framebuffer_multisample_(false), |
| 55 texture_(0), | 56 texture_(0), |
| 56 fbo_(0), | 57 fbo_(0), |
| 57 depth_stencil_buffer_(0), | 58 depth_stencil_buffer_(0), |
| 58 cached_width_(0), | 59 cached_width_(0), |
| 59 cached_height_(0), | 60 cached_height_(0), |
| 60 multisample_fbo_(0), | 61 multisample_fbo_(0), |
| 61 multisample_depth_stencil_buffer_(0), | 62 multisample_depth_stencil_buffer_(0), |
| 62 multisample_color_buffer_(0), | 63 multisample_color_buffer_(0), |
| 63 bound_fbo_(0), | 64 bound_fbo_(0), |
| 64 bound_texture_(0), | 65 bound_texture_(0), |
| 65 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 66 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| 66 scanline_(0), | 67 scanline_(0), |
| 67 #endif | 68 #endif |
| 69 gl_context_(context), |
| 70 gl_surface_(surface), |
| 68 fragment_compiler_(0), | 71 fragment_compiler_(0), |
| 69 vertex_compiler_(0), | 72 vertex_compiler_(0) { |
| 70 window_(window), | |
| 71 share_group_(share_group) { | |
| 72 } | 73 } |
| 73 | 74 |
| 74 WebGraphicsContext3DInProcessImpl::~WebGraphicsContext3DInProcessImpl() { | 75 WebGraphicsContext3DInProcessImpl::~WebGraphicsContext3DInProcessImpl() { |
| 75 if (!initialized_) | 76 if (!initialized_) |
| 76 return; | 77 return; |
| 77 | 78 |
| 78 makeContextCurrent(); | 79 makeContextCurrent(); |
| 79 | 80 |
| 80 if (attributes_.antialias) { | 81 if (attributes_.antialias) { |
| 81 glDeleteRenderbuffersEXT(1, &multisample_color_buffer_); | 82 glDeleteRenderbuffersEXT(1, &multisample_color_buffer_); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 98 gl_surface_->Destroy(); | 99 gl_surface_->Destroy(); |
| 99 | 100 |
| 100 for (ShaderSourceMap::iterator ii = shader_source_map_.begin(); | 101 for (ShaderSourceMap::iterator ii = shader_source_map_.begin(); |
| 101 ii != shader_source_map_.end(); ++ii) { | 102 ii != shader_source_map_.end(); ++ii) { |
| 102 if (ii->second) | 103 if (ii->second) |
| 103 delete ii->second; | 104 delete ii->second; |
| 104 } | 105 } |
| 105 AngleDestroyCompilers(); | 106 AngleDestroyCompilers(); |
| 106 } | 107 } |
| 107 | 108 |
| 108 bool WebGraphicsContext3DInProcessImpl::initialize( | 109 WebGraphicsContext3DInProcessImpl* |
| 110 WebGraphicsContext3DInProcessImpl::CreateForWebView( |
| 109 WebGraphicsContext3D::Attributes attributes, | 111 WebGraphicsContext3D::Attributes attributes, |
| 110 WebView* webView, | 112 WebView* web_view, |
| 111 bool render_directly_to_web_view) { | 113 bool render_directly_to_web_view) { |
| 112 if (!gfx::GLSurface::InitializeOneOff()) | 114 if (!gfx::GLSurface::InitializeOneOff()) |
| 113 return false; | 115 return NULL; |
| 114 | 116 |
| 115 render_directly_to_web_view_ = render_directly_to_web_view; | 117 bool is_gles2 = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; |
| 116 gfx::GLShareGroup* share_group = 0; | 118 gfx::GLShareGroup* share_group = 0; |
| 117 | 119 if (!render_directly_to_web_view) { |
| 118 is_gles2_ = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; | 120 // Pick up the compositor's context to share resources with. |
| 119 | 121 WebGraphicsContext3D* view_context = web_view ? |
| 120 if (window_ != gfx::kNullPluginWindow) { | 122 web_view->graphicsContext3D() : NULL; |
| 121 share_group = share_group_; | 123 if (view_context) { |
| 122 gl_surface_ = gfx::GLSurface::CreateViewGLSurface(false, window_); | 124 WebGraphicsContext3DInProcessImpl* contextImpl = |
| 123 } else { | 125 static_cast<WebGraphicsContext3DInProcessImpl*>(view_context); |
| 124 if (!render_directly_to_web_view) { | 126 share_group = contextImpl->gl_context_->share_group(); |
| 125 // Pick up the compositor's context to share resources with. | 127 } else { |
| 126 WebGraphicsContext3D* view_context = webView ? | 128 // The compositor's context didn't get created |
| 127 webView->graphicsContext3D() : NULL; | 129 // successfully, so conceptually there is no way we can |
| 128 if (view_context) { | 130 // render successfully to the WebView. |
| 129 WebGraphicsContext3DInProcessImpl* contextImpl = | 131 render_directly_to_web_view = false; |
| 130 static_cast<WebGraphicsContext3DInProcessImpl*>(view_context); | |
| 131 share_group = contextImpl->gl_context_->share_group(); | |
| 132 } else { | |
| 133 // The compositor's context didn't get created | |
| 134 // successfully, so conceptually there is no way we can | |
| 135 // render successfully to the WebView. | |
| 136 render_directly_to_web_view_ = false; | |
| 137 } | |
| 138 } | 132 } |
| 139 // This implementation always renders offscreen regardless of | |
| 140 // whether render_directly_to_web_view is true. Both DumpRenderTree | |
| 141 // and test_shell paint first to an intermediate offscreen buffer | |
| 142 // and from there to the window, and WebViewImpl::paint already | |
| 143 // correctly handles the case where the compositor is active but | |
| 144 // the output needs to go to a WebCanvas. | |
| 145 gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, | |
| 146 gfx::Size(1, 1)); | |
| 147 } | 133 } |
| 148 | 134 |
| 149 if (!gl_surface_.get()) { | 135 // This implementation always renders offscreen regardless of whether |
| 150 if (!is_gles2_) | 136 // render_directly_to_web_view is true. Both DumpRenderTree and test_shell |
| 151 return false; | 137 // paint first to an intermediate offscreen buffer and from there to the |
| 138 // window, and WebViewImpl::paint already correctly handles the case where the |
| 139 // compositor is active but the output needs to go to a WebCanvas. |
| 140 scoped_refptr<gfx::GLSurface> gl_surface = |
| 141 gfx::GLSurface::CreateOffscreenGLSurface(false, gfx::Size(1, 1)); |
| 142 |
| 143 if (!gl_surface.get()) { |
| 144 if (!is_gles2) |
| 145 return NULL; |
| 152 | 146 |
| 153 // Embedded systems have smaller limit on number of GL contexts. Sometimes | 147 // Embedded systems have smaller limit on number of GL contexts. Sometimes |
| 154 // failure of GL context creation is because of existing GL contexts | 148 // failure of GL context creation is because of existing GL contexts |
| 155 // referenced by JavaScript garbages. Collect garbage and try again. | 149 // referenced by JavaScript garbages. Collect garbage and try again. |
| 156 // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving | 150 // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving |
| 157 // a page unload event, iterate down any live WebGraphicsContext3D instances | 151 // a page unload event, iterate down any live WebGraphicsContext3D instances |
| 158 // and force them to drop their contexts, sending a context lost event if | 152 // and force them to drop their contexts, sending a context lost event if |
| 159 // necessary. | 153 // necessary. |
| 160 if (webView) webView->mainFrame()->collectGarbage(); | 154 if (web_view) web_view->mainFrame()->collectGarbage(); |
| 161 | 155 |
| 162 gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(false, | 156 gl_surface = gfx::GLSurface::CreateOffscreenGLSurface(false, |
| 163 gfx::Size(1, 1)); | 157 gfx::Size(1, 1)); |
| 164 if (!gl_surface_.get()) | 158 if (!gl_surface.get()) |
| 165 return false; | 159 return NULL; |
| 166 } | 160 } |
| 167 | 161 |
| 168 // TODO(kbr): This implementation doesn't yet support lost contexts | 162 // TODO(kbr): This implementation doesn't yet support lost contexts |
| 169 // and therefore can't yet properly support GPU switching. | 163 // and therefore can't yet properly support GPU switching. |
| 170 gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; | 164 gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; |
| 171 | 165 |
| 172 gl_context_ = gfx::GLContext::CreateGLContext(share_group, | 166 scoped_refptr<gfx::GLContext> gl_context = gfx::GLContext::CreateGLContext( |
| 173 gl_surface_.get(), | 167 share_group, |
| 174 gpu_preference); | 168 gl_surface.get(), |
| 175 if (!gl_context_.get()) { | 169 gpu_preference); |
| 176 if (!is_gles2_) | 170 |
| 177 return false; | 171 if (!gl_context.get()) { |
| 172 if (!is_gles2) |
| 173 return NULL; |
| 178 | 174 |
| 179 // Embedded systems have smaller limit on number of GL contexts. Sometimes | 175 // Embedded systems have smaller limit on number of GL contexts. Sometimes |
| 180 // failure of GL context creation is because of existing GL contexts | 176 // failure of GL context creation is because of existing GL contexts |
| 181 // referenced by JavaScript garbages. Collect garbage and try again. | 177 // referenced by JavaScript garbages. Collect garbage and try again. |
| 182 // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving | 178 // TODO: Besides this solution, kbr@chromium.org suggested: upon receiving |
| 183 // a page unload event, iterate down any live WebGraphicsContext3D instances | 179 // a page unload event, iterate down any live WebGraphicsContext3D instances |
| 184 // and force them to drop their contexts, sending a context lost event if | 180 // and force them to drop their contexts, sending a context lost event if |
| 185 // necessary. | 181 // necessary. |
| 186 if (webView) webView->mainFrame()->collectGarbage(); | 182 if (web_view) |
| 183 web_view->mainFrame()->collectGarbage(); |
| 187 | 184 |
| 188 gl_context_ = gfx::GLContext::CreateGLContext(share_group, | 185 gl_context = gfx::GLContext::CreateGLContext(share_group, |
| 189 gl_surface_.get(), | 186 gl_surface.get(), |
| 190 gpu_preference); | 187 gpu_preference); |
| 191 if (!gl_context_.get()) | 188 if (!gl_context.get()) |
| 192 return false; | 189 return NULL; |
| 193 } | 190 } |
| 191 scoped_ptr<WebGraphicsContext3DInProcessImpl> context( |
| 192 new WebGraphicsContext3DInProcessImpl( |
| 193 gl_surface.get(), gl_context.get(), render_directly_to_web_view)); |
| 194 if (!context->Initialize(attributes)) |
| 195 return NULL; |
| 196 return context.release(); |
| 197 } |
| 198 |
| 199 WebGraphicsContext3DInProcessImpl* |
| 200 WebGraphicsContext3DInProcessImpl::CreateForWindow( |
| 201 WebGraphicsContext3D::Attributes attributes, |
| 202 gfx::AcceleratedWidget window, |
| 203 gfx::GLShareGroup* share_group) { |
| 204 if (!gfx::GLSurface::InitializeOneOff()) |
| 205 return NULL; |
| 206 |
| 207 scoped_refptr<gfx::GLSurface> gl_surface = |
| 208 gfx::GLSurface::CreateViewGLSurface(false, window); |
| 209 if (!gl_surface.get()) |
| 210 return NULL; |
| 211 |
| 212 gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; |
| 213 |
| 214 scoped_refptr<gfx::GLContext> gl_context = gfx::GLContext::CreateGLContext( |
| 215 share_group, |
| 216 gl_surface.get(), |
| 217 gpu_preference); |
| 218 if (!gl_context.get()) |
| 219 return NULL; |
| 220 scoped_ptr<WebGraphicsContext3DInProcessImpl> context( |
| 221 new WebGraphicsContext3DInProcessImpl( |
| 222 gl_surface.get(), gl_context.get(), true)); |
| 223 if (!context->Initialize(attributes)) |
| 224 return NULL; |
| 225 return context.release(); |
| 226 } |
| 227 |
| 228 bool WebGraphicsContext3DInProcessImpl::Initialize( |
| 229 WebGraphicsContext3D::Attributes attributes) { |
| 230 is_gles2_ = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; |
| 231 |
| 194 | 232 |
| 195 attributes_ = attributes; | 233 attributes_ = attributes; |
| 196 | 234 |
| 197 // FIXME: for the moment we disable multisampling for the compositor. | 235 // FIXME: for the moment we disable multisampling for the compositor. |
| 198 // It actually works in this implementation, but there are a few | 236 // It actually works in this implementation, but there are a few |
| 199 // considerations. First, we likely want to reduce the fuzziness in | 237 // considerations. First, we likely want to reduce the fuzziness in |
| 200 // these tests as much as possible because we want to run pixel tests. | 238 // these tests as much as possible because we want to run pixel tests. |
| 201 // Second, Mesa's multisampling doesn't seem to antialias straight | 239 // Second, Mesa's multisampling doesn't seem to antialias straight |
| 202 // edges in some CSS 3D samples. Third, we don't have multisampling | 240 // edges in some CSS 3D samples. Third, we don't have multisampling |
| 203 // support for the compositor in the normal case at the time of this | 241 // support for the compositor in the normal case at the time of this |
| 204 // writing. | 242 // writing. |
| 205 if (render_directly_to_web_view) | 243 if (render_directly_to_web_view_) |
| 206 attributes_.antialias = false; | 244 attributes_.antialias = false; |
| 207 | 245 |
| 208 if (!gl_context_->MakeCurrent(gl_surface_.get())) { | 246 if (!gl_context_->MakeCurrent(gl_surface_.get())) { |
| 209 gl_context_ = NULL; | 247 gl_context_ = NULL; |
| 210 return false; | 248 return false; |
| 211 } | 249 } |
| 212 | 250 |
| 213 const char* extensions = | 251 const char* extensions = |
| 214 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); | 252 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); |
| 215 DCHECK(extensions); | 253 DCHECK(extensions); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 bool WebGraphicsContext3DInProcessImpl::setParentContext( | 355 bool WebGraphicsContext3DInProcessImpl::setParentContext( |
| 318 WebGraphicsContext3D* parent_context) { | 356 WebGraphicsContext3D* parent_context) { |
| 319 return false; | 357 return false; |
| 320 } | 358 } |
| 321 | 359 |
| 322 WebGLId WebGraphicsContext3DInProcessImpl::getPlatformTextureId() { | 360 WebGLId WebGraphicsContext3DInProcessImpl::getPlatformTextureId() { |
| 323 return texture_; | 361 return texture_; |
| 324 } | 362 } |
| 325 | 363 |
| 326 void WebGraphicsContext3DInProcessImpl::prepareTexture() { | 364 void WebGraphicsContext3DInProcessImpl::prepareTexture() { |
| 327 if (window_ != gfx::kNullPluginWindow) { | 365 if (!gl_surface_->IsOffscreen()) { |
| 328 gl_surface_->SwapBuffers(); | 366 gl_surface_->SwapBuffers(); |
| 329 } else if (!render_directly_to_web_view_) { | 367 } else if (!render_directly_to_web_view_) { |
| 330 // We need to prepare our rendering results for the compositor. | 368 // We need to prepare our rendering results for the compositor. |
| 331 makeContextCurrent(); | 369 makeContextCurrent(); |
| 332 ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_); | 370 ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_); |
| 333 } | 371 } |
| 334 } | 372 } |
| 335 | 373 |
| 336 void WebGraphicsContext3DInProcessImpl::postSubBufferCHROMIUM( | 374 void WebGraphicsContext3DInProcessImpl::postSubBufferCHROMIUM( |
| 337 int x, int y, int width, int height) { | 375 int x, int y, int width, int height) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 351 } | 389 } |
| 352 | 390 |
| 353 } // anonymous namespace | 391 } // anonymous namespace |
| 354 | 392 |
| 355 void WebGraphicsContext3DInProcessImpl::reshape(int width, int height) { | 393 void WebGraphicsContext3DInProcessImpl::reshape(int width, int height) { |
| 356 cached_width_ = width; | 394 cached_width_ = width; |
| 357 cached_height_ = height; | 395 cached_height_ = height; |
| 358 makeContextCurrent(); | 396 makeContextCurrent(); |
| 359 | 397 |
| 360 bool must_restore_fbo = false; | 398 bool must_restore_fbo = false; |
| 361 if (window_ == gfx::kNullPluginWindow) | 399 if (gl_surface_->IsOffscreen()) |
| 362 must_restore_fbo = AllocateOffscreenFrameBuffer(width, height); | 400 must_restore_fbo = AllocateOffscreenFrameBuffer(width, height); |
| 363 | 401 |
| 364 gl_surface_->Resize(gfx::Size(width, height)); | 402 gl_surface_->Resize(gfx::Size(width, height)); |
| 365 ClearRenderTarget(); | 403 ClearRenderTarget(); |
| 366 | 404 |
| 367 if (must_restore_fbo) | 405 if (must_restore_fbo) |
| 368 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | 406 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); |
| 369 | 407 |
| 370 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 408 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| 371 if (scanline_) { | 409 if (scanline_) { |
| (...skipping 1330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1702 if (length > 1) { | 1740 if (length > 1) { |
| 1703 entry->translated_source.reset(new char[length]); | 1741 entry->translated_source.reset(new char[length]); |
| 1704 ShGetObjectCode(compiler, entry->translated_source.get()); | 1742 ShGetObjectCode(compiler, entry->translated_source.get()); |
| 1705 } | 1743 } |
| 1706 entry->is_valid = true; | 1744 entry->is_valid = true; |
| 1707 return true; | 1745 return true; |
| 1708 } | 1746 } |
| 1709 | 1747 |
| 1710 } // namespace gpu | 1748 } // namespace gpu |
| 1711 } // namespace webkit | 1749 } // namespace webkit |
| OLD | NEW |