Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1199)

Side by Side Diff: webkit/gpu/webgraphicscontext3d_in_process_impl.cc

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

Powered by Google App Engine
This is Rietveld 408576698