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 | |
24 namespace webkit { | 19 namespace webkit { |
25 namespace gpu { | 20 namespace gpu { |
26 | 21 |
27 enum { | 22 enum { |
28 MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB, | 23 MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB, |
29 MAX_VARYING_VECTORS = 0x8DFC, | 24 MAX_VARYING_VECTORS = 0x8DFC, |
30 MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD | 25 MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD |
31 }; | 26 }; |
32 | 27 |
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 // Helper macros to reduce the amount of code. | |
642 | |
643 #define DELEGATE_TO_GL(name, glname) \ | |
644 void WebGraphicsContext3DInProcessImpl::name() { \ | |
645 makeContextCurrent(); \ | |
646 gl##glname(); \ | |
647 } | |
648 | |
649 #define DELEGATE_TO_GL_1(name, glname, t1) \ | |
650 void WebGraphicsContext3DInProcessImpl::name(t1 a1) { \ | |
651 makeContextCurrent(); \ | |
652 gl##glname(a1); \ | |
653 } | |
654 | |
655 #define DELEGATE_TO_GL_1R(name, glname, t1, rt) \ | |
656 rt WebGraphicsContext3DInProcessImpl::name(t1 a1) { \ | |
657 makeContextCurrent(); \ | |
658 return gl##glname(a1); \ | |
659 } | |
660 | |
661 #define DELEGATE_TO_GL_1RB(name, glname, t1, rt) \ | |
662 rt WebGraphicsContext3DInProcessImpl::name(t1 a1) { \ | |
663 makeContextCurrent(); \ | |
664 return gl##glname(a1) ? true : false; \ | |
665 } | |
666 | |
667 #define DELEGATE_TO_GL_2(name, glname, t1, t2) \ | |
668 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2) { \ | |
669 makeContextCurrent(); \ | |
670 gl##glname(a1, a2); \ | |
671 } | |
672 | |
673 #define DELEGATE_TO_GL_2R(name, glname, t1, t2, rt) \ | |
674 rt WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2) { \ | |
675 makeContextCurrent(); \ | |
676 return gl##glname(a1, a2); \ | |
677 } | |
678 | |
679 #define DELEGATE_TO_GL_3(name, glname, t1, t2, t3) \ | |
680 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3) { \ | |
681 makeContextCurrent(); \ | |
682 gl##glname(a1, a2, a3); \ | |
683 } | |
684 | |
685 #define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ | |
686 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4) { \ | |
687 makeContextCurrent(); \ | |
688 gl##glname(a1, a2, a3, a4); \ | |
689 } | |
690 | |
691 #define DELEGATE_TO_GL_5(name, glname, t1, t2, t3, t4, t5) \ | |
692 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
693 t5 a5) { \ | |
694 makeContextCurrent(); \ | |
695 gl##glname(a1, a2, a3, a4, a5); \ | |
696 } | |
697 | |
698 #define DELEGATE_TO_GL_6(name, glname, t1, t2, t3, t4, t5, t6) \ | |
699 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
700 t5 a5, t6 a6) { \ | |
701 makeContextCurrent(); \ | |
702 gl##glname(a1, a2, a3, a4, a5, a6); \ | |
703 } | |
704 | |
705 #define DELEGATE_TO_GL_7(name, glname, t1, t2, t3, t4, t5, t6, t7) \ | |
706 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
707 t5 a5, t6 a6, t7 a7) { \ | |
708 makeContextCurrent(); \ | |
709 gl##glname(a1, a2, a3, a4, a5, a6, a7); \ | |
710 } | |
711 | |
712 #define DELEGATE_TO_GL_8(name, glname, t1, t2, t3, t4, t5, t6, t7, t8) \ | |
713 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
714 t5 a5, t6 a6, t7 a7, t8 a8) { \ | |
715 makeContextCurrent(); \ | |
716 gl##glname(a1, a2, a3, a4, a5, a6, a7, a8); \ | |
717 } | |
718 | |
719 #define DELEGATE_TO_GL_9(name, glname, t1, t2, t3, t4, t5, t6, t7, t8, t9) \ | |
720 void WebGraphicsContext3DInProcessImpl::name(t1 a1, t2 a2, t3 a3, t4 a4, \ | |
721 t5 a5, t6 a6, t7 a7, t8 a8, \ | |
722 t9 a9) { \ | |
723 makeContextCurrent(); \ | |
724 gl##glname(a1, a2, a3, a4, a5, a6, a7, a8, a9); \ | |
725 } | |
726 | |
727 void WebGraphicsContext3DInProcessImpl::activeTexture(WGC3Denum texture) { | |
728 // FIXME: query number of textures available. | |
729 if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32) | |
730 // FIXME: raise exception. | |
731 return; | |
732 | |
733 makeContextCurrent(); | |
734 glActiveTexture(texture); | |
735 } | |
736 | |
737 DELEGATE_TO_GL_2(attachShader, AttachShader, WebGLId, WebGLId) | |
738 | |
739 DELEGATE_TO_GL_3(bindAttribLocation, BindAttribLocation, | |
740 WebGLId, WGC3Duint, const WGC3Dchar*) | |
741 | |
742 DELEGATE_TO_GL_2(bindBuffer, BindBuffer, WGC3Denum, WebGLId); | |
743 | |
744 void WebGraphicsContext3DInProcessImpl::bindFramebuffer( | |
745 WGC3Denum target, WebGLId framebuffer) { | |
746 makeContextCurrent(); | |
747 if (!framebuffer) | |
748 framebuffer = (attributes_.antialias ? multisample_fbo_ : fbo_); | |
749 if (framebuffer != bound_fbo_) { | |
750 glBindFramebufferEXT(target, framebuffer); | |
751 bound_fbo_ = framebuffer; | |
752 } | |
753 } | |
754 | |
755 DELEGATE_TO_GL_2(bindRenderbuffer, BindRenderbufferEXT, WGC3Denum, WebGLId) | |
756 | |
757 void WebGraphicsContext3DInProcessImpl::bindTexture( | |
758 WGC3Denum target, WebGLId texture) { | |
759 makeContextCurrent(); | |
760 glBindTexture(target, texture); | |
761 bound_texture_ = texture; | |
762 } | |
763 | |
764 DELEGATE_TO_GL_4(blendColor, BlendColor, | |
765 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
766 | |
767 DELEGATE_TO_GL_1(blendEquation, BlendEquation, WGC3Denum) | |
768 | |
769 DELEGATE_TO_GL_2(blendEquationSeparate, BlendEquationSeparate, | |
770 WGC3Denum, WGC3Denum) | |
771 | |
772 DELEGATE_TO_GL_2(blendFunc, BlendFunc, WGC3Denum, WGC3Denum) | |
773 | |
774 DELEGATE_TO_GL_4(blendFuncSeparate, BlendFuncSeparate, | |
775 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) | |
776 | |
777 DELEGATE_TO_GL_4(bufferData, BufferData, | |
778 WGC3Denum, WGC3Dsizeiptr, const void*, WGC3Denum) | |
779 | |
780 DELEGATE_TO_GL_4(bufferSubData, BufferSubData, | |
781 WGC3Denum, WGC3Dintptr, WGC3Dsizeiptr, const void*) | |
782 | |
783 DELEGATE_TO_GL_1R(checkFramebufferStatus, CheckFramebufferStatusEXT, | |
784 WGC3Denum, WGC3Denum) | |
785 | |
786 DELEGATE_TO_GL_1(clear, Clear, WGC3Dbitfield) | |
787 | |
788 DELEGATE_TO_GL_4(clearColor, ClearColor, | |
789 WGC3Dclampf, WGC3Dclampf, WGC3Dclampf, WGC3Dclampf) | |
790 | |
791 DELEGATE_TO_GL_1(clearDepth, ClearDepth, WGC3Dclampf) | |
792 | |
793 DELEGATE_TO_GL_1(clearStencil, ClearStencil, WGC3Dint) | |
794 | |
795 DELEGATE_TO_GL_4(colorMask, ColorMask, | |
796 WGC3Dboolean, WGC3Dboolean, WGC3Dboolean, WGC3Dboolean) | |
797 | |
798 void WebGraphicsContext3DInProcessImpl::compileShader(WebGLId shader) { | |
799 makeContextCurrent(); | |
800 | |
801 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
802 if (result == shader_source_map_.end()) { | |
803 // Passing down to gl driver to generate the correct error; or the case | |
804 // where the shader deletion is delayed when it's attached to a program. | |
805 glCompileShader(shader); | |
806 return; | |
807 } | |
808 ShaderSourceEntry* entry = result->second; | |
809 DCHECK(entry); | |
810 | |
811 if (!AngleValidateShaderSource(entry)) { | |
812 // Shader didn't validate; don't move forward with compiling | |
813 // translated source. | |
814 return; | |
815 } | |
816 | |
817 const char* translated_source = entry->translated_source.get(); | |
818 int shader_length = translated_source ? strlen(translated_source) : 0; | |
819 glShaderSource( | |
820 shader, 1, const_cast<const char**>(&translated_source), &shader_length); | |
821 glCompileShader(shader); | |
822 | |
823 #ifndef NDEBUG | |
824 int compileStatus; | |
825 glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); | |
826 // DCHECK that ANGLE generated GLSL will be accepted by OpenGL | |
827 DCHECK(compileStatus == GL_TRUE); | |
828 #endif | |
829 } | |
830 | |
831 void WebGraphicsContext3DInProcessImpl::copyTexImage2D( | |
832 WGC3Denum target, WGC3Dint level, WGC3Denum internalformat, WGC3Dint x, | |
833 WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border) { | |
834 makeContextCurrent(); | |
835 | |
836 bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
837 if (needsResolve) { | |
838 ResolveMultisampledFramebuffer(x, y, width, height); | |
839 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
840 } | |
841 | |
842 glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); | |
843 | |
844 if (needsResolve) | |
845 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
846 } | |
847 | |
848 void WebGraphicsContext3DInProcessImpl::copyTexSubImage2D( | |
849 WGC3Denum target, WGC3Dint level, WGC3Dint xoffset, WGC3Dint yoffset, | |
850 WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height) { | |
851 makeContextCurrent(); | |
852 | |
853 bool needsResolve = (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
854 if (needsResolve) { | |
855 ResolveMultisampledFramebuffer(x, y, width, height); | |
856 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
857 } | |
858 | |
859 glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); | |
860 | |
861 if (needsResolve) | |
862 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
863 } | |
864 | |
865 DELEGATE_TO_GL_1(cullFace, CullFace, WGC3Denum) | |
866 | |
867 DELEGATE_TO_GL_1(depthFunc, DepthFunc, WGC3Denum) | |
868 | |
869 DELEGATE_TO_GL_1(depthMask, DepthMask, WGC3Dboolean) | |
870 | |
871 DELEGATE_TO_GL_2(depthRange, DepthRange, WGC3Dclampf, WGC3Dclampf) | |
872 | |
873 DELEGATE_TO_GL_2(detachShader, DetachShader, WebGLId, WebGLId) | |
874 | |
875 DELEGATE_TO_GL_1(disable, Disable, WGC3Denum) | |
876 | |
877 DELEGATE_TO_GL_1(disableVertexAttribArray, DisableVertexAttribArray, WGC3Duint) | |
878 | |
879 DELEGATE_TO_GL_3(drawArrays, DrawArrays, WGC3Denum, WGC3Dint, WGC3Dsizei) | |
880 | |
881 void WebGraphicsContext3DInProcessImpl::drawElements( | |
882 WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset) { | |
883 makeContextCurrent(); | |
884 glDrawElements(mode, count, type, | |
885 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | |
886 } | |
887 | |
888 DELEGATE_TO_GL_1(enable, Enable, WGC3Denum) | |
889 | |
890 DELEGATE_TO_GL_1(enableVertexAttribArray, EnableVertexAttribArray, WGC3Duint) | |
891 | |
892 DELEGATE_TO_GL(finish, Finish) | |
893 | |
894 DELEGATE_TO_GL(flush, Flush) | |
895 | |
896 DELEGATE_TO_GL_4(framebufferRenderbuffer, FramebufferRenderbufferEXT, | |
897 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId) | |
898 | |
899 DELEGATE_TO_GL_5(framebufferTexture2D, FramebufferTexture2DEXT, | |
900 WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint) | |
901 | |
902 DELEGATE_TO_GL_1(frontFace, FrontFace, WGC3Denum) | |
903 | |
904 void WebGraphicsContext3DInProcessImpl::generateMipmap(WGC3Denum target) { | |
905 makeContextCurrent(); | |
906 if (is_gles2_ || have_ext_framebuffer_object_) | |
907 glGenerateMipmapEXT(target); | |
908 // FIXME: provide alternative code path? This will be unpleasant | |
909 // to implement if glGenerateMipmapEXT is not available -- it will | |
910 // require a texture readback and re-upload. | |
911 } | |
912 | |
913 bool WebGraphicsContext3DInProcessImpl::getActiveAttrib( | |
914 WebGLId program, WGC3Duint index, ActiveInfo& info) { | |
915 makeContextCurrent(); | |
916 if (!program) { | |
917 synthesizeGLError(GL_INVALID_VALUE); | |
918 return false; | |
919 } | |
920 GLint max_name_length = -1; | |
921 glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_name_length); | |
922 if (max_name_length < 0) | |
923 return false; | |
924 scoped_array<GLchar> name(new GLchar[max_name_length]); | |
925 GLsizei length = 0; | |
926 GLint size = -1; | |
927 GLenum type = 0; | |
928 glGetActiveAttrib(program, index, max_name_length, | |
929 &length, &size, &type, name.get()); | |
930 if (size < 0) { | |
931 return false; | |
932 } | |
933 info.name = WebString::fromUTF8(name.get(), length); | |
934 info.type = type; | |
935 info.size = size; | |
936 return true; | |
937 } | |
938 | |
939 bool WebGraphicsContext3DInProcessImpl::getActiveUniform( | |
940 WebGLId program, WGC3Duint index, ActiveInfo& info) { | |
941 makeContextCurrent(); | |
942 GLint max_name_length = -1; | |
943 glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length); | |
944 if (max_name_length < 0) | |
945 return false; | |
946 scoped_array<GLchar> name(new GLchar[max_name_length]); | |
947 GLsizei length = 0; | |
948 GLint size = -1; | |
949 GLenum type = 0; | |
950 glGetActiveUniform(program, index, max_name_length, | |
951 &length, &size, &type, name.get()); | |
952 if (size < 0) { | |
953 return false; | |
954 } | |
955 info.name = WebString::fromUTF8(name.get(), length); | |
956 info.type = type; | |
957 info.size = size; | |
958 return true; | |
959 } | |
960 | |
961 DELEGATE_TO_GL_4(getAttachedShaders, GetAttachedShaders, | |
962 WebGLId, WGC3Dsizei, WGC3Dsizei*, WebGLId*) | |
963 | |
964 DELEGATE_TO_GL_2R(getAttribLocation, GetAttribLocation, | |
965 WebGLId, const WGC3Dchar*, WGC3Dint) | |
966 | |
967 DELEGATE_TO_GL_2(getBooleanv, GetBooleanv, | |
968 WGC3Denum, WGC3Dboolean*) | |
969 | |
970 DELEGATE_TO_GL_3(getBufferParameteriv, GetBufferParameteriv, | |
971 WGC3Denum, WGC3Denum, WGC3Dint*) | |
972 | |
973 WebGraphicsContext3D::Attributes WebGraphicsContext3DInProcessImpl:: | |
974 getContextAttributes() { | |
975 return attributes_; | |
976 } | |
977 | |
978 WGC3Denum WebGraphicsContext3DInProcessImpl::getError() { | |
979 DCHECK(synthetic_errors_list_.size() == synthetic_errors_set_.size()); | |
980 if (synthetic_errors_set_.size() > 0) { | |
981 WGC3Denum error = synthetic_errors_list_.front(); | |
982 synthetic_errors_list_.pop_front(); | |
983 synthetic_errors_set_.erase(error); | |
984 return error; | |
985 } | |
986 | |
987 makeContextCurrent(); | |
988 return glGetError(); | |
989 } | |
990 | |
991 bool WebGraphicsContext3DInProcessImpl::isContextLost() { | |
992 return false; | |
993 } | |
994 | |
995 DELEGATE_TO_GL_2(getFloatv, GetFloatv, WGC3Denum, WGC3Dfloat*) | |
996 | |
997 void WebGraphicsContext3DInProcessImpl::getFramebufferAttachmentParameteriv( | |
998 WGC3Denum target, WGC3Denum attachment, | |
999 WGC3Denum pname, WGC3Dint* value) { | |
1000 makeContextCurrent(); | |
1001 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) | |
1002 attachment = GL_DEPTH_ATTACHMENT; // Or GL_STENCIL_ATTACHMENT; | |
1003 // either works. | |
1004 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); | |
1005 } | |
1006 | |
1007 void WebGraphicsContext3DInProcessImpl::getIntegerv( | |
1008 WGC3Denum pname, WGC3Dint* value) { | |
1009 makeContextCurrent(); | |
1010 if (is_gles2_) { | |
1011 glGetIntegerv(pname, value); | |
1012 return; | |
1013 } | |
1014 // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and | |
1015 // MAX_VARYING_VECTORS because desktop GL's corresponding queries | |
1016 // return the number of components whereas GLES2 return the number | |
1017 // of vectors (each vector has 4 components). Therefore, the value | |
1018 // returned by desktop GL needs to be divided by 4. | |
1019 switch (pname) { | |
1020 case MAX_FRAGMENT_UNIFORM_VECTORS: | |
1021 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value); | |
1022 *value /= 4; | |
1023 break; | |
1024 case MAX_VERTEX_UNIFORM_VECTORS: | |
1025 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value); | |
1026 *value /= 4; | |
1027 break; | |
1028 case MAX_VARYING_VECTORS: | |
1029 glGetIntegerv(GL_MAX_VARYING_FLOATS, value); | |
1030 *value /= 4; | |
1031 break; | |
1032 default: | |
1033 glGetIntegerv(pname, value); | |
1034 } | |
1035 } | |
1036 | |
1037 DELEGATE_TO_GL_3(getProgramiv, GetProgramiv, WebGLId, WGC3Denum, WGC3Dint*) | |
1038 | |
1039 WebString WebGraphicsContext3DInProcessImpl::getProgramInfoLog( | |
1040 WebGLId program) { | |
1041 makeContextCurrent(); | |
1042 GLint log_length; | |
1043 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); | |
1044 if (!log_length) | |
1045 return WebString(); | |
1046 scoped_array<GLchar> log(new GLchar[log_length]); | |
1047 GLsizei returned_log_length; | |
1048 glGetProgramInfoLog(program, log_length, &returned_log_length, log.get()); | |
1049 DCHECK(log_length == returned_log_length + 1); | |
1050 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | |
1051 return res; | |
1052 } | |
1053 | |
1054 DELEGATE_TO_GL_3(getRenderbufferParameteriv, GetRenderbufferParameterivEXT, | |
1055 WGC3Denum, WGC3Denum, WGC3Dint*) | |
1056 | |
1057 void WebGraphicsContext3DInProcessImpl::getShaderiv( | |
1058 WebGLId shader, WGC3Denum pname, WGC3Dint* value) { | |
1059 makeContextCurrent(); | |
1060 | |
1061 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1062 if (result != shader_source_map_.end()) { | |
1063 ShaderSourceEntry* entry = result->second; | |
1064 DCHECK(entry); | |
1065 switch (pname) { | |
1066 case GL_COMPILE_STATUS: | |
1067 if (!entry->is_valid) { | |
1068 *value = 0; | |
1069 return; | |
1070 } | |
1071 break; | |
1072 case GL_INFO_LOG_LENGTH: | |
1073 if (!entry->is_valid) { | |
1074 *value = entry->log.get() ? strlen(entry->log.get()) : 0; | |
1075 if (*value) | |
1076 (*value)++; | |
1077 return; | |
1078 } | |
1079 break; | |
1080 case GL_SHADER_SOURCE_LENGTH: | |
1081 *value = entry->source.get() ? strlen(entry->source.get()) : 0; | |
1082 if (*value) | |
1083 (*value)++; | |
1084 return; | |
1085 } | |
1086 } | |
1087 | |
1088 glGetShaderiv(shader, pname, value); | |
1089 } | |
1090 | |
1091 WebString WebGraphicsContext3DInProcessImpl::getShaderInfoLog(WebGLId shader) { | |
1092 makeContextCurrent(); | |
1093 | |
1094 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1095 if (result != shader_source_map_.end()) { | |
1096 ShaderSourceEntry* entry = result->second; | |
1097 DCHECK(entry); | |
1098 if (!entry->is_valid) { | |
1099 if (!entry->log.get()) | |
1100 return WebString(); | |
1101 WebString res = WebString::fromUTF8( | |
1102 entry->log.get(), strlen(entry->log.get())); | |
1103 return res; | |
1104 } | |
1105 } | |
1106 | |
1107 GLint log_length = 0; | |
1108 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); | |
1109 if (log_length <= 1) | |
1110 return WebString(); | |
1111 scoped_array<GLchar> log(new GLchar[log_length]); | |
1112 GLsizei returned_log_length; | |
1113 glGetShaderInfoLog(shader, log_length, &returned_log_length, log.get()); | |
1114 DCHECK(log_length == returned_log_length + 1); | |
1115 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | |
1116 return res; | |
1117 } | |
1118 | |
1119 WebString WebGraphicsContext3DInProcessImpl::getShaderSource(WebGLId shader) { | |
1120 makeContextCurrent(); | |
1121 | |
1122 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1123 if (result != shader_source_map_.end()) { | |
1124 ShaderSourceEntry* entry = result->second; | |
1125 DCHECK(entry); | |
1126 if (!entry->source.get()) | |
1127 return WebString(); | |
1128 WebString res = WebString::fromUTF8( | |
1129 entry->source.get(), strlen(entry->source.get())); | |
1130 return res; | |
1131 } | |
1132 | |
1133 GLint log_length = 0; | |
1134 glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &log_length); | |
1135 if (log_length <= 1) | |
1136 return WebString(); | |
1137 scoped_array<GLchar> log(new GLchar[log_length]); | |
1138 GLsizei returned_log_length; | |
1139 glGetShaderSource(shader, log_length, &returned_log_length, log.get()); | |
1140 DCHECK(log_length == returned_log_length + 1); | |
1141 WebString res = WebString::fromUTF8(log.get(), returned_log_length); | |
1142 return res; | |
1143 } | |
1144 | |
1145 WebString WebGraphicsContext3DInProcessImpl::getString(WGC3Denum name) { | |
1146 makeContextCurrent(); | |
1147 std::string result(reinterpret_cast<const char*>(glGetString(name))); | |
1148 if (name == GL_EXTENSIONS) { | |
1149 // GL_CHROMIUM_copy_texture_to_parent_texture requires the | |
1150 // desktopGL-only function glGetTexLevelParameteriv (GLES2 | |
1151 // doesn't support it). | |
1152 if (!is_gles2_) | |
1153 result += " GL_CHROMIUM_copy_texture_to_parent_texture"; | |
1154 } | |
1155 return WebString::fromUTF8(result.c_str()); | |
1156 } | |
1157 | |
1158 DELEGATE_TO_GL_3(getTexParameterfv, GetTexParameterfv, | |
1159 WGC3Denum, WGC3Denum, WGC3Dfloat*) | |
1160 | |
1161 DELEGATE_TO_GL_3(getTexParameteriv, GetTexParameteriv, | |
1162 WGC3Denum, WGC3Denum, WGC3Dint*) | |
1163 | |
1164 DELEGATE_TO_GL_3(getUniformfv, GetUniformfv, WebGLId, WGC3Dint, WGC3Dfloat*) | |
1165 | |
1166 DELEGATE_TO_GL_3(getUniformiv, GetUniformiv, WebGLId, WGC3Dint, WGC3Dint*) | |
1167 | |
1168 DELEGATE_TO_GL_2R(getUniformLocation, GetUniformLocation, | |
1169 WebGLId, const WGC3Dchar*, WGC3Dint) | |
1170 | |
1171 DELEGATE_TO_GL_3(getVertexAttribfv, GetVertexAttribfv, | |
1172 WGC3Duint, WGC3Denum, WGC3Dfloat*) | |
1173 | |
1174 DELEGATE_TO_GL_3(getVertexAttribiv, GetVertexAttribiv, | |
1175 WGC3Duint, WGC3Denum, WGC3Dint*) | |
1176 | |
1177 WGC3Dsizeiptr WebGraphicsContext3DInProcessImpl::getVertexAttribOffset( | |
1178 WGC3Duint index, WGC3Denum pname) { | |
1179 makeContextCurrent(); | |
1180 void* pointer; | |
1181 glGetVertexAttribPointerv(index, pname, &pointer); | |
1182 return static_cast<WGC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer)); | |
1183 } | |
1184 | |
1185 DELEGATE_TO_GL_2(hint, Hint, WGC3Denum, WGC3Denum) | |
1186 | |
1187 DELEGATE_TO_GL_1RB(isBuffer, IsBuffer, WebGLId, WGC3Dboolean) | |
1188 | |
1189 DELEGATE_TO_GL_1RB(isEnabled, IsEnabled, WGC3Denum, WGC3Dboolean) | |
1190 | |
1191 DELEGATE_TO_GL_1RB(isFramebuffer, IsFramebufferEXT, WebGLId, WGC3Dboolean) | |
1192 | |
1193 DELEGATE_TO_GL_1RB(isProgram, IsProgram, WebGLId, WGC3Dboolean) | |
1194 | |
1195 DELEGATE_TO_GL_1RB(isRenderbuffer, IsRenderbufferEXT, WebGLId, WGC3Dboolean) | |
1196 | |
1197 DELEGATE_TO_GL_1RB(isShader, IsShader, WebGLId, WGC3Dboolean) | |
1198 | |
1199 DELEGATE_TO_GL_1RB(isTexture, IsTexture, WebGLId, WGC3Dboolean) | |
1200 | |
1201 DELEGATE_TO_GL_1(lineWidth, LineWidth, WGC3Dfloat) | |
1202 | |
1203 DELEGATE_TO_GL_1(linkProgram, LinkProgram, WebGLId) | |
1204 | |
1205 DELEGATE_TO_GL_2(pixelStorei, PixelStorei, WGC3Denum, WGC3Dint) | |
1206 | |
1207 DELEGATE_TO_GL_2(polygonOffset, PolygonOffset, WGC3Dfloat, WGC3Dfloat) | |
1208 | |
1209 void WebGraphicsContext3DInProcessImpl::readPixels( | |
1210 WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height, | |
1211 WGC3Denum format, WGC3Denum type, void* pixels) { | |
1212 makeContextCurrent(); | |
1213 // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., | |
1214 // all previous rendering calls should be done before reading pixels. | |
1215 glFlush(); | |
1216 bool needs_resolve = | |
1217 (attributes_.antialias && bound_fbo_ == multisample_fbo_); | |
1218 if (needs_resolve) { | |
1219 ResolveMultisampledFramebuffer(x, y, width, height); | |
1220 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | |
1221 glFlush(); | |
1222 } | |
1223 | |
1224 glReadPixels(x, y, width, height, format, type, pixels); | |
1225 | |
1226 if (needs_resolve) | |
1227 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_); | |
1228 } | |
1229 | |
1230 void WebGraphicsContext3DInProcessImpl::releaseShaderCompiler() { | |
1231 } | |
1232 | |
1233 void WebGraphicsContext3DInProcessImpl::renderbufferStorage( | |
1234 WGC3Denum target, | |
1235 WGC3Denum internalformat, | |
1236 WGC3Dsizei width, | |
1237 WGC3Dsizei height) { | |
1238 makeContextCurrent(); | |
1239 if (!is_gles2_) { | |
1240 switch (internalformat) { | |
1241 case GL_DEPTH_STENCIL: | |
1242 internalformat = GL_DEPTH24_STENCIL8_EXT; | |
1243 break; | |
1244 case GL_DEPTH_COMPONENT16: | |
1245 internalformat = GL_DEPTH_COMPONENT; | |
1246 break; | |
1247 case GL_RGBA4: | |
1248 case GL_RGB5_A1: | |
1249 internalformat = GL_RGBA; | |
1250 break; | |
1251 case 0x8D62: // GL_RGB565 | |
1252 internalformat = GL_RGB; | |
1253 break; | |
1254 } | |
1255 } | |
1256 glRenderbufferStorageEXT(target, internalformat, width, height); | |
1257 } | |
1258 | |
1259 DELEGATE_TO_GL_2(sampleCoverage, SampleCoverage, WGC3Dclampf, WGC3Dboolean) | |
1260 | |
1261 DELEGATE_TO_GL_4(scissor, Scissor, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | |
1262 | |
1263 void WebGraphicsContext3DInProcessImpl::texImage2D( | |
1264 WGC3Denum target, WGC3Dint level, WGC3Denum internalFormat, | |
1265 WGC3Dsizei width, WGC3Dsizei height, WGC3Dint border, | |
1266 WGC3Denum format, WGC3Denum type, const void* pixels) { | |
1267 if (width && height && !pixels) { | |
1268 synthesizeGLError(GL_INVALID_VALUE); | |
1269 return; | |
1270 } | |
1271 makeContextCurrent(); | |
1272 glTexImage2D(target, level, internalFormat, | |
1273 width, height, border, format, type, pixels); | |
1274 } | |
1275 | |
1276 void WebGraphicsContext3DInProcessImpl::shaderSource( | |
1277 WebGLId shader, const WGC3Dchar* source) { | |
1278 makeContextCurrent(); | |
1279 GLint length = source ? strlen(source) : 0; | |
1280 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1281 if (result != shader_source_map_.end()) { | |
1282 ShaderSourceEntry* entry = result->second; | |
1283 DCHECK(entry); | |
1284 entry->source.reset(new char[length + 1]); | |
1285 memcpy(entry->source.get(), source, (length + 1) * sizeof(char)); | |
1286 } else { | |
1287 glShaderSource(shader, 1, &source, &length); | |
1288 } | |
1289 } | |
1290 | |
1291 DELEGATE_TO_GL_3(stencilFunc, StencilFunc, WGC3Denum, WGC3Dint, WGC3Duint) | |
1292 | |
1293 DELEGATE_TO_GL_4(stencilFuncSeparate, StencilFuncSeparate, | |
1294 WGC3Denum, WGC3Denum, WGC3Dint, WGC3Duint) | |
1295 | |
1296 DELEGATE_TO_GL_1(stencilMask, StencilMask, WGC3Duint) | |
1297 | |
1298 DELEGATE_TO_GL_2(stencilMaskSeparate, StencilMaskSeparate, | |
1299 WGC3Denum, WGC3Duint) | |
1300 | |
1301 DELEGATE_TO_GL_3(stencilOp, StencilOp, | |
1302 WGC3Denum, WGC3Denum, WGC3Denum) | |
1303 | |
1304 DELEGATE_TO_GL_4(stencilOpSeparate, StencilOpSeparate, | |
1305 WGC3Denum, WGC3Denum, WGC3Denum, WGC3Denum) | |
1306 | |
1307 DELEGATE_TO_GL_3(texParameterf, TexParameterf, WGC3Denum, WGC3Denum, WGC3Dfloat) | |
1308 | |
1309 DELEGATE_TO_GL_3(texParameteri, TexParameteri, WGC3Denum, WGC3Denum, WGC3Dint) | |
1310 | |
1311 DELEGATE_TO_GL_9(texSubImage2D, TexSubImage2D, | |
1312 WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, | |
1313 WGC3Dsizei, WGC3Denum, WGC3Denum, const void*) | |
1314 | |
1315 DELEGATE_TO_GL_2(uniform1f, Uniform1f, WGC3Dint, WGC3Dfloat) | |
1316 | |
1317 DELEGATE_TO_GL_3(uniform1fv, Uniform1fv, | |
1318 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | |
1319 | |
1320 DELEGATE_TO_GL_2(uniform1i, Uniform1i, WGC3Dint, WGC3Dint) | |
1321 | |
1322 DELEGATE_TO_GL_3(uniform1iv, Uniform1iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1323 | |
1324 DELEGATE_TO_GL_3(uniform2f, Uniform2f, WGC3Dint, WGC3Dfloat, WGC3Dfloat) | |
1325 | |
1326 DELEGATE_TO_GL_3(uniform2fv, Uniform2fv, | |
1327 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | |
1328 | |
1329 DELEGATE_TO_GL_3(uniform2i, Uniform2i, WGC3Dint, WGC3Dint, WGC3Dint) | |
1330 | |
1331 DELEGATE_TO_GL_3(uniform2iv, Uniform2iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1332 | |
1333 DELEGATE_TO_GL_4(uniform3f, Uniform3f, | |
1334 WGC3Dint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1335 | |
1336 DELEGATE_TO_GL_3(uniform3fv, Uniform3fv, | |
1337 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | |
1338 | |
1339 DELEGATE_TO_GL_4(uniform3i, Uniform3i, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) | |
1340 | |
1341 DELEGATE_TO_GL_3(uniform3iv, Uniform3iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1342 | |
1343 DELEGATE_TO_GL_5(uniform4f, Uniform4f, WGC3Dint, | |
1344 WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1345 | |
1346 DELEGATE_TO_GL_3(uniform4fv, Uniform4fv, | |
1347 WGC3Dint, WGC3Dsizei, const WGC3Dfloat*) | |
1348 | |
1349 DELEGATE_TO_GL_5(uniform4i, Uniform4i, WGC3Dint, | |
1350 WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint) | |
1351 | |
1352 DELEGATE_TO_GL_3(uniform4iv, Uniform4iv, WGC3Dint, WGC3Dsizei, const WGC3Dint*) | |
1353 | |
1354 DELEGATE_TO_GL_4(uniformMatrix2fv, UniformMatrix2fv, | |
1355 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1356 | |
1357 DELEGATE_TO_GL_4(uniformMatrix3fv, UniformMatrix3fv, | |
1358 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1359 | |
1360 DELEGATE_TO_GL_4(uniformMatrix4fv, UniformMatrix4fv, | |
1361 WGC3Dint, WGC3Dsizei, WGC3Dboolean, const WGC3Dfloat*) | |
1362 | |
1363 DELEGATE_TO_GL_1(useProgram, UseProgram, WebGLId) | |
1364 | |
1365 DELEGATE_TO_GL_1(validateProgram, ValidateProgram, WebGLId) | |
1366 | |
1367 DELEGATE_TO_GL_2(vertexAttrib1f, VertexAttrib1f, WGC3Duint, WGC3Dfloat) | |
1368 | |
1369 DELEGATE_TO_GL_2(vertexAttrib1fv, VertexAttrib1fv, WGC3Duint, const WGC3Dfloat*) | |
1370 | |
1371 DELEGATE_TO_GL_3(vertexAttrib2f, VertexAttrib2f, | |
1372 WGC3Duint, WGC3Dfloat, WGC3Dfloat) | |
1373 | |
1374 DELEGATE_TO_GL_2(vertexAttrib2fv, VertexAttrib2fv, WGC3Duint, const WGC3Dfloat*) | |
1375 | |
1376 DELEGATE_TO_GL_4(vertexAttrib3f, VertexAttrib3f, | |
1377 WGC3Duint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1378 | |
1379 DELEGATE_TO_GL_2(vertexAttrib3fv, VertexAttrib3fv, WGC3Duint, const WGC3Dfloat*) | |
1380 | |
1381 DELEGATE_TO_GL_5(vertexAttrib4f, VertexAttrib4f, | |
1382 WGC3Duint, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat, WGC3Dfloat) | |
1383 | |
1384 DELEGATE_TO_GL_2(vertexAttrib4fv, VertexAttrib4fv, WGC3Duint, const WGC3Dfloat*) | |
1385 | |
1386 void WebGraphicsContext3DInProcessImpl::vertexAttribPointer( | |
1387 WGC3Duint index, WGC3Dint size, WGC3Denum type, WGC3Dboolean normalized, | |
1388 WGC3Dsizei stride, WGC3Dintptr offset) { | |
1389 makeContextCurrent(); | |
1390 glVertexAttribPointer(index, size, type, normalized, stride, | |
1391 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | |
1392 } | |
1393 | |
1394 DELEGATE_TO_GL_4(viewport, Viewport, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei) | |
1395 | |
1396 WebGLId WebGraphicsContext3DInProcessImpl::createBuffer() { | |
1397 makeContextCurrent(); | |
1398 GLuint o; | |
1399 glGenBuffersARB(1, &o); | |
1400 return o; | |
1401 } | |
1402 | |
1403 WebGLId WebGraphicsContext3DInProcessImpl::createFramebuffer() { | |
1404 makeContextCurrent(); | |
1405 GLuint o = 0; | |
1406 glGenFramebuffersEXT(1, &o); | |
1407 return o; | |
1408 } | |
1409 | |
1410 WebGLId WebGraphicsContext3DInProcessImpl::createProgram() { | |
1411 makeContextCurrent(); | |
1412 return glCreateProgram(); | |
1413 } | |
1414 | |
1415 WebGLId WebGraphicsContext3DInProcessImpl::createRenderbuffer() { | |
1416 makeContextCurrent(); | |
1417 GLuint o; | |
1418 glGenRenderbuffersEXT(1, &o); | |
1419 return o; | |
1420 } | |
1421 | |
1422 WebGLId WebGraphicsContext3DInProcessImpl::createShader( | |
1423 WGC3Denum shaderType) { | |
1424 makeContextCurrent(); | |
1425 DCHECK(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER); | |
1426 GLuint shader = glCreateShader(shaderType); | |
1427 if (shader) { | |
1428 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1429 if (result != shader_source_map_.end()) { | |
1430 delete result->second; | |
1431 shader_source_map_.erase(result); | |
1432 } | |
1433 shader_source_map_.insert( | |
1434 ShaderSourceMap::value_type(shader, new ShaderSourceEntry(shaderType))); | |
1435 } | |
1436 | |
1437 return shader; | |
1438 } | |
1439 | |
1440 WebGLId WebGraphicsContext3DInProcessImpl::createTexture() { | |
1441 makeContextCurrent(); | |
1442 GLuint o; | |
1443 glGenTextures(1, &o); | |
1444 return o; | |
1445 } | |
1446 | |
1447 void WebGraphicsContext3DInProcessImpl::deleteBuffer(WebGLId buffer) { | |
1448 makeContextCurrent(); | |
1449 glDeleteBuffersARB(1, &buffer); | |
1450 } | |
1451 | |
1452 void WebGraphicsContext3DInProcessImpl::deleteFramebuffer( | |
1453 WebGLId framebuffer) { | |
1454 makeContextCurrent(); | |
1455 glDeleteFramebuffersEXT(1, &framebuffer); | |
1456 } | |
1457 | |
1458 void WebGraphicsContext3DInProcessImpl::deleteProgram(WebGLId program) { | |
1459 makeContextCurrent(); | |
1460 glDeleteProgram(program); | |
1461 } | |
1462 | |
1463 void WebGraphicsContext3DInProcessImpl::deleteRenderbuffer( | |
1464 WebGLId renderbuffer) { | |
1465 makeContextCurrent(); | |
1466 glDeleteRenderbuffersEXT(1, &renderbuffer); | |
1467 } | |
1468 | |
1469 void WebGraphicsContext3DInProcessImpl::deleteShader(WebGLId shader) { | |
1470 makeContextCurrent(); | |
1471 | |
1472 ShaderSourceMap::iterator result = shader_source_map_.find(shader); | |
1473 if (result != shader_source_map_.end()) { | |
1474 delete result->second; | |
1475 shader_source_map_.erase(result); | |
1476 } | |
1477 glDeleteShader(shader); | |
1478 } | |
1479 | |
1480 void WebGraphicsContext3DInProcessImpl::deleteTexture(WebGLId texture) { | |
1481 makeContextCurrent(); | |
1482 glDeleteTextures(1, &texture); | |
1483 } | |
1484 | |
1485 bool WebGraphicsContext3DInProcessImpl::AngleCreateCompilers() { | |
1486 if (!ShInitialize()) | |
1487 return false; | |
1488 | |
1489 ShBuiltInResources resources; | |
1490 ShInitBuiltInResources(&resources); | |
1491 getIntegerv(GL_MAX_VERTEX_ATTRIBS, &resources.MaxVertexAttribs); | |
1492 getIntegerv(MAX_VERTEX_UNIFORM_VECTORS, &resources.MaxVertexUniformVectors); | |
1493 getIntegerv(MAX_VARYING_VECTORS, &resources.MaxVaryingVectors); | |
1494 getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, | |
1495 &resources.MaxVertexTextureImageUnits); | |
1496 getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, | |
1497 &resources.MaxCombinedTextureImageUnits); | |
1498 getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &resources.MaxTextureImageUnits); | |
1499 getIntegerv(MAX_FRAGMENT_UNIFORM_VECTORS, | |
1500 &resources.MaxFragmentUniformVectors); | |
1501 // Always set to 1 for OpenGL ES. | |
1502 resources.MaxDrawBuffers = 1; | |
1503 | |
1504 fragment_compiler_ = ShConstructCompiler( | |
1505 SH_FRAGMENT_SHADER, SH_WEBGL_SPEC, &resources); | |
1506 vertex_compiler_ = ShConstructCompiler( | |
1507 SH_VERTEX_SHADER, SH_WEBGL_SPEC, &resources); | |
1508 return (fragment_compiler_ && vertex_compiler_); | |
1509 } | |
1510 | |
1511 void WebGraphicsContext3DInProcessImpl::AngleDestroyCompilers() { | |
1512 if (fragment_compiler_) { | |
1513 ShDestruct(fragment_compiler_); | |
1514 fragment_compiler_ = 0; | |
1515 } | |
1516 if (vertex_compiler_) { | |
1517 ShDestruct(vertex_compiler_); | |
1518 vertex_compiler_ = 0; | |
1519 } | |
1520 } | |
1521 | |
1522 bool WebGraphicsContext3DInProcessImpl::AngleValidateShaderSource( | |
1523 ShaderSourceEntry* entry) { | |
1524 entry->is_valid = false; | |
1525 entry->translated_source.reset(); | |
1526 entry->log.reset(); | |
1527 | |
1528 ShHandle compiler = 0; | |
1529 switch (entry->type) { | |
1530 case GL_FRAGMENT_SHADER: | |
1531 compiler = fragment_compiler_; | |
1532 break; | |
1533 case GL_VERTEX_SHADER: | |
1534 compiler = vertex_compiler_; | |
1535 break; | |
1536 } | |
1537 if (!compiler) | |
1538 return false; | |
1539 | |
1540 char* source = entry->source.get(); | |
1541 if (!ShCompile(compiler, &source, 1, SH_OBJECT_CODE)) { | |
1542 int logSize = 0; | |
1543 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &logSize); | |
1544 if (logSize > 1) { | |
1545 entry->log.reset(new char[logSize]); | |
1546 ShGetInfoLog(compiler, entry->log.get()); | |
1547 } | |
1548 return false; | |
1549 } | |
1550 | |
1551 int length = 0; | |
1552 if (is_gles2_) { | |
1553 // ANGLE does not yet have a GLSL ES backend. Therefore if the | |
1554 // compile succeeds we send the original source down. | |
1555 length = strlen(entry->source.get()); | |
1556 if (length > 0) | |
1557 ++length; // Add null terminator | |
1558 } else { | |
1559 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &length); | |
1560 } | |
1561 if (length > 1) { | |
1562 entry->translated_source.reset(new char[length]); | |
1563 if (is_gles2_) | |
1564 strncpy(entry->translated_source.get(), entry->source.get(), length); | |
1565 else | |
1566 ShGetObjectCode(compiler, entry->translated_source.get()); | |
1567 } | |
1568 entry->is_valid = true; | |
1569 return true; | |
1570 } | |
1571 | |
1572 #else // USE_WGC3D_TYPES | |
1573 | |
33 WebGraphicsContext3DInProcessImpl:: | 1574 WebGraphicsContext3DInProcessImpl:: |
34 VertexAttribPointerState::VertexAttribPointerState() | 1575 VertexAttribPointerState::VertexAttribPointerState() |
35 : enabled(false), | 1576 : enabled(false), |
36 buffer(0), | 1577 buffer(0), |
37 indx(0), | 1578 indx(0), |
38 size(0), | 1579 size(0), |
39 type(0), | 1580 type(0), |
40 normalized(false), | 1581 normalized(false), |
41 stride(0), | 1582 stride(0), |
42 offset(0) { | 1583 offset(0) { |
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1303 | 2844 |
1304 void WebGraphicsContext3DInProcessImpl::releaseShaderCompiler() { | 2845 void WebGraphicsContext3DInProcessImpl::releaseShaderCompiler() { |
1305 } | 2846 } |
1306 | 2847 |
1307 void WebGraphicsContext3DInProcessImpl::renderbufferStorage( | 2848 void WebGraphicsContext3DInProcessImpl::renderbufferStorage( |
1308 unsigned long target, | 2849 unsigned long target, |
1309 unsigned long internalformat, | 2850 unsigned long internalformat, |
1310 unsigned long width, | 2851 unsigned long width, |
1311 unsigned long height) { | 2852 unsigned long height) { |
1312 makeContextCurrent(); | 2853 makeContextCurrent(); |
1313 if (!is_gles2_) { | 2854 switch (internalformat) { |
1314 switch (internalformat) { | 2855 case GL_DEPTH_STENCIL: |
1315 case GL_DEPTH_STENCIL: | 2856 internalformat = GL_DEPTH24_STENCIL8_EXT; |
1316 internalformat = GL_DEPTH24_STENCIL8_EXT; | 2857 break; |
1317 break; | 2858 case GL_DEPTH_COMPONENT16: |
1318 case GL_DEPTH_COMPONENT16: | 2859 internalformat = GL_DEPTH_COMPONENT; |
1319 internalformat = GL_DEPTH_COMPONENT; | 2860 break; |
1320 break; | 2861 case GL_RGBA4: |
1321 case GL_RGBA4: | 2862 case GL_RGB5_A1: |
1322 case GL_RGB5_A1: | 2863 internalformat = GL_RGBA; |
1323 internalformat = GL_RGBA; | 2864 break; |
1324 break; | 2865 case 0x8D62: // GL_RGB565 |
1325 case 0x8D62: // GL_RGB565 | 2866 internalformat = GL_RGB; |
1326 internalformat = GL_RGB; | 2867 break; |
Ken Russell (switch to Gerrit)
2011/01/26 23:58:02
Looks like you need to sync to TOT.
| |
1327 break; | |
1328 } | |
1329 } | 2868 } |
1330 glRenderbufferStorageEXT(target, internalformat, width, height); | 2869 glRenderbufferStorageEXT(target, internalformat, width, height); |
1331 } | 2870 } |
1332 | 2871 |
1333 DELEGATE_TO_GL_2_C1(sampleCoverage, SampleCoverage, double, bool) | 2872 DELEGATE_TO_GL_2_C1(sampleCoverage, SampleCoverage, double, bool) |
1334 | 2873 |
1335 DELEGATE_TO_GL_4(scissor, Scissor, long, long, unsigned long, unsigned long) | 2874 DELEGATE_TO_GL_4(scissor, Scissor, long, long, unsigned long, unsigned long) |
1336 | 2875 |
1337 void WebGraphicsContext3DInProcessImpl::texImage2D( | 2876 void WebGraphicsContext3DInProcessImpl::texImage2D( |
1338 unsigned target, unsigned level, unsigned internalFormat, | 2877 unsigned target, unsigned level, unsigned internalFormat, |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1646 entry->translated_source.reset(new char[length]); | 3185 entry->translated_source.reset(new char[length]); |
1647 if (is_gles2_) | 3186 if (is_gles2_) |
1648 strncpy(entry->translated_source.get(), entry->source.get(), length); | 3187 strncpy(entry->translated_source.get(), entry->source.get(), length); |
1649 else | 3188 else |
1650 ShGetObjectCode(compiler, entry->translated_source.get()); | 3189 ShGetObjectCode(compiler, entry->translated_source.get()); |
1651 } | 3190 } |
1652 entry->is_valid = true; | 3191 entry->is_valid = true; |
1653 return true; | 3192 return true; |
1654 } | 3193 } |
1655 | 3194 |
3195 #endif // USE_WGC3D_TYPES | |
3196 | |
1656 } // namespace gpu | 3197 } // namespace gpu |
1657 } // namespace webkit | 3198 } // namespace webkit |
1658 | 3199 |
OLD | NEW |