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 |