OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "app/gfx/gl/gl_bindings.h" | 12 #include "app/gfx/gl/gl_bindings.h" |
13 #include "app/gfx/gl/gl_context.h" | 13 #include "app/gfx/gl/gl_context.h" |
14 #include "app/gfx/gl/gl_implementation.h" | 14 #include "app/gfx/gl/gl_implementation.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
18 | 18 |
| 19 using WebKit::WebGLId; |
| 20 using WebKit::WebGraphicsContext3D; |
| 21 using WebKit::WebString; |
| 22 using WebKit::WebView; |
| 23 |
19 namespace webkit { | 24 namespace webkit { |
20 namespace gpu { | 25 namespace gpu { |
21 | 26 |
22 enum { | 27 enum { |
23 MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB, | 28 MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB, |
24 MAX_VARYING_VECTORS = 0x8DFC, | 29 MAX_VARYING_VECTORS = 0x8DFC, |
25 MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD | 30 MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD |
26 }; | 31 }; |
27 | 32 |
28 #if defined(USE_WGC3D_TYPES) | |
29 | |
30 WebGraphicsContext3DInProcessImpl::WebGraphicsContext3DInProcessImpl() | |
31 : initialized_(false), | |
32 render_directly_to_web_view_(false), | |
33 is_gles2_(false), | |
34 have_ext_framebuffer_object_(false), | |
35 have_ext_framebuffer_multisample_(false), | |
36 have_angle_framebuffer_multisample_(false), | |
37 texture_(0), | |
38 fbo_(0), | |
39 depth_stencil_buffer_(0), | |
40 cached_width_(0), | |
41 cached_height_(0), | |
42 multisample_fbo_(0), | |
43 multisample_depth_stencil_buffer_(0), | |
44 multisample_color_buffer_(0), | |
45 bound_fbo_(0), | |
46 bound_texture_(0), | |
47 copy_texture_to_parent_texture_fbo_(0), | |
48 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | |
49 scanline_(0), | |
50 #endif | |
51 fragment_compiler_(0), | |
52 vertex_compiler_(0) { | |
53 } | |
54 | |
55 WebGraphicsContext3DInProcessImpl::~WebGraphicsContext3DInProcessImpl() { | |
56 if (!initialized_) | |
57 return; | |
58 | |
59 makeContextCurrent(); | |
60 | |
61 if (attributes_.antialias) { | |
62 glDeleteRenderbuffersEXT(1, &multisample_color_buffer_); | |
63 if (attributes_.depth || attributes_.stencil) | |
64 glDeleteRenderbuffersEXT(1, &multisample_depth_stencil_buffer_); | |
65 glDeleteFramebuffersEXT(1, &multisample_fbo_); | |
66 } else { | |
67 if (attributes_.depth || attributes_.stencil) | |
68 glDeleteRenderbuffersEXT(1, &depth_stencil_buffer_); | |
69 } | |
70 glDeleteTextures(1, &texture_); | |
71 glDeleteFramebuffersEXT(1, ©_texture_to_parent_texture_fbo_); | |
72 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | |
73 if (scanline_) | |
74 delete[] scanline_; | |
75 #endif | |
76 glDeleteFramebuffersEXT(1, &fbo_); | |
77 | |
78 gl_context_->Destroy(); | |
79 | |
80 for (ShaderSourceMap::iterator ii = shader_source_map_.begin(); | |
81 ii != shader_source_map_.end(); ++ii) { | |
82 if (ii->second) | |
83 delete ii->second; | |
84 } | |
85 AngleDestroyCompilers(); | |
86 } | |
87 | |
88 bool WebGraphicsContext3DInProcessImpl::initialize( | |
89 WebGraphicsContext3D::Attributes attributes, | |
90 WebView* webView, | |
91 bool render_directly_to_web_view) { | |
92 if (!gfx::GLContext::InitializeOneOff()) | |
93 return false; | |
94 | |
95 render_directly_to_web_view_ = render_directly_to_web_view; | |
96 gfx::GLContext* share_context = 0; | |
97 | |
98 if (!render_directly_to_web_view) { | |
99 // Pick up the compositor's context to share resources with. | |
100 WebGraphicsContext3D* view_context = webView->graphicsContext3D(); | |
101 if (view_context) { | |
102 WebGraphicsContext3DInProcessImpl* contextImpl = | |
103 static_cast<WebGraphicsContext3DInProcessImpl*>(view_context); | |
104 share_context = contextImpl->gl_context_.get(); | |
105 } else { | |
106 // The compositor's context didn't get created | |
107 // successfully, so conceptually there is no way we can | |
108 // render successfully to the WebView. | |
109 render_directly_to_web_view_ = false; | |
110 } | |
111 } | |
112 | |
113 // This implementation always renders offscreen regardless of | |
114 // whether render_directly_to_web_view is true. Both DumpRenderTree | |
115 // and test_shell paint first to an intermediate offscreen buffer | |
116 // and from there to the window, and WebViewImpl::paint already | |
117 // correctly handles the case where the compositor is active but | |
118 // the output needs to go to a WebCanvas. | |
119 gl_context_.reset(gfx::GLContext::CreateOffscreenGLContext(share_context)); | |
120 if (!gl_context_.get()) | |
121 return false; | |
122 | |
123 attributes_ = attributes; | |
124 | |
125 // FIXME: for the moment we disable multisampling for the compositor. | |
126 // It actually works in this implementation, but there are a few | |
127 // considerations. First, we likely want to reduce the fuzziness in | |
128 // these tests as much as possible because we want to run pixel tests. | |
129 // Second, Mesa's multisampling doesn't seem to antialias straight | |
130 // edges in some CSS 3D samples. Third, we don't have multisampling | |
131 // support for the compositor in the normal case at the time of this | |
132 // writing. | |
133 if (render_directly_to_web_view) | |
134 attributes_.antialias = false; | |
135 | |
136 is_gles2_ = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; | |
137 const char* extensions = | |
138 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); | |
139 have_ext_framebuffer_object_ = | |
140 strstr(extensions, "GL_EXT_framebuffer_object") != NULL; | |
141 have_ext_framebuffer_multisample_ = | |
142 strstr(extensions, "GL_EXT_framebuffer_multisample") != NULL; | |
143 have_angle_framebuffer_multisample_ = | |
144 strstr(extensions, "GL_ANGLE_framebuffer_multisample") != NULL; | |
145 | |
146 ValidateAttributes(); | |
147 | |
148 if (!is_gles2_) { | |
149 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); | |
150 glEnable(GL_POINT_SPRITE); | |
151 } | |
152 | |
153 if (!AngleCreateCompilers()) { | |
154 AngleDestroyCompilers(); | |
155 return false; | |
156 } | |
157 | |
158 glGenFramebuffersEXT(1, ©_texture_to_parent_texture_fbo_); | |
159 | |
160 initialized_ = true; | |
161 return true; | |
162 } | |
163 | |
164 void WebGraphicsContext3DInProcessImpl::ValidateAttributes() { | |
165 const char* extensions = | |
166 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); | |
167 | |
168 if (attributes_.stencil) { | |
169 if (strstr(extensions, "GL_OES_packed_depth_stencil") || | |
170 strstr(extensions, "GL_EXT_packed_depth_stencil")) { | |
171 if (!attributes_.depth) { | |
172 attributes_.depth = true; | |
173 } | |
174 } else { | |
175 attributes_.stencil = false; | |
176 } | |
177 } | |
178 if (attributes_.antialias) { | |
179 bool isValidVendor = true; | |
180 #if defined(OS_MACOSX) | |
181 // Currently in Mac we only turn on antialias if vendor is NVIDIA. | |
182 const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | |
183 if (!strstr(vendor, "NVIDIA")) | |
184 isValidVendor = false; | |
185 #endif | |
186 if (!(isValidVendor && | |
187 (have_ext_framebuffer_multisample_ || | |
188 (have_angle_framebuffer_multisample_ && | |
189 strstr(extensions, "GL_OES_rgb8_rgba8"))))) | |
190 attributes_.antialias = false; | |
191 | |
192 // Don't antialias when using Mesa to ensure more reliable testing and | |
193 // because it doesn't appear to multisample straight lines correctly. | |
194 const char* renderer = | |
195 reinterpret_cast<const char*>(glGetString(GL_RENDERER)); | |
196 if (!strncmp(renderer, "Mesa", 4)) { | |
197 attributes_.antialias = false; | |
198 } | |
199 } | |
200 // FIXME: instead of enforcing premultipliedAlpha = true, implement the | |
201 // correct behavior when premultipliedAlpha = false is requested. | |
202 attributes_.premultipliedAlpha = true; | |
203 } | |
204 | |
205 void WebGraphicsContext3DInProcessImpl::ResolveMultisampledFramebuffer( | |
206 WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { | |
207 if (attributes_.antialias) { | |
208 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, multisample_fbo_); | |
209 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_); | |
210 if (have_ext_framebuffer_multisample_) { | |
211 glBlitFramebufferEXT(x, y, | |
212 x + width, y + height, | |
213 x, y, | |
214 x + width, y + height, | |
215 GL_COLOR_BUFFER_BIT, GL_NEAREST); | |
216 } else { | |
217 DCHECK(have_angle_framebuffer_multisample_); | |
218 glBlitFramebufferANGLE(x, y, | |
219 x + width, y + height, | |
220 x, y, | |
221 x + width, y + height, | |
222 GL_COLOR_BUFFER_BIT, GL_NEAREST); | |
223 } | |
224 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
225 } | |
226 } | |
227 | |
228 bool WebGraphicsContext3DInProcessImpl::makeContextCurrent() { | |
229 return gl_context_->MakeCurrent(); | |
230 } | |
231 | |
232 int WebGraphicsContext3DInProcessImpl::width() { | |
233 return cached_width_; | |
234 } | |
235 | |
236 int WebGraphicsContext3DInProcessImpl::height() { | |
237 return cached_height_; | |
238 } | |
239 | |
240 bool WebGraphicsContext3DInProcessImpl::isGLES2Compliant() { | |
241 return is_gles2_; | |
242 } | |
243 | |
244 WebGLId WebGraphicsContext3DInProcessImpl::getPlatformTextureId() { | |
245 return texture_; | |
246 } | |
247 | |
248 void WebGraphicsContext3DInProcessImpl::prepareTexture() { | |
249 if (!render_directly_to_web_view_) { | |
250 // We need to prepare our rendering results for the compositor. | |
251 makeContextCurrent(); | |
252 ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_); | |
253 } | |
254 } | |
255 | |
256 namespace { | |
257 | |
258 int CreateTextureObject(GLenum target) { | |
259 GLuint texture = 0; | |
260 glGenTextures(1, &texture); | |
261 glBindTexture(target, texture); | |
262 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
263 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
264 return texture; | |
265 } | |
266 | |
267 } // anonymous namespace | |
268 | |
269 void WebGraphicsContext3DInProcessImpl::reshape(int width, int height) { | |
270 cached_width_ = width; | |
271 cached_height_ = height; | |
272 makeContextCurrent(); | |
273 | |
274 GLenum target = GL_TEXTURE_2D; | |
275 | |
276 if (!texture_) { | |
277 // Generate the texture object | |
278 texture_ = CreateTextureObject(target); | |
279 // Generate the framebuffer object | |
280 glGenFramebuffersEXT(1, &fbo_); | |
281 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
282 bound_fbo_ = fbo_; | |
283 if (attributes_.depth || attributes_.stencil) | |
284 glGenRenderbuffersEXT(1, &depth_stencil_buffer_); | |
285 // Generate the multisample framebuffer object | |
286 if (attributes_.antialias) { | |
287 glGenFramebuffersEXT(1, &multisample_fbo_); | |
288 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); | |
289 bound_fbo_ = multisample_fbo_; | |
290 glGenRenderbuffersEXT(1, &multisample_color_buffer_); | |
291 if (attributes_.depth || attributes_.stencil) | |
292 glGenRenderbuffersEXT(1, &multisample_depth_stencil_buffer_); | |
293 } | |
294 } | |
295 | |
296 GLint internal_multisampled_color_format = 0; | |
297 GLint internal_color_format = 0; | |
298 GLint color_format = 0; | |
299 GLint internal_depth_stencil_format = 0; | |
300 if (attributes_.alpha) { | |
301 // GL_RGBA8_OES == GL_RGBA8 | |
302 internal_multisampled_color_format = GL_RGBA8; | |
303 internal_color_format = is_gles2_ ? GL_RGBA : GL_RGBA8; | |
304 color_format = GL_RGBA; | |
305 } else { | |
306 // GL_RGB8_OES == GL_RGB8 | |
307 internal_multisampled_color_format = GL_RGB8; | |
308 internal_color_format = is_gles2_ ? GL_RGB : GL_RGB8; | |
309 color_format = GL_RGB; | |
310 } | |
311 if (attributes_.stencil || attributes_.depth) { | |
312 // We don't allow the logic where stencil is required and depth is not. | |
313 // See GraphicsContext3DInternal constructor. | |
314 if (attributes_.stencil && attributes_.depth) { | |
315 internal_depth_stencil_format = GL_DEPTH24_STENCIL8_EXT; | |
316 } else { | |
317 if (is_gles2_) | |
318 internal_depth_stencil_format = GL_DEPTH_COMPONENT16; | |
319 else | |
320 internal_depth_stencil_format = GL_DEPTH_COMPONENT; | |
321 } | |
322 } | |
323 | |
324 bool must_restore_fbo = false; | |
325 | |
326 // Resize multisampling FBO | |
327 if (attributes_.antialias) { | |
328 GLint max_sample_count; | |
329 glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_sample_count); | |
330 GLint sample_count = std::min(8, max_sample_count); | |
331 if (bound_fbo_ != multisample_fbo_) { | |
332 must_restore_fbo = true; | |
333 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); | |
334 } | |
335 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, multisample_color_buffer_); | |
336 if (have_ext_framebuffer_multisample_) { | |
337 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, | |
338 sample_count, | |
339 internal_multisampled_color_format, | |
340 width, | |
341 height); | |
342 } else { | |
343 DCHECK(have_angle_framebuffer_multisample_); | |
344 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER_EXT, | |
345 sample_count, | |
346 internal_multisampled_color_format, | |
347 width, | |
348 height); | |
349 } | |
350 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
351 GL_COLOR_ATTACHMENT0_EXT, | |
352 GL_RENDERBUFFER_EXT, | |
353 multisample_color_buffer_); | |
354 if (attributes_.stencil || attributes_.depth) { | |
355 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, | |
356 multisample_depth_stencil_buffer_); | |
357 if (have_ext_framebuffer_multisample_) { | |
358 glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, | |
359 sample_count, | |
360 internal_depth_stencil_format, | |
361 width, | |
362 height); | |
363 } else { | |
364 DCHECK(have_angle_framebuffer_multisample_); | |
365 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER_EXT, | |
366 sample_count, | |
367 internal_depth_stencil_format, | |
368 width, | |
369 height); | |
370 } | |
371 if (attributes_.stencil) | |
372 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
373 GL_STENCIL_ATTACHMENT_EXT, | |
374 GL_RENDERBUFFER_EXT, | |
375 multisample_depth_stencil_buffer_); | |
376 if (attributes_.depth) | |
377 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
378 GL_DEPTH_ATTACHMENT_EXT, | |
379 GL_RENDERBUFFER_EXT, | |
380 multisample_depth_stencil_buffer_); | |
381 } | |
382 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); | |
383 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | |
384 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { | |
385 LOG(ERROR) << "Multisampling framebuffer was incomplete"; | |
386 | |
387 // FIXME: cleanup. | |
388 NOTIMPLEMENTED(); | |
389 } | |
390 } | |
391 | |
392 // Resize regular FBO | |
393 if (bound_fbo_ != fbo_) { | |
394 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
395 must_restore_fbo = true; | |
396 } | |
397 glBindTexture(target, texture_); | |
398 glTexImage2D(target, 0, internal_color_format, | |
399 width, height, | |
400 0, color_format, GL_UNSIGNED_BYTE, 0); | |
401 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, | |
402 GL_COLOR_ATTACHMENT0_EXT, | |
403 target, | |
404 texture_, | |
405 0); | |
406 glBindTexture(target, 0); | |
407 if (!attributes_.antialias && (attributes_.stencil || attributes_.depth)) { | |
408 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer_); | |
409 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, | |
410 internal_depth_stencil_format, | |
411 width, height); | |
412 if (attributes_.stencil) | |
413 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
414 GL_STENCIL_ATTACHMENT_EXT, | |
415 GL_RENDERBUFFER_EXT, | |
416 depth_stencil_buffer_); | |
417 if (attributes_.depth) | |
418 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
419 GL_DEPTH_ATTACHMENT_EXT, | |
420 GL_RENDERBUFFER_EXT, | |
421 depth_stencil_buffer_); | |
422 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); | |
423 } | |
424 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | |
425 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { | |
426 LOG(ERROR) << "Framebuffer was incomplete"; | |
427 | |
428 // FIXME: cleanup. | |
429 NOTIMPLEMENTED(); | |
430 } | |
431 | |
432 if (attributes_.antialias) { | |
433 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample_fbo_); | |
434 if (bound_fbo_ == multisample_fbo_) | |
435 must_restore_fbo = false; | |
436 } | |
437 | |
438 // Initialize renderbuffers to 0. | |
439 GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0; | |
440 GLint clearStencil = 0; | |
441 GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}; | |
442 GLboolean depthMask = GL_TRUE; | |
443 GLuint stencilMask = 0xffffffff; | |
444 GLboolean isScissorEnabled = GL_FALSE; | |
445 GLboolean isDitherEnabled = GL_FALSE; | |
446 GLbitfield clearMask = GL_COLOR_BUFFER_BIT; | |
447 glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); | |
448 glClearColor(0, 0, 0, 0); | |
449 glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); | |
450 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
451 if (attributes_.depth) { | |
452 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); | |
453 glClearDepth(1); | |
454 glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); | |
455 glDepthMask(GL_TRUE); | |
456 clearMask |= GL_DEPTH_BUFFER_BIT; | |
457 } | |
458 if (attributes_.stencil) { | |
459 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil); | |
460 glClearStencil(0); | |
461 glGetIntegerv(GL_STENCIL_WRITEMASK, | |
462 reinterpret_cast<GLint*>(&stencilMask)); | |
463 glStencilMaskSeparate(GL_FRONT, 0xffffffff); | |
464 clearMask |= GL_STENCIL_BUFFER_BIT; | |
465 } | |
466 isScissorEnabled = glIsEnabled(GL_SCISSOR_TEST); | |
467 glDisable(GL_SCISSOR_TEST); | |
468 isDitherEnabled = glIsEnabled(GL_DITHER); | |
469 glDisable(GL_DITHER); | |
470 | |
471 glClear(clearMask); | |
472 | |
473 glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); | |
474 glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); | |
475 if (attributes_.depth) { | |
476 glClearDepth(clearDepth); | |
477 glDepthMask(depthMask); | |
478 } | |
479 if (attributes_.stencil) { | |
480 glClearStencil(clearStencil); | |
481 glStencilMaskSeparate(GL_FRONT, stencilMask); | |
482 } | |
483 if (isScissorEnabled) | |
484 glEnable(GL_SCISSOR_TEST); | |
485 else | |
486 glDisable(GL_SCISSOR_TEST); | |
487 if (isDitherEnabled) | |
488 glEnable(GL_DITHER); | |
489 else | |
490 glDisable(GL_DITHER); | |
491 | |
492 if (must_restore_fbo) | |
493 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
494 | |
495 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | |
496 if (scanline_) { | |
497 delete[] scanline_; | |
498 scanline_ = 0; | |
499 } | |
500 scanline_ = new unsigned char[width * 4]; | |
501 #endif // FLIP_FRAMEBUFFER_VERTICALLY | |
502 } | |
503 | |
504 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | |
505 void WebGraphicsContext3DInProcessImpl::FlipVertically( | |
506 unsigned char* framebuffer, unsigned int width, unsigned int height) { | |
507 unsigned char* scanline = scanline_; | |
508 if (!scanline) | |
509 return; | |
510 unsigned int row_bytes = width * 4; | |
511 unsigned int count = height / 2; | |
512 for (unsigned int i = 0; i < count; i++) { | |
513 unsigned char* row_a = framebuffer + i * row_bytes; | |
514 unsigned char* row_b = framebuffer + (height - i - 1) * row_bytes; | |
515 // FIXME: this is where the multiplication of the alpha | |
516 // channel into the color buffer will need to occur if the | |
517 // user specifies the "premultiplyAlpha" flag in the context | |
518 // creation attributes. | |
519 memcpy(scanline, row_b, row_bytes); | |
520 memcpy(row_b, row_a, row_bytes); | |
521 memcpy(row_a, scanline, row_bytes); | |
522 } | |
523 } | |
524 #endif | |
525 | |
526 bool WebGraphicsContext3DInProcessImpl::readBackFramebuffer( | |
527 unsigned char* pixels, size_t bufferSize) { | |
528 if (bufferSize != static_cast<size_t>(4 * width() * height())) | |
529 return false; | |
530 | |
531 makeContextCurrent(); | |
532 | |
533 // Earlier versions of this code used the GPU to flip the | |
534 // framebuffer vertically before reading it back for compositing | |
535 // via software. This code was quite complicated, used a lot of | |
536 // GPU memory, and didn't provide an obvious speedup. Since this | |
537 // vertical flip is only a temporary solution anyway until Chrome | |
538 // is fully GPU composited, it wasn't worth the complexity. | |
539 | |
540 ResolveMultisampledFramebuffer(0, 0, cached_width_, cached_height_); | |
541 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
542 | |
543 GLint pack_alignment = 4; | |
544 bool must_restore_pack_alignment = false; | |
545 glGetIntegerv(GL_PACK_ALIGNMENT, &pack_alignment); | |
546 if (pack_alignment > 4) { | |
547 glPixelStorei(GL_PACK_ALIGNMENT, 4); | |
548 must_restore_pack_alignment = true; | |
549 } | |
550 | |
551 if (is_gles2_) { | |
552 // FIXME: consider testing for presence of GL_OES_read_format | |
553 // and GL_EXT_read_format_bgra, and using GL_BGRA_EXT here | |
554 // directly. | |
555 glReadPixels(0, 0, cached_width_, cached_height_, | |
556 GL_RGBA, GL_UNSIGNED_BYTE, pixels); | |
557 for (size_t i = 0; i < bufferSize; i += 4) { | |
558 std::swap(pixels[i], pixels[i + 2]); | |
559 } | |
560 } else { | |
561 glReadPixels(0, 0, cached_width_, cached_height_, | |
562 GL_BGRA, GL_UNSIGNED_BYTE, pixels); | |
563 } | |
564 | |
565 if (must_restore_pack_alignment) | |
566 glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); | |
567 | |
568 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
569 | |
570 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | |
571 if (pixels) | |
572 FlipVertically(pixels, cached_width_, cached_height_); | |
573 #endif | |
574 | |
575 return true; | |
576 } | |
577 | |
578 void WebGraphicsContext3DInProcessImpl::synthesizeGLError(WGC3Denum error) { | |
579 if (synthetic_errors_set_.find(error) == synthetic_errors_set_.end()) { | |
580 synthetic_errors_set_.insert(error); | |
581 synthetic_errors_list_.push_back(error); | |
582 } | |
583 } | |
584 | |
585 void* WebGraphicsContext3DInProcessImpl::mapBufferSubDataCHROMIUM( | |
586 WGC3Denum target, WGC3Dintptr offset, | |
587 WGC3Dsizeiptr size, WGC3Denum access) { | |
588 return 0; | |
589 } | |
590 | |
591 void WebGraphicsContext3DInProcessImpl::unmapBufferSubDataCHROMIUM( | |
592 const void* mem) { | |
593 } | |
594 | |
595 void* WebGraphicsContext3DInProcessImpl::mapTexSubImage2DCHROMIUM( | |
596 WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, | |
597 WGC3Dsizei width, WGC3Dsizei height, WGC3Denum format, WGC3Denum type, | |
598 WGC3Denum access) { | |
599 return 0; | |
600 } | |
601 | |
602 void WebGraphicsContext3DInProcessImpl::unmapTexSubImage2DCHROMIUM( | |
603 const void* mem) { | |
604 } | |
605 | |
606 void WebGraphicsContext3DInProcessImpl::copyTextureToParentTextureCHROMIUM( | |
607 WebGLId id, WebGLId id2) { | |
608 if (!glGetTexLevelParameteriv) | |
609 return; | |
610 | |
611 makeContextCurrent(); | |
612 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, copy_texture_to_parent_texture_fbo_); | |
613 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, | |
614 GL_COLOR_ATTACHMENT0, | |
615 GL_TEXTURE_2D, | |
616 id, | |
617 0); // level | |
618 glBindTexture(GL_TEXTURE_2D, id2); | |
619 GLsizei width, height; | |
620 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); | |
621 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); | |
622 glCopyTexImage2D(GL_TEXTURE_2D, | |
623 0, // level | |
624 GL_RGBA, | |
625 0, 0, // x, y | |
626 width, | |
627 height, | |
628 0); // border | |
629 glBindTexture(GL_TEXTURE_2D, bound_texture_); | |
630 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
631 } | |
632 | |
633 WebString WebGraphicsContext3DInProcessImpl:: | |
634 getRequestableExtensionsCHROMIUM() { | |
635 return WebString(); | |
636 } | |
637 | |
638 void WebGraphicsContext3DInProcessImpl::requestExtensionCHROMIUM(const char*) { | |
639 } | |
640 | |
641 void WebGraphicsContext3DInProcessImpl::blitFramebufferCHROMIUM( | |
642 WGC3Dint srcX0, WGC3Dint srcY0, WGC3Dint srcX1, WGC3Dint srcY1, | |
643 WGC3Dint dstX0, WGC3Dint dstY0, WGC3Dint dstX1, WGC3Dint dstY1, | |
644 WGC3Dbitfield mask, WGC3Denum filter) { | |
645 } | |
646 | |
647 void WebGraphicsContext3DInProcessImpl::renderbufferStorageMultisampleCHROMIUM( | |
648 WGC3Denum target, WGC3Dsizei samples, WGC3Denum internalformat, | |
649 WGC3Dsizei width, WGC3Dsizei height) { | |
650 } | |
651 | |
652 // Helper macros to reduce the amount of code. | |
653 | |
654 #define DELEGATE_TO_GL(name, glname) \ | |
655 void WebGraphicsContext3DInProcessImpl::name() { \ | |
656 makeContextCurrent(); \ | |
657 gl##glname(); \ | |
658 } | |
659 | |
660 #define DELEGATE_TO_GL_1(name, glname, t1) \ | |
661 void WebGraphicsContext3DInProcessImpl::name(t1 a1) { \ | |
662 makeContextCurrent(); \ | |
663 gl##glname(a1); \ | |
664 } | |
665 | |
666 #define DELEGATE_TO_GL_1R(name, glname, t1, rt) \ | |
667 rt WebGraphicsContext3DInProcessImpl::name(t1 a1) { \ | |
668 makeContextCurrent(); \ | |
669 return gl##glname(a1); \ | |
670 } | |
671 | |
672 #define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \ | |
673 rt WebGraphicsContext3DInProcessImpl::name(t1 a1) { \ | |
674 makeContextCurrent(); \ | |
675 return gl##glname(a1) ? true : false; \ | |
676 } | |
677 | |
678 #define DELEGATE_TO_GL_2(name, glname, t1, t2) \ | |
679 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2) { \ | |
680 makeContextCurrent(); \ | |
681 gl##glname(a1, a2); \ | |
682 } | |
683 | |
684 #define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \ | |
685 rt WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2) { \ | |
686 makeContextCurrent(); \ | |
687 return gl##glname(a1, a2); \ | |
688 } | |
689 | |
690 #define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \ | |
691 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3) { \ | |
692 makeContextCurrent(); \ | |
693 gl##glname(a1, a2, a3); \ | |
694 } | |
695 | |
696 #define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ | |
697 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4) { \ | |
698 makeContextCurrent(); \ | |
699 gl##glname(a1, a2, a3, a4); \ | |
700 } | |
701 | |
702 #define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \ | |
703 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
704 t5 a5) { \ | |
705 makeContextCurrent(); \ | |
706 gl##glname(a1, a2, a3, a4, a5); \ | |
707 } | |
708 | |
709 #define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \ | |
710 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
711 t5 a5, t6 a6) { \ | |
712 makeContextCurrent(); \ | |
713 gl##glname(a1, a2, a3, a4, a5, a6); \ | |
714 } | |
715 | |
716 #define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \ | |
717 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
718 t5 a5, t6 a6, t7 a7) { \ | |
719 makeContextCurrent(); \ | |
720 gl##glname(a1, a2, a3, a4, a5, a6, a7); \ | |
721 } | |
722 | |
723 #define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \ | |
724 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
725 t5 a5, t6 a6, t7 a7, t8 a8) { \ | |
726 makeContextCurrent(); \ | |
727 gl##glname(a1, a2, a3, a4, a5, a6, a7, a8); \ | |
728 } | |
729 | |
730 #define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ | |
731 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
732 t5 a5, t6 a6, t7 a7, t8 a8, \ | |
733 t9 a9) { \ | |
734 makeContextCurrent(); \ | |
735 gl##glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \ | |
736 } | |
737 | |
738 void WebGraphicsContext3DInProcessImpl::activeTexture(WGC3Denum texture) { | |
739 // FIXME: query number of textures available. | |
740 if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32) | |
741 // FIXME: raise exception. | |
742 return; | |
743 | |
744 makeContextCurrent(); | |
745 glActiveTexture(texture); | |
746 } | |
747 | |
748 DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId) | |
749 | |
750 DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, | |
751 WebGLId, WGC3Duint, const WGC3Dchar*) | |
752 | |
753 DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId); | |
754 | |
755 void WebGraphicsContext3DInProcessImpl::bindFramebuffer( | |
756 WGC3Denum target, WebGLId framebuffer) { | |
757 makeContextCurrent(); | |
758 if (!framebuffer) | |
759 framebuffer = (attributes_.antialias ? multisample_fbo_ : fbo_); | |
760 if (framebuffer != bound_fbo_) { | |
761 glBindFramebufferEXT(target, framebuffer); | |
762 bound_fbo_ = framebuffer; | |
763 } | |
764 } | |
765 | |
766 DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbufferEXT, WGC3Denum, WebGLId) | |
767 | |
768 void WebGraphicsContext3DInProcessImpl::bindTexture( | |
769 WGC3Denum target, WebGLId texture) { | |
770 makeContextCurrent(); | |
771 glBindTexture(target, texture); | |
772 bound_texture_ = texture; | |
773 } | |
774 | |
775 DELEGATE_TO_GL_4(blendColor, BlendColor, | |
776 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
777 | |
778 DELEGATE_TO_GL_1(blendEquation, BlendEquation, WGC3Denum) | |
779 | |
780 DELEGATE_TO_GL_2(blendEquationSeparate, BlendEquationSeparate, | |
781 WGC3Denum, WGC3Denum) | |
782 | |
783 DELEGATE_TO_GL_2(blendFunc, BlendFunc, WGC3Denum, WGC3Denum) | |
784 | |
785 DELEGATE_TO_GL_4(blendFuncSeparate, BlendFuncSeparate, | |
786 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) | |
787 | |
788 DELEGATE_TO_GL_4(bufferData, BufferData, | |
789 WGC3Denum, WGC3Dsizeiptr, const void*, WGC3Denum) | |
790 | |
791 DELEGATE_TO_GL_4(bufferSubData, BufferSubData, | |
792 WGC3Denum, WGC3Dintptr, WGC3Dsizeiptr, const void*) | |
793 | |
794 DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatusEXT, | |
795 WGC3Denum, WGC3Denum) | |
796 | |
797 DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield) | |
798 | |
799 DELEGATE_TO_GL_4(clearColor, ClearColor, | |
800 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) | |
801 | |
802 DELEGATE_TO_GL_1(clearDepth, ClearDepth, WGC3Dclampf) | |
803 | |
804 DELEGATE_TO_GL_1(clearStencil, ClearStencil, WGC3Dint) | |
805 | |
806 DELEGATE_TO_GL_4(colorMask, ColorMask, | |
807 WGC3Dboolean, WGC3Dboolean, WGC3Dboolean, WGC3Dboolean) | |
808 | |
809 void WebGraphicsContext3DInProcessImpl::compileShader(WebGLId shader) { | |
810 makeContextCurrent(); | |
811 | |
812 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
813 if (result == shader_source_map_.end()) { | |
814 // Passing down to gl driver to generate the correct error; or the case | |
815 // where the shader deletion is delayed when it's attached to a program. | |
816 glCompileShader(shader); | |
817 return; | |
818 } | |
819 ShaderSourceEntry* entry = result->second; | |
820 DCHECK(entry); | |
821 | |
822 if (!AngleValidateShaderSource(entry)) { | |
823 // Shader didn't validate; don't move forward with compiling | |
824 // translated source. | |
825 return; | |
826 } | |
827 | |
828 const char* translated_source = entry->translated_source.get(); | |
829 int shader_length = translated_source ? strlen(translated_source) : 0; | |
830 glShaderSource( | |
831 shader, 1, const_cast<const char**>(&translated_source), &shader_length); | |
832 glCompileShader(shader); | |
833 | |
834 #ifndef NDEBUG | |
835 int compileStatus; | |
836 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); | |
837 // DCHECK that ANGLE generated GLSL will be accepted by OpenGL | |
838 DCHECK(compileStatus == GL_TRUE); | |
839 #endif | |
840 } | |
841 | |
842 void WebGraphicsContext3DInProcessImpl::copyTexImage2D( | |
843 WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dint x, | |
844 WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border) { | |
845 makeContextCurrent(); | |
846 | |
847 bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
848 if (needsResolve) { | |
849 ResolveMultisampledFramebuffer(x, y, width, height); | |
850 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
851 } | |
852 | |
853 glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); | |
854 | |
855 if (needsResolve) | |
856 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
857 } | |
858 | |
859 void WebGraphicsContext3DInProcessImpl::copyTexSubImage2D( | |
860 WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, | |
861 WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { | |
862 makeContextCurrent(); | |
863 | |
864 bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
865 if (needsResolve) { | |
866 ResolveMultisampledFramebuffer(x, y, width, height); | |
867 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
868 } | |
869 | |
870 glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); | |
871 | |
872 if (needsResolve) | |
873 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
874 } | |
875 | |
876 DELEGATE_TO_GL_1(cullFace, CullFace, WGC3Denum) | |
877 | |
878 DELEGATE_TO_GL_1(depthFunc, DepthFunc, WGC3Denum) | |
879 | |
880 DELEGATE_TO_GL_1(depthMask, DepthMask, WGC3Dboolean) | |
881 | |
882 DELEGATE_TO_GL_2(depthRange, DepthRange, WGC3Dclampf, WGC3Dclampf) | |
883 | |
884 DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId) | |
885 | |
886 DELEGATE_TO_GL_1(disable, Disable, WGC3Denum) | |
887 | |
888 DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray, WGC3Duint) | |
889 | |
890 DELEGATE_TO_GL_3(drawArrays, DrawArrays, WGC3Denum, WGC3Dint, WGC3Dsizei) | |
891 | |
892 void WebGraphicsContext3DInProcessImpl::drawElements( | |
893 WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset) { | |
894 makeContextCurrent(); | |
895 glDrawElements(mode, count, type, | |
896 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | |
897 } | |
898 | |
899 DELEGATE_TO_GL_1(enable, Enable, WGC3Denum) | |
900 | |
901 DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray, WGC3Duint) | |
902 | |
903 DELEGATE_TO_GL(finish, Finish) | |
904 | |
905 DELEGATE_TO_GL(flush, Flush) | |
906 | |
907 DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbufferEXT, | |
908 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId) | |
909 | |
910 DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2DEXT, | |
911 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint) | |
912 | |
913 DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum) | |
914 | |
915 void WebGraphicsContext3DInProcessImpl::generateMipmap(WGC3Denum target) { | |
916 makeContextCurrent(); | |
917 if (is_gles2_ || have_ext_framebuffer_object_) | |
918 glGenerateMipmapEXT(target); | |
919 // FIXME: provide alternative code path? This will be unpleasant | |
920 // to implement if glGenerateMipmapEXT is not available -- it will | |
921 // require a texture readback and re-upload. | |
922 } | |
923 | |
924 bool WebGraphicsContext3DInProcessImpl::getActiveAttrib( | |
925 WebGLId program, WGC3Duint index, ActiveInfo& info) { | |
926 makeContextCurrent(); | |
927 if (!program) { | |
928 synthesizeGLError(GL_INVALID_VALUE); | |
929 return false; | |
930 } | |
931 GLint max_name_length = -1; | |
932 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); | |
933 if (max_name_length < 0) | |
934 return false; | |
935 scoped_array<GLchar> name(new GLchar[max_name_length]); | |
936 GLsizei length = 0; | |
937 GLint size = -1; | |
938 GLenum type = 0; | |
939 glGetActiveAttrib(program, index, max_name_length, | |
940 &length, &size, &type, name.get()); | |
941 if (size < 0) { | |
942 return false; | |
943 } | |
944 info.name = WebString::fromUTF8(name.get(), length); | |
945 info.type = type; | |
946 info.size = size; | |
947 return true; | |
948 } | |
949 | |
950 bool WebGraphicsContext3DInProcessImpl::getActiveUniform( | |
951 WebGLId program, WGC3Duint index, ActiveInfo& info) { | |
952 makeContextCurrent(); | |
953 GLint max_name_length = -1; | |
954 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); | |
955 if (max_name_length < 0) | |
956 return false; | |
957 scoped_array<GLchar> name(new GLchar[max_name_length]); | |
958 GLsizei length = 0; | |
959 GLint size = -1; | |
960 GLenum type = 0; | |
961 glGetActiveUniform(program, index, max_name_length, | |
962 &length, &size, &type, name.get()); | |
963 if (size < 0) { | |
964 return false; | |
965 } | |
966 info.name = WebString::fromUTF8(name.get(), length); | |
967 info.type = type; | |
968 info.size = size; | |
969 return true; | |
970 } | |
971 | |
972 DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders, | |
973 WebGLId, WGC3Dsizei, WGC3Dsizei*, WebGLId*) | |
974 | |
975 DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation, | |
976 WebGLId, const WGC3Dchar*, WGC3Dint) | |
977 | |
978 DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, | |
979 WGC3Denum, WGC3Dboolean*) | |
980 | |
981 DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv, | |
982 WGC3Denum, WGC3Denum, WGC3Dint*) | |
983 | |
984 WebGraphicsContext3D::Attributes WebGraphicsContext3DInProcessImpl:: | |
985 getContextAttributes() { | |
986 return attributes_; | |
987 } | |
988 | |
989 WGC3Denum WebGraphicsContext3DInProcessImpl::getError() { | |
990 DCHECK(synthetic_errors_list_.size() == synthetic_errors_set_.size()); | |
991 if (synthetic_errors_set_.size() > 0) { | |
992 WGC3Denum error = synthetic_errors_list_.front(); | |
993 synthetic_errors_list_.pop_front(); | |
994 synthetic_errors_set_.erase(error); | |
995 return error; | |
996 } | |
997 | |
998 makeContextCurrent(); | |
999 return glGetError(); | |
1000 } | |
1001 | |
1002 bool WebGraphicsContext3DInProcessImpl::isContextLost() { | |
1003 return false; | |
1004 } | |
1005 | |
1006 DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*) | |
1007 | |
1008 void WebGraphicsContext3DInProcessImpl::getFramebufferAttachmentParameteriv( | |
1009 WGC3Denum target, WGC3Denum attachment, | |
1010 WGC3Denum pname, WGC3Dint* value) { | |
1011 makeContextCurrent(); | |
1012 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) | |
1013 attachment = GL_DEPTH_ATTACHMENT; // Or GL_STENCIL_ATTACHMENT; | |
1014 // either works. | |
1015 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); | |
1016 } | |
1017 | |
1018 void WebGraphicsContext3DInProcessImpl::getIntegerv( | |
1019 WGC3Denum pname, WGC3Dint* value) { | |
1020 makeContextCurrent(); | |
1021 if (is_gles2_) { | |
1022 glGetIntegerv(pname, value); | |
1023 return; | |
1024 } | |
1025 // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and | |
1026 // MAX_VARYING_VECTORS because desktop GL's corresponding queries | |
1027 // return the number of components whereas GLES2 return the number | |
1028 // of vectors (each vector has 4 components). Therefore, the value | |
1029 // returned by desktop GL needs to be divided by 4. | |
1030 switch (pname) { | |
1031 case MAX_FRAGMENT_UNIFORM_VECTORS: | |
1032 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value); | |
1033 *value /= 4; | |
1034 break; | |
1035 case MAX_VERTEX_UNIFORM_VECTORS: | |
1036 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value); | |
1037 *value /= 4; | |
1038 break; | |
1039 case MAX_VARYING_VECTORS: | |
1040 glGetIntegerv(GL_MAX_VARYING_FLOATS, value); | |
1041 *value /= 4; | |
1042 break; | |
1043 default: | |
1044 glGetIntegerv(pname, value); | |
1045 } | |
1046 } | |
1047 | |
1048 DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*) | |
1049 | |
1050 WebString WebGraphicsContext3DInProcessImpl::getProgramInfoLog( | |
1051 WebGLId program) { | |
1052 makeContextCurrent(); | |
1053 GLint log_length; | |
1054 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); | |
1055 if (!log_length) | |
1056 return WebString(); | |
1057 scoped_array<GLchar> log(new GLchar[log_length]); | |
1058 GLsizei returned_log_length; | |
1059 glGetProgramInfoLog(program, log_length, &returned_log_length, log.get()); | |
1060 DCHECK(log_length == returned_log_length + 1); | |
1061 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | |
1062 return res; | |
1063 } | |
1064 | |
1065 DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameterivEXT, | |
1066 WGC3Denum, WGC3Denum, WGC3Dint*) | |
1067 | |
1068 void WebGraphicsContext3DInProcessImpl::getShaderiv( | |
1069 WebGLId shader, WGC3Denum pname, WGC3Dint* value) { | |
1070 makeContextCurrent(); | |
1071 | |
1072 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1073 if (result != shader_source_map_.end()) { | |
1074 ShaderSourceEntry* entry = result->second; | |
1075 DCHECK(entry); | |
1076 switch (pname) { | |
1077 case GL_COMPILE_STATUS: | |
1078 if (!entry->is_valid) { | |
1079 *value = 0; | |
1080 return; | |
1081 } | |
1082 break; | |
1083 case GL_INFO_LOG_LENGTH: | |
1084 if (!entry->is_valid) { | |
1085 *value = entry->log.get() ? strlen(entry->log.get()) : 0; | |
1086 if (*value) | |
1087 (*value)++; | |
1088 return; | |
1089 } | |
1090 break; | |
1091 case GL_SHADER_SOURCE_LENGTH: | |
1092 *value = entry->source.get() ? strlen(entry->source.get()) : 0; | |
1093 if (*value) | |
1094 (*value)++; | |
1095 return; | |
1096 } | |
1097 } | |
1098 | |
1099 glGetShaderiv(shader, pname, value); | |
1100 } | |
1101 | |
1102 WebString WebGraphicsContext3DInProcessImpl::getShaderInfoLog(WebGLId shader) { | |
1103 makeContextCurrent(); | |
1104 | |
1105 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1106 if (result != shader_source_map_.end()) { | |
1107 ShaderSourceEntry* entry = result->second; | |
1108 DCHECK(entry); | |
1109 if (!entry->is_valid) { | |
1110 if (!entry->log.get()) | |
1111 return WebString(); | |
1112 WebString res = WebString::fromUTF8( | |
1113 entry->log.get(), strlen(entry->log.get())); | |
1114 return res; | |
1115 } | |
1116 } | |
1117 | |
1118 GLint log_length = 0; | |
1119 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); | |
1120 if (log_length <= 1) | |
1121 return WebString(); | |
1122 scoped_array<GLchar> log(new GLchar[log_length]); | |
1123 GLsizei returned_log_length; | |
1124 glGetShaderInfoLog(shader, log_length, &returned_log_length, log.get()); | |
1125 DCHECK(log_length == returned_log_length + 1); | |
1126 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | |
1127 return res; | |
1128 } | |
1129 | |
1130 WebString WebGraphicsContext3DInProcessImpl::getShaderSource(WebGLId shader) { | |
1131 makeContextCurrent(); | |
1132 | |
1133 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1134 if (result != shader_source_map_.end()) { | |
1135 ShaderSourceEntry* entry = result->second; | |
1136 DCHECK(entry); | |
1137 if (!entry->source.get()) | |
1138 return WebString(); | |
1139 WebString res = WebString::fromUTF8( | |
1140 entry->source.get(), strlen(entry->source.get())); | |
1141 return res; | |
1142 } | |
1143 | |
1144 GLint log_length = 0; | |
1145 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &log_length); | |
1146 if (log_length <= 1) | |
1147 return WebString(); | |
1148 scoped_array<GLchar> log(new GLchar[log_length]); | |
1149 GLsizei returned_log_length; | |
1150 glGetShaderSource(shader, log_length, &returned_log_length, log.get()); | |
1151 DCHECK(log_length == returned_log_length + 1); | |
1152 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | |
1153 return res; | |
1154 } | |
1155 | |
1156 WebString WebGraphicsContext3DInProcessImpl::getString(WGC3Denum name) { | |
1157 makeContextCurrent(); | |
1158 std::string result(reinterpret_cast<const char*>(glGetString(name))); | |
1159 if (name == GL_EXTENSIONS) { | |
1160 // GL_CHROMIUM_copy_texture_to_parent_texture requires the | |
1161 // desktopGL-only function glGetTexLevelParameteriv (GLES2 | |
1162 // doesn't support it). | |
1163 if (!is_gles2_) | |
1164 result += " GL_CHROMIUM_copy_texture_to_parent_texture"; | |
1165 } | |
1166 return WebString::fromUTF8(result.c_str()); | |
1167 } | |
1168 | |
1169 DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv, | |
1170 WGC3Denum, WGC3Denum, WGC3Dfloat*) | |
1171 | |
1172 DELEGATE_TO_GL_3(getTexParameteriv, GetTexParameteriv, | |
1173 WGC3Denum, WGC3Denum, WGC3Dint*) | |
1174 | |
1175 DELEGATE_TO_GL_3(getUniformfv, GetUniformfv, WebGLId, WGC3Dint, WGC3Dfloat*) | |
1176 | |
1177 DELEGATE_TO_GL_3(getUniformiv, GetUniformiv, WebGLId, WGC3Dint, WGC3Dint*) | |
1178 | |
1179 DELEGATE_TO_GL_2R(getUniformLocation, GetUniformLocation, | |
1180 WebGLId, const WGC3Dchar*, WGC3Dint) | |
1181 | |
1182 DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv, | |
1183 WGC3Duint, WGC3Denum, WGC3Dfloat*) | |
1184 | |
1185 DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv, | |
1186 WGC3Duint, WGC3Denum, WGC3Dint*) | |
1187 | |
1188 WGC3Dsizeiptr WebGraphicsContext3DInProcessImpl::getVertexAttribOffset( | |
1189 WGC3Duint index, WGC3Denum pname) { | |
1190 makeContextCurrent(); | |
1191 void* pointer; | |
1192 glGetVertexAttribPointerv(index, pname, &pointer); | |
1193 return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer)); | |
1194 } | |
1195 | |
1196 DELEGATE_TO_GL_2(hint, Hint, WGC3Denum, WGC3Denum) | |
1197 | |
1198 DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, WGC3Dboolean) | |
1199 | |
1200 DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, WGC3Denum, WGC3Dboolean) | |
1201 | |
1202 DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebufferEXT, WebGLId, WGC3Dboolean) | |
1203 | |
1204 DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, WGC3Dboolean) | |
1205 | |
1206 DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbufferEXT, WebGLId, WGC3Dboolean) | |
1207 | |
1208 DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, WGC3Dboolean) | |
1209 | |
1210 DELEGATE_TO_GL_1RB(isTexture, IsTexture, WebGLId, WGC3Dboolean) | |
1211 | |
1212 DELEGATE_TO_GL_1(lineWidth, LineWidth, WGC3Dfloat) | |
1213 | |
1214 DELEGATE_TO_GL_1(linkProgram, LinkProgram, WebGLId) | |
1215 | |
1216 DELEGATE_TO_GL_2(pixelStorei, PixelStorei, WGC3Denum, WGC3Dint) | |
1217 | |
1218 DELEGATE_TO_GL_2(polygonOffset, PolygonOffset, WGC3Dfloat, WGC3Dfloat) | |
1219 | |
1220 void WebGraphicsContext3DInProcessImpl::readPixels( | |
1221 WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height, | |
1222 WGC3Denum format, WGC3Denum type, void* pixels) { | |
1223 makeContextCurrent(); | |
1224 // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., | |
1225 // all previous rendering calls should be done before reading pixels. | |
1226 glFlush(); | |
1227 bool needs_resolve = | |
1228 (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
1229 if (needs_resolve) { | |
1230 ResolveMultisampledFramebuffer(x, y, width, height); | |
1231 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
1232 glFlush(); | |
1233 } | |
1234 | |
1235 glReadPixels(x, y, width, height, format, type, pixels); | |
1236 | |
1237 if (needs_resolve) | |
1238 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
1239 } | |
1240 | |
1241 void WebGraphicsContext3DInProcessImpl::releaseShaderCompiler() { | |
1242 } | |
1243 | |
1244 void WebGraphicsContext3DInProcessImpl::renderbufferStorage( | |
1245 WGC3Denum target, | |
1246 WGC3Denum internalformat, | |
1247 WGC3Dsizei width, | |
1248 WGC3Dsizei height) { | |
1249 makeContextCurrent(); | |
1250 if (!is_gles2_) { | |
1251 switch (internalformat) { | |
1252 case GL_DEPTH_STENCIL: | |
1253 internalformat = GL_DEPTH24_STENCIL8_EXT; | |
1254 break; | |
1255 case GL_DEPTH_COMPONENT16: | |
1256 internalformat = GL_DEPTH_COMPONENT; | |
1257 break; | |
1258 case GL_RGBA4: | |
1259 case GL_RGB5_A1: | |
1260 internalformat = GL_RGBA; | |
1261 break; | |
1262 case 0x8D62: // GL_RGB565 | |
1263 internalformat = GL_RGB; | |
1264 break; | |
1265 } | |
1266 } | |
1267 glRenderbufferStorageEXT(target, internalformat, width, height); | |
1268 } | |
1269 | |
1270 DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dclampf, WGC3Dboolean) | |
1271 | |
1272 DELEGATE_TO_GL_4(scissor, Scissor, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | |
1273 | |
1274 void WebGraphicsContext3DInProcessImpl::texImage2D( | |
1275 WGC3Denum target, WGC3Dint level, WGC3Denum internalFormat, | |
1276 WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, | |
1277 WGC3Denum format, WGC3Denum type, const void* pixels) { | |
1278 if (width && height && !pixels) { | |
1279 synthesizeGLError(GL_INVALID_VALUE); | |
1280 return; | |
1281 } | |
1282 makeContextCurrent(); | |
1283 glTexImage2D(target, level, internalFormat, | |
1284 width, height, border, format, type, pixels); | |
1285 } | |
1286 | |
1287 void WebGraphicsContext3DInProcessImpl::shaderSource( | |
1288 WebGLId shader, const WGC3Dchar* source) { | |
1289 makeContextCurrent(); | |
1290 GLint length = source ? strlen(source) : 0; | |
1291 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1292 if (result != shader_source_map_.end()) { | |
1293 ShaderSourceEntry* entry = result->second; | |
1294 DCHECK(entry); | |
1295 entry->source.reset(new char[length + 1]); | |
1296 memcpy(entry->source.get(), source, (length + 1) * sizeof(char)); | |
1297 } else { | |
1298 glShaderSource(shader, 1, &source, &length); | |
1299 } | |
1300 } | |
1301 | |
1302 DELEGATE_TO_GL_3(stencilFunc, StencilFunc, WGC3Denum, WGC3Dint, WGC3Duint) | |
1303 | |
1304 DELEGATE_TO_GL_4(stencilFuncSeparate, StencilFuncSeparate, | |
1305 WGC3Denum, WGC3Denum, WGC3Dint, WGC3Duint) | |
1306 | |
1307 DELEGATE_TO_GL_1(stencilMask, StencilMask, WGC3Duint) | |
1308 | |
1309 DELEGATE_TO_GL_2(stencilMaskSeparate, StencilMaskSeparate, | |
1310 WGC3Denum, WGC3Duint) | |
1311 | |
1312 DELEGATE_TO_GL_3(stencilOp, StencilOp, | |
1313 WGC3Denum, WGC3Denum, WGC3Denum) | |
1314 | |
1315 DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate, | |
1316 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) | |
1317 | |
1318 DELEGATE_TO_GL_3(texParameterf, TexParameterf, WGC3Denum, WGC3Denum, WGC3Dfloat) | |
1319 | |
1320 DELEGATE_TO_GL_3(texParameteri, TexParameteri, WGC3Denum, WGC3Denum, WGC3Dint) | |
1321 | |
1322 DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D, | |
1323 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, | |
1324 WGC3Dsizei, WGC3Denum, WGC3Denum, const void*) | |
1325 | |
1326 DELEGATE_TO_GL_2(uniform1f, Uniform1f, WGC3Dint, WGC3Dfloat) | |
1327 | |
1328 DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, | |
1329 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | |
1330 | |
1331 DELEGATE_TO_GL_2(uniform1i, Uniform1i, WGC3Dint, WGC3Dint) | |
1332 | |
1333 DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1334 | |
1335 DELEGATE_TO_GL_3(uniform2f, Uniform2f, WGC3Dint, WGC3Dfloat, WGC3Dfloat) | |
1336 | |
1337 DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, | |
1338 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | |
1339 | |
1340 DELEGATE_TO_GL_3(uniform2i, Uniform2i, WGC3Dint, WGC3Dint, WGC3Dint) | |
1341 | |
1342 DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1343 | |
1344 DELEGATE_TO_GL_4(uniform3f, Uniform3f, | |
1345 WGC3Dint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1346 | |
1347 DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, | |
1348 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | |
1349 | |
1350 DELEGATE_TO_GL_4(uniform3i, Uniform3i, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) | |
1351 | |
1352 DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1353 | |
1354 DELEGATE_TO_GL_5(uniform4f, Uniform4f, WGC3Dint, | |
1355 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1356 | |
1357 DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, | |
1358 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | |
1359 | |
1360 DELEGATE_TO_GL_5(uniform4i, Uniform4i, WGC3Dint, | |
1361 WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) | |
1362 | |
1363 DELEGATE_TO_GL_3(uniform4iv, Uniform4iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1364 | |
1365 DELEGATE_TO_GL_4(uniformMatrix2fv, UniformMatrix2fv, | |
1366 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1367 | |
1368 DELEGATE_TO_GL_4(uniformMatrix3fv, UniformMatrix3fv, | |
1369 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1370 | |
1371 DELEGATE_TO_GL_4(uniformMatrix4fv, UniformMatrix4fv, | |
1372 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1373 | |
1374 DELEGATE_TO_GL_1(useProgram, UseProgram, WebGLId) | |
1375 | |
1376 DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId) | |
1377 | |
1378 DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, WGC3Duint, WGC3Dfloat) | |
1379 | |
1380 DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint, const WGC3Dfloat*) | |
1381 | |
1382 DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, | |
1383 WGC3Duint, WGC3Dfloat, WGC3Dfloat) | |
1384 | |
1385 DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint, const WGC3Dfloat*) | |
1386 | |
1387 DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, | |
1388 WGC3Duint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1389 | |
1390 DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint, const WGC3Dfloat*) | |
1391 | |
1392 DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, | |
1393 WGC3Duint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1394 | |
1395 DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint, const WGC3Dfloat*) | |
1396 | |
1397 void WebGraphicsContext3DInProcessImpl::vertexAttribPointer( | |
1398 WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dboolean normalized, | |
1399 WGC3Dsizei stride, WGC3Dintptr offset) { | |
1400 makeContextCurrent(); | |
1401 glVertexAttribPointer(index, size, type, normalized, stride, | |
1402 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | |
1403 } | |
1404 | |
1405 DELEGATE_TO_GL_4(viewport, Viewport, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | |
1406 | |
1407 WebGLId WebGraphicsContext3DInProcessImpl::createBuffer() { | |
1408 makeContextCurrent(); | |
1409 GLuint o; | |
1410 glGenBuffersARB(1, &o); | |
1411 return o; | |
1412 } | |
1413 | |
1414 WebGLId WebGraphicsContext3DInProcessImpl::createFramebuffer() { | |
1415 makeContextCurrent(); | |
1416 GLuint o = 0; | |
1417 glGenFramebuffersEXT(1, &o); | |
1418 return o; | |
1419 } | |
1420 | |
1421 WebGLId WebGraphicsContext3DInProcessImpl::createProgram() { | |
1422 makeContextCurrent(); | |
1423 return glCreateProgram(); | |
1424 } | |
1425 | |
1426 WebGLId WebGraphicsContext3DInProcessImpl::createRenderbuffer() { | |
1427 makeContextCurrent(); | |
1428 GLuint o; | |
1429 glGenRenderbuffersEXT(1, &o); | |
1430 return o; | |
1431 } | |
1432 | |
1433 WebGLId WebGraphicsContext3DInProcessImpl::createShader( | |
1434 WGC3Denum shaderType) { | |
1435 makeContextCurrent(); | |
1436 DCHECK(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); | |
1437 GLuint shader = glCreateShader(shaderType); | |
1438 if (shader) { | |
1439 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1440 if (result != shader_source_map_.end()) { | |
1441 delete result->second; | |
1442 shader_source_map_.erase(result); | |
1443 } | |
1444 shader_source_map_.insert( | |
1445 ShaderSourceMap::value_type(shader, new ShaderSourceEntry(shaderType))); | |
1446 } | |
1447 | |
1448 return shader; | |
1449 } | |
1450 | |
1451 WebGLId WebGraphicsContext3DInProcessImpl::createTexture() { | |
1452 makeContextCurrent(); | |
1453 GLuint o; | |
1454 glGenTextures(1, &o); | |
1455 return o; | |
1456 } | |
1457 | |
1458 void WebGraphicsContext3DInProcessImpl::deleteBuffer(WebGLId buffer) { | |
1459 makeContextCurrent(); | |
1460 glDeleteBuffersARB(1, &buffer); | |
1461 } | |
1462 | |
1463 void WebGraphicsContext3DInProcessImpl::deleteFramebuffer( | |
1464 WebGLId framebuffer) { | |
1465 makeContextCurrent(); | |
1466 glDeleteFramebuffersEXT(1, &framebuffer); | |
1467 } | |
1468 | |
1469 void WebGraphicsContext3DInProcessImpl::deleteProgram(WebGLId program) { | |
1470 makeContextCurrent(); | |
1471 glDeleteProgram(program); | |
1472 } | |
1473 | |
1474 void WebGraphicsContext3DInProcessImpl::deleteRenderbuffer( | |
1475 WebGLId renderbuffer) { | |
1476 makeContextCurrent(); | |
1477 glDeleteRenderbuffersEXT(1, &renderbuffer); | |
1478 } | |
1479 | |
1480 void WebGraphicsContext3DInProcessImpl::deleteShader(WebGLId shader) { | |
1481 makeContextCurrent(); | |
1482 | |
1483 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1484 if (result != shader_source_map_.end()) { | |
1485 delete result->second; | |
1486 shader_source_map_.erase(result); | |
1487 } | |
1488 glDeleteShader(shader); | |
1489 } | |
1490 | |
1491 void WebGraphicsContext3DInProcessImpl::deleteTexture(WebGLId texture) { | |
1492 makeContextCurrent(); | |
1493 glDeleteTextures(1, &texture); | |
1494 } | |
1495 | |
1496 bool WebGraphicsContext3DInProcessImpl::AngleCreateCompilers() { | |
1497 if (!ShInitialize()) | |
1498 return false; | |
1499 | |
1500 ShBuiltInResources resources; | |
1501 ShInitBuiltInResources(&resources); | |
1502 getIntegerv(GL_MAX_VERTEX_ATTRIBS, &resources.MaxVertexAttribs); | |
1503 getIntegerv(MAX_VERTEX_UNIFORM_VECTORS, &resources.MaxVertexUniformVectors); | |
1504 getIntegerv(MAX_VARYING_VECTORS, &resources.MaxVaryingVectors); | |
1505 getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, | |
1506 &resources.MaxVertexTextureImageUnits); | |
1507 getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, | |
1508 &resources.MaxCombinedTextureImageUnits); | |
1509 getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &resources.MaxTextureImageUnits); | |
1510 getIntegerv(MAX_FRAGMENT_UNIFORM_VECTORS, | |
1511 &resources.MaxFragmentUniformVectors); | |
1512 // Always set to 1 for OpenGL ES. | |
1513 resources.MaxDrawBuffers = 1; | |
1514 | |
1515 fragment_compiler_ = ShConstructCompiler( | |
1516 SH_FRAGMENT_SHADER, SH_WEBGL_SPEC, &resources); | |
1517 vertex_compiler_ = ShConstructCompiler( | |
1518 SH_VERTEX_SHADER, SH_WEBGL_SPEC, &resources); | |
1519 return (fragment_compiler_ && vertex_compiler_); | |
1520 } | |
1521 | |
1522 void WebGraphicsContext3DInProcessImpl::AngleDestroyCompilers() { | |
1523 if (fragment_compiler_) { | |
1524 ShDestruct(fragment_compiler_); | |
1525 fragment_compiler_ = 0; | |
1526 } | |
1527 if (vertex_compiler_) { | |
1528 ShDestruct(vertex_compiler_); | |
1529 vertex_compiler_ = 0; | |
1530 } | |
1531 } | |
1532 | |
1533 bool WebGraphicsContext3DInProcessImpl::AngleValidateShaderSource( | |
1534 ShaderSourceEntry* entry) { | |
1535 entry->is_valid = false; | |
1536 entry->translated_source.reset(); | |
1537 entry->log.reset(); | |
1538 | |
1539 ShHandle compiler = 0; | |
1540 switch (entry->type) { | |
1541 case GL_FRAGMENT_SHADER: | |
1542 compiler = fragment_compiler_; | |
1543 break; | |
1544 case GL_VERTEX_SHADER: | |
1545 compiler = vertex_compiler_; | |
1546 break; | |
1547 } | |
1548 if (!compiler) | |
1549 return false; | |
1550 | |
1551 char* source = entry->source.get(); | |
1552 if (!ShCompile(compiler, &source, 1, SH_OBJECT_CODE)) { | |
1553 int logSize = 0; | |
1554 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &logSize); | |
1555 if (logSize > 1) { | |
1556 entry->log.reset(new char[logSize]); | |
1557 ShGetInfoLog(compiler, entry->log.get()); | |
1558 } | |
1559 return false; | |
1560 } | |
1561 | |
1562 int length = 0; | |
1563 if (is_gles2_) { | |
1564 // ANGLE does not yet have a GLSL ES backend. Therefore if the | |
1565 // compile succeeds we send the original source down. | |
1566 length = strlen(entry->source.get()); | |
1567 if (length > 0) | |
1568 ++length; // Add null terminator | |
1569 } else { | |
1570 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &length); | |
1571 } | |
1572 if (length > 1) { | |
1573 entry->translated_source.reset(new char[length]); | |
1574 if (is_gles2_) | |
1575 strncpy(entry->translated_source.get(), entry->source.get(), length); | |
1576 else | |
1577 ShGetObjectCode(compiler, entry->translated_source.get()); | |
1578 } | |
1579 entry->is_valid = true; | |
1580 return true; | |
1581 } | |
1582 | |
1583 #else // USE_WGC3D_TYPES | |
1584 | |
1585 WebGraphicsContext3DInProcessImpl:: | 33 WebGraphicsContext3DInProcessImpl:: |
1586 VertexAttribPointerState::VertexAttribPointerState() | 34 VertexAttribPointerState::VertexAttribPointerState() |
1587 : enabled(false), | 35 : enabled(false), |
1588 buffer(0), | 36 buffer(0), |
1589 indx(0), | 37 indx(0), |
1590 size(0), | 38 size(0), |
1591 type(0), | 39 type(0), |
1592 normalized(false), | 40 normalized(false), |
1593 stride(0), | 41 stride(0), |
1594 offset(0) { | 42 offset(0) { |
(...skipping 1271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2866 | 1314 |
2867 void WebGraphicsContext3DInProcessImpl::releaseShaderCompiler() { | 1315 void WebGraphicsContext3DInProcessImpl::releaseShaderCompiler() { |
2868 } | 1316 } |
2869 | 1317 |
2870 void WebGraphicsContext3DInProcessImpl::renderbufferStorage( | 1318 void WebGraphicsContext3DInProcessImpl::renderbufferStorage( |
2871 unsigned long target, | 1319 unsigned long target, |
2872 unsigned long internalformat, | 1320 unsigned long internalformat, |
2873 unsigned long width, | 1321 unsigned long width, |
2874 unsigned long height) { | 1322 unsigned long height) { |
2875 makeContextCurrent(); | 1323 makeContextCurrent(); |
2876 switch (internalformat) { | 1324 if (!is_gles2_) { |
2877 case GL_DEPTH_STENCIL: | 1325 switch (internalformat) { |
2878 internalformat = GL_DEPTH24_STENCIL8_EXT; | 1326 case GL_DEPTH_STENCIL: |
2879 break; | 1327 internalformat = GL_DEPTH24_STENCIL8_EXT; |
2880 case GL_DEPTH_COMPONENT16: | 1328 break; |
2881 internalformat = GL_DEPTH_COMPONENT; | 1329 case GL_DEPTH_COMPONENT16: |
2882 break; | 1330 internalformat = GL_DEPTH_COMPONENT; |
2883 case GL_RGBA4: | 1331 break; |
2884 case GL_RGB5_A1: | 1332 case GL_RGBA4: |
2885 internalformat = GL_RGBA; | 1333 case GL_RGB5_A1: |
2886 break; | 1334 internalformat = GL_RGBA; |
2887 case 0x8D62: // GL_RGB565 | 1335 break; |
2888 internalformat = GL_RGB; | 1336 case 0x8D62: // GL_RGB565 |
2889 break; | 1337 internalformat = GL_RGB; |
| 1338 break; |
| 1339 } |
2890 } | 1340 } |
2891 glRenderbufferStorageEXT(target, internalformat, width, height); | 1341 glRenderbufferStorageEXT(target, internalformat, width, height); |
2892 } | 1342 } |
2893 | 1343 |
2894 DELEGATE_TO_GL_2_C1(sampleCoverage, SampleCoverage, double, bool) | 1344 DELEGATE_TO_GL_2_C1(sampleCoverage, SampleCoverage, double, bool) |
2895 | 1345 |
2896 DELEGATE_TO_GL_4(scissor, Scissor, long, long, unsigned long, unsigned long) | 1346 DELEGATE_TO_GL_4(scissor, Scissor, long, long, unsigned long, unsigned long) |
2897 | 1347 |
2898 void WebGraphicsContext3DInProcessImpl::texImage2D( | 1348 void WebGraphicsContext3DInProcessImpl::texImage2D( |
2899 unsigned target, unsigned level, unsigned internalFormat, | 1349 unsigned target, unsigned level, unsigned internalFormat, |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3207 entry->translated_source.reset(new char[length]); | 1657 entry->translated_source.reset(new char[length]); |
3208 if (is_gles2_) | 1658 if (is_gles2_) |
3209 strncpy(entry->translated_source.get(), entry->source.get(), length); | 1659 strncpy(entry->translated_source.get(), entry->source.get(), length); |
3210 else | 1660 else |
3211 ShGetObjectCode(compiler, entry->translated_source.get()); | 1661 ShGetObjectCode(compiler, entry->translated_source.get()); |
3212 } | 1662 } |
3213 entry->is_valid = true; | 1663 entry->is_valid = true; |
3214 return true; | 1664 return true; |
3215 } | 1665 } |
3216 | 1666 |
3217 #endif // USE_WGC3D_TYPES | |
3218 | |
3219 } // namespace gpu | 1667 } // namespace gpu |
3220 } // namespace webkit | 1668 } // namespace webkit |
3221 | 1669 |
OLD | NEW |