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