1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32
33 #if ENABLE(3D_CANVAS)
34
35 #include "GraphicsContext3D.h"
36
37 #include "CachedImage.h"
38 #include "CString.h"
39 #include "HTMLCanvasElement.h"
40 #include "HTMLImageElement.h"
41 #include "ImageBuffer.h"
42 #include "ImageData.h"
43 #include "NotImplemented.h"
44 #include "WebGLBuffer.h"
45 #include "WebGLByteArray.h"
46 #include "WebGLFloatArray.h"
47 #include "WebGLFramebuffer.h"
48 #include "WebGLIntArray.h"
49 #include "WebGLProgram.h"
50 #include "WebGLRenderbuffer.h"
51 #include "WebGLRenderingContext.h"
52 #include "WebGLShader.h"
53 #include "WebGLTexture.h"
54 #include "WebGLUnsignedByteArray.h"
55
56 #include <stdio.h>
57 #include <wtf/FastMalloc.h>
58
59 #if OS(WINDOWS)
60 #include <windows.h>
61 #endif
62
63 #include "GL/glew.h"
64
65 #if PLATFORM(CG)
66 #include "GraphicsContext.h"
67 #include <CoreGraphics/CGContext.h>
68 #include <CoreGraphics/CGBitmapContext.h>
69 #include <CoreGraphics/CGImage.h>
70 #include <OpenGL/OpenGL.h>
71 #else
72 #define FLIP_FRAMEBUFFER_VERTICALLY
73 #endif
74
75 #if PLATFORM(SKIA)
76 #include "NativeImageSkia.h"
77 #endif
78
79 #if OS(DARWIN)
80 #define USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER
81 #endif
82
83 #if OS(LINUX)
84 #include <dlfcn.h>
85 #include "GL/glxew.h"
86 #endif
87
88 using namespace std;
89
90 namespace WebCore {
91
92 // GraphicsContext3DInternal -----------------------------------------------------
93
94 // Uncomment this to render to a separate window for debugging
95 // #define RENDER_TO_DEBUGGING_WINDOW
96
97 #define EXTRACT(val) (!val ? 0 : val->object())
98
99 class GraphicsContext3DInternal {
100 public:
101 GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs);
102 ~GraphicsContext3DInternal();
103
104 bool makeContextCurrent();
105
106 PlatformGraphicsContext3D platformGraphicsContext3D() const;
107 Platform3DObject platformTexture() const;
108
109 void reshape(int width, int height);
110
111 void beginPaint(WebGLRenderingContext* context);
112
113 bool validateTextureTarget(int target);
114 bool validateTextureParameter(int param);
115
116 void activeTexture(unsigned long texture);
117 void bindBuffer(unsigned long target,
118 WebGLBuffer* buffer);
119 void bindFramebuffer(unsigned long target,
120 WebGLFramebuffer* framebuffer);
121 void bindTexture(unsigned long target,
122 WebGLTexture* texture);
123 void bufferDataImpl(unsigned long target, int size, const void* data, unsigned long usage);
124 void disableVertexAttribArray(unsigned long index);
125 void enableVertexAttribArray(unsigned long index);
126 unsigned long getError();
127 GraphicsContext3D::Attributes getContextAttributes();
128 void vertexAttribPointer(unsigned long indx, int size, int type, bool normalized,
129 unsigned long stride, unsigned long offset);
130 void viewportImpl(long x, long y, unsigned long width, unsigned long height);
131
132 void synthesizeGLError(unsigned long error);
133
134 private:
135 GraphicsContext3D::Attributes m_attrs;
136
137 unsigned int m_texture;
138 unsigned int m_fbo;
139 unsigned int m_depthBuffer;
140 unsigned int m_cachedWidth, m_cachedHeight;
141
142 // For tracking which FBO is bound
143 unsigned int m_boundFBO;
144
145 #ifdef FLIP_FRAMEBUFFER_VERTICALLY
146 unsigned char* m_scanline;
147 void flipVertically(unsigned char* framebuffer,
148 unsigned int width,
149 unsigned int height);
150 #endif
151
152 // Note: we aren't currently using this information, but we will
153 // need to in order to verify that all enabled vertex arrays have
154 // a valid buffer bound -- to avoid crashes on certain cards.
155 unsigned int m_boundArrayBuffer;
156 class VertexAttribPointerState {
157 public:
158 VertexAttribPointerState();
159
160 bool enabled;
161 unsigned long buffer;
162 unsigned long indx;
163 int size;
164 int type;
165 bool normalized;
166 unsigned long stride;
167 unsigned long offset;
168 };
169
170 enum {
171 NumTrackedPointerStates = 2
172 };
173 VertexAttribPointerState m_vertexAttribPointerState[NumTrackedPointerStates];
174
175 // Errors raised by synthesizeGLError().
176 ListHashSet<unsigned long> m_syntheticErrors;
177
178 #if PLATFORM(SKIA)
179 // If the width and height of the Canvas's backing store don't
180 // match those that we were given in the most recent call to
181 // reshape(), then we need an intermediate bitmap to read back the
182 // frame buffer into. This seems to happen when CSS styles are
183 // used to resize the Canvas.
184 SkBitmap* m_resizingBitmap;
185 #endif
186
187 static bool s_initializedGLEW;
188 #if OS(WINDOWS)
189 HWND m_canvasWindow;
190 HDC m_canvasDC;
191 HGLRC m_contextObj;
192 #elif PLATFORM(CG)
193 CGLPBufferObj m_pbuffer;
194 CGLContextObj m_contextObj;
195 unsigned char* m_renderOutput;
196 #elif OS(LINUX)
197 GLXContext m_contextObj;
198 GLXPbuffer m_pbuffer;
199
200 // In order to avoid problems caused by linking against libGL, we
201 // dynamically look up all the symbols we need.
202 // http://code.google.com/p/chromium/issues/detail?id=16800
203 class GLConnection {
204 public:
205 ~GLConnection();
206
207 static GLConnection* create();
208
chooseFBConfig(int screen,const int * attrib_list,int * nelements)209 GLXFBConfig* chooseFBConfig(int screen, const int *attrib_list, int *nelements)
210 {
211 return m_glXChooseFBConfig(m_display, screen, attrib_list, nelements);
212 }
213
createNewContext(GLXFBConfig config,int renderType,GLXContext shareList,Bool direct)214 GLXContext createNewContext(GLXFBConfig config, int renderType, GLXContext shareList, Bool direct)
215 {
216 return m_glXCreateNewContext(m_display, config, renderType, shareList, direct);
217 }
218
createPbuffer(GLXFBConfig config,const int * attribList)219 GLXPbuffer createPbuffer(GLXFBConfig config, const int *attribList)
220 {
221 return m_glXCreatePbuffer(m_display, config, attribList);
222 }
223
destroyPbuffer(GLXPbuffer pbuf)224 void destroyPbuffer(GLXPbuffer pbuf)
225 {
226 m_glXDestroyPbuffer(m_display, pbuf);
227 }
228
makeCurrent(GLXDrawable drawable,GLXContext ctx)229 Bool makeCurrent(GLXDrawable drawable, GLXContext ctx)
230 {
231 return m_glXMakeCurrent(m_display, drawable, ctx);
232 }
233
destroyContext(GLXContext ctx)234 void destroyContext(GLXContext ctx)
235 {
236 m_glXDestroyContext(m_display, ctx);
237 }
238
getCurrentContext()239 GLXContext getCurrentContext()
240 {
241 return m_glXGetCurrentContext();
242 }
243
244 private:
245 Display* m_display;
246 void* m_libGL;
247 PFNGLXCHOOSEFBCONFIGPROC m_glXChooseFBConfig;
248 PFNGLXCREATENEWCONTEXTPROC m_glXCreateNewContext;
249 PFNGLXCREATEPBUFFERPROC m_glXCreatePbuffer;
250 PFNGLXDESTROYPBUFFERPROC m_glXDestroyPbuffer;
251 typedef Bool (* PFNGLXMAKECURRENTPROC)(Display* dpy, GLXDrawable drawable, GLXContext ctx);
252 PFNGLXMAKECURRENTPROC m_glXMakeCurrent;
253 typedef void (* PFNGLXDESTROYCONTEXTPROC)(Display* dpy, GLXContext ctx);
254 PFNGLXDESTROYCONTEXTPROC m_glXDestroyContext;
255 typedef GLXContext (* PFNGLXGETCURRENTCONTEXTPROC)(void);
256 PFNGLXGETCURRENTCONTEXTPROC m_glXGetCurrentContext;
257
GLConnection(Display * display,void * libGL,PFNGLXCHOOSEFBCONFIGPROC chooseFBConfig,PFNGLXCREATENEWCONTEXTPROC createNewContext,PFNGLXCREATEPBUFFERPROC createPbuffer,PFNGLXDESTROYPBUFFERPROC destroyPbuffer,PFNGLXMAKECURRENTPROC makeCurrent,PFNGLXDESTROYCONTEXTPROC destroyContext,PFNGLXGETCURRENTCONTEXTPROC getCurrentContext)258 GLConnection(Display* display,
259 void* libGL,
260 PFNGLXCHOOSEFBCONFIGPROC chooseFBConfig,
261 PFNGLXCREATENEWCONTEXTPROC createNewContext,
262 PFNGLXCREATEPBUFFERPROC createPbuffer,
263 PFNGLXDESTROYPBUFFERPROC destroyPbuffer,
264 PFNGLXMAKECURRENTPROC makeCurrent,
265 PFNGLXDESTROYCONTEXTPROC destroyContext,
266 PFNGLXGETCURRENTCONTEXTPROC getCurrentContext)
267 : m_libGL(libGL)
268 , m_display(display)
269 , m_glXChooseFBConfig(chooseFBConfig)
270 , m_glXCreateNewContext(createNewContext)
271 , m_glXCreatePbuffer(createPbuffer)
272 , m_glXDestroyPbuffer(destroyPbuffer)
273 , m_glXMakeCurrent(makeCurrent)
274 , m_glXDestroyContext(destroyContext)
275 , m_glXGetCurrentContext(getCurrentContext)
276 {
277 }
278 };
279
280 static GLConnection* s_gl;
281 #else
282 #error Must port GraphicsContext3D to your platform
283 #endif
284 };
285
286 bool GraphicsContext3DInternal::s_initializedGLEW = false;
287
288 #if OS(LINUX)
289 GraphicsContext3DInternal::GLConnection* GraphicsContext3DInternal::s_gl = 0;
290
create()291 GraphicsContext3DInternal::GLConnection* GraphicsContext3DInternal::GLConnection::create()
292 {
293 Display* dpy = XOpenDisplay(0);
294 if (!dpy) {
295 printf("GraphicsContext3D: error opening X display\n");
296 return 0;
297 }
298
299 // We use RTLD_GLOBAL semantics so that GLEW initialization works;
300 // GLEW expects to be able to open the current process's handle
301 // and do dlsym's of GL entry points from there.
302 void* libGL = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
303 if (!libGL) {
304 XCloseDisplay(dpy);
305 printf("GraphicsContext3D: error opening libGL.so.1: %s\n", dlerror());
306 return 0;
307 }
308
309 PFNGLXCHOOSEFBCONFIGPROC chooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) dlsym(libGL, "glXChooseFBConfig");
310 PFNGLXCREATENEWCONTEXTPROC createNewContext = (PFNGLXCREATENEWCONTEXTPROC) dlsym(libGL, "glXCreateNewContext");
311 PFNGLXCREATEPBUFFERPROC createPbuffer = (PFNGLXCREATEPBUFFERPROC) dlsym(libGL, "glXCreatePbuffer");
312 PFNGLXDESTROYPBUFFERPROC destroyPbuffer = (PFNGLXDESTROYPBUFFERPROC) dlsym(libGL, "glXDestroyPbuffer");
313 PFNGLXMAKECURRENTPROC makeCurrent = (PFNGLXMAKECURRENTPROC) dlsym(libGL, "glXMakeCurrent");
314 PFNGLXDESTROYCONTEXTPROC destroyContext = (PFNGLXDESTROYCONTEXTPROC) dlsym(libGL, "glXDestroyContext");
315 PFNGLXGETCURRENTCONTEXTPROC getCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC) dlsym(libGL, "glXGetCurrentContext");
316 if (!chooseFBConfig || !createNewContext || !createPbuffer
317 || !destroyPbuffer || !makeCurrent || !destroyContext
318 || !getCurrentContext) {
319 XCloseDisplay(dpy);
320 dlclose(libGL);
321 printf("GraphicsContext3D: error looking up bootstrapping entry points\n");
322 return 0;
323 }
324 return new GLConnection(dpy,
325 libGL,
326 chooseFBConfig,
327 createNewContext,
328 createPbuffer,
329 destroyPbuffer,
330 makeCurrent,
331 destroyContext,
332 getCurrentContext);
333 }
334
~GLConnection()335 GraphicsContext3DInternal::GLConnection::~GLConnection()
336 {
337 XCloseDisplay(m_display);
338 dlclose(m_libGL);
339 }
340
341 #endif // OS(LINUX)
342
VertexAttribPointerState()343 GraphicsContext3DInternal::VertexAttribPointerState::VertexAttribPointerState()
344 : enabled(false)
345 , buffer(0)
346 , indx(0)
347 , size(0)
348 , type(0)
349 , normalized(false)
350 , stride(0)
351 , offset(0)
352 {
353 }
354
GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs)355 GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs)
356 : m_attrs(attrs)
357 , m_texture(0)
358 , m_fbo(0)
359 , m_depthBuffer(0)
360 , m_boundFBO(0)
361 #ifdef FLIP_FRAMEBUFFER_VERTICALLY
362 , m_scanline(0)
363 #endif
364 , m_boundArrayBuffer(0)
365 #if PLATFORM(SKIA)
366 , m_resizingBitmap(0)
367 #endif
368 #if OS(WINDOWS)
369 , m_canvasWindow(0)
370 , m_canvasDC(0)
371 , m_contextObj(0)
372 #elif PLATFORM(CG)
373 , m_pbuffer(0)
374 , m_contextObj(0)
375 , m_renderOutput(0)
376 #elif OS(LINUX)
377 , m_contextObj(0)
378 , m_pbuffer(0)
379 #else
380 #error Must port to your platform
381 #endif
382 {
383 // FIXME: we need to take into account the user's requested
384 // context creation attributes, in particular stencil and
385 // antialias, and determine which could and could not be honored
386 // based on the capabilities of the OpenGL implementation.
387 m_attrs.alpha = true;
388 m_attrs.depth = true;
389 m_attrs.stencil = false;
390 m_attrs.antialias = false;
391 m_attrs.premultipliedAlpha = true;
392
393 #if OS(WINDOWS)
394 WNDCLASS wc;
395 if (!GetClassInfo(GetModuleHandle(0), L"CANVASGL", &wc)) {
396 ZeroMemory(&wc, sizeof(WNDCLASS));
397 wc.style = CS_OWNDC;
398 wc.hInstance = GetModuleHandle(0);
399 wc.lpfnWndProc = DefWindowProc;
400 wc.lpszClassName = L"CANVASGL";
401
402 if (!RegisterClass(&wc)) {
403 printf("GraphicsContext3D: RegisterClass failed\n");
404 return;
405 }
406 }
407
408 m_canvasWindow = CreateWindow(L"CANVASGL", L"CANVASGL",
409 WS_CAPTION,
410 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
411 CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
412 if (!m_canvasWindow) {
413 printf("GraphicsContext3DInternal: CreateWindow failed\n");
414 return;
415 }
416
417 // get the device context
418 m_canvasDC = GetDC(m_canvasWindow);
419 if (!m_canvasDC) {
420 printf("GraphicsContext3DInternal: GetDC failed\n");
421 return;
422 }
423
424 // find default pixel format
425 PIXELFORMATDESCRIPTOR pfd;
426 ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
427 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
428 pfd.nVersion = 1;
429 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL
430 #ifdef RENDER_TO_DEBUGGING_WINDOW
431 | PFD_DOUBLEBUFFER
432 #endif // RENDER_TO_DEBUGGING_WINDOW
433 ;
434 int pixelformat = ChoosePixelFormat(m_canvasDC, &pfd);
435
436 // set the pixel format for the dc
437 if (!SetPixelFormat(m_canvasDC, pixelformat, &pfd)) {
438 printf("GraphicsContext3D: SetPixelFormat failed\n");
439 return;
440 }
441
442 // create rendering context
443 m_contextObj = wglCreateContext(m_canvasDC);
444 if (!m_contextObj) {
445 printf("GraphicsContext3D: wglCreateContext failed\n");
446 return;
447 }
448
449 if (!wglMakeCurrent(m_canvasDC, m_contextObj)) {
450 printf("GraphicsContext3D: wglMakeCurrent failed\n");
451 return;
452 }
453
454 #ifdef RENDER_TO_DEBUGGING_WINDOW
455 typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
456 PFNWGLSWAPINTERVALEXTPROC setSwapInterval = 0;
457 setSwapInterval = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT");
458 if (setSwapInterval)
459 setSwapInterval(1);
460 #endif // RENDER_TO_DEBUGGING_WINDOW
461
462 #elif PLATFORM(CG)
463 // Create a 1x1 pbuffer and associated context to bootstrap things
464 CGLPixelFormatAttribute attribs[] = {
465 (CGLPixelFormatAttribute) kCGLPFAPBuffer,
466 (CGLPixelFormatAttribute) 0
467 };
468 CGLPixelFormatObj pixelFormat;
469 GLint numPixelFormats;
470 if (CGLChoosePixelFormat(attribs, &pixelFormat, &numPixelFormats) != kCGLNoError) {
471 printf("GraphicsContext3D: error choosing pixel format\n");
472 return;
473 }
474 if (!pixelFormat) {
475 printf("GraphicsContext3D: no pixel format selected\n");
476 return;
477 }
478 CGLContextObj context;
479 CGLError res = CGLCreateContext(pixelFormat, 0, &context);
480 CGLDestroyPixelFormat(pixelFormat);
481 if (res != kCGLNoError) {
482 printf("GraphicsContext3D: error creating context\n");
483 return;
484 }
485 CGLPBufferObj pbuffer;
486 if (CGLCreatePBuffer(1, 1, GL_TEXTURE_2D, GL_RGBA, 0, &pbuffer) != kCGLNoError) {
487 CGLDestroyContext(context);
488 printf("GraphicsContext3D: error creating pbuffer\n");
489 return;
490 }
491 if (CGLSetPBuffer(context, pbuffer, 0, 0, 0) != kCGLNoError) {
492 CGLDestroyContext(context);
493 CGLDestroyPBuffer(pbuffer);
494 printf("GraphicsContext3D: error attaching pbuffer to context\n");
495 return;
496 }
497 if (CGLSetCurrentContext(context) != kCGLNoError) {
498 CGLDestroyContext(context);
499 CGLDestroyPBuffer(pbuffer);
500 printf("GraphicsContext3D: error making context current\n");
501 return;
502 }
503 m_pbuffer = pbuffer;
504 m_contextObj = context;
505 #elif OS(LINUX)
506 if (!s_gl) {
507 s_gl = GLConnection::create();
508 if (!s_gl)
509 return;
510 }
511
512 int configAttrs[] = {
513 GLX_DRAWABLE_TYPE,
514 GLX_PBUFFER_BIT,
515 GLX_RENDER_TYPE,
516 GLX_RGBA_BIT,
517 GLX_DOUBLEBUFFER,
518 0,
519 0
520 };
521 int nelements = 0;
522 GLXFBConfig* config = s_gl->chooseFBConfig(0, configAttrs, &nelements);
523 if (!config) {
524 printf("GraphicsContext3D: glXChooseFBConfig failed\n");
525 return;
526 }
527 if (!nelements) {
528 printf("GraphicsContext3D: glXChooseFBConfig returned 0 elements\n");
529 XFree(config);
530 return;
531 }
532 GLXContext context = s_gl->createNewContext(config[0], GLX_RGBA_TYPE, 0, True);
533 if (!context) {
534 printf("GraphicsContext3D: glXCreateNewContext failed\n");
535 XFree(config);
536 return;
537 }
538 int pbufferAttrs[] = {
539 GLX_PBUFFER_WIDTH,
540 1,
541 GLX_PBUFFER_HEIGHT,
542 1,
543 0
544 };
545 GLXPbuffer pbuffer = s_gl->createPbuffer(config[0], pbufferAttrs);
546 XFree(config);
547 if (!pbuffer) {
548 printf("GraphicsContext3D: glxCreatePbuffer failed\n");
549 return;
550 }
551 if (!s_gl->makeCurrent(pbuffer, context)) {
552 printf("GraphicsContext3D: glXMakeCurrent failed\n");
553 return;
554 }
555 m_contextObj = context;
556 m_pbuffer = pbuffer;
557 #else
558 #error Must port to your platform
559 #endif
560
561 if (!s_initializedGLEW) {
562 // Initialize GLEW and check for GL 2.0 support by the drivers.
563 GLenum glewInitResult = glewInit();
564 if (glewInitResult != GLEW_OK) {
565 printf("GraphicsContext3D: GLEW initialization failed\n");
566 return;
567 }
568 if (!glewIsSupported("GL_VERSION_2_0")) {
569 printf("GraphicsContext3D: OpenGL 2.0 not supported\n");
570 return;
571 }
572 s_initializedGLEW = true;
573 }
574 }
575
~GraphicsContext3DInternal()576 GraphicsContext3DInternal::~GraphicsContext3DInternal()
577 {
578 makeContextCurrent();
579 #ifndef RENDER_TO_DEBUGGING_WINDOW
580 glDeleteRenderbuffersEXT(1, &m_depthBuffer);
581 glDeleteTextures(1, &m_texture);
582 #ifdef FLIP_FRAMEBUFFER_VERTICALLY
583 if (m_scanline)
584 delete[] m_scanline;
585 #endif
586 glDeleteFramebuffersEXT(1, &m_fbo);
587 #endif // !RENDER_TO_DEBUGGING_WINDOW
588 #if PLATFORM(SKIA)
589 if (m_resizingBitmap)
590 delete m_resizingBitmap;
591 #endif
592 #if OS(WINDOWS)
593 wglMakeCurrent(0, 0);
594 wglDeleteContext(m_contextObj);
595 ReleaseDC(m_canvasWindow, m_canvasDC);
596 DestroyWindow(m_canvasWindow);
597 #elif PLATFORM(CG)
598 CGLSetCurrentContext(0);
599 CGLDestroyContext(m_contextObj);
600 CGLDestroyPBuffer(m_pbuffer);
601 if (m_renderOutput)
602 delete[] m_renderOutput;
603 #elif OS(LINUX)
604 s_gl->makeCurrent(0, 0);
605 s_gl->destroyContext(m_contextObj);
606 s_gl->destroyPbuffer(m_pbuffer);
607 #else
608 #error Must port to your platform
609 #endif
610 m_contextObj = 0;
611 }
612
makeContextCurrent()613 bool GraphicsContext3DInternal::makeContextCurrent()
614 {
615 #if OS(WINDOWS)
616 if (wglGetCurrentContext() != m_contextObj)
617 if (wglMakeCurrent(m_canvasDC, m_contextObj))
618 return true;
619 #elif PLATFORM(CG)
620 if (CGLGetCurrentContext() != m_contextObj)
621 if (CGLSetCurrentContext(m_contextObj) == kCGLNoError)
622 return true;
623 #elif OS(LINUX)
624 if (s_gl->getCurrentContext() != m_contextObj)
625 if (s_gl->makeCurrent(m_pbuffer, m_contextObj))
626 return true;
627 #else
628 #error Must port to your platform
629 #endif
630 return false;
631 }
632
platformGraphicsContext3D() const633 PlatformGraphicsContext3D GraphicsContext3DInternal::platformGraphicsContext3D() const
634 {
635 return m_contextObj;
636 }
637
platformTexture() const638 Platform3DObject GraphicsContext3DInternal::platformTexture() const
639 {
640 return m_texture;
641 }
642
createTextureObject(GLenum target)643 static int createTextureObject(GLenum target)
644 {
645 GLuint texture = 0;
646 glGenTextures(1, &texture);
647 glBindTexture(target, texture);
648 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
649 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
650 return texture;
651 }
652
reshape(int width,int height)653 void GraphicsContext3DInternal::reshape(int width, int height)
654 {
655 #ifdef RENDER_TO_DEBUGGING_WINDOW
656 SetWindowPos(m_canvasWindow, HWND_TOP, 0, 0, width, height,
657 SWP_NOMOVE);
658 ShowWindow(m_canvasWindow, SW_SHOW);
659 #endif
660
661 m_cachedWidth = width;
662 m_cachedHeight = height;
663 makeContextCurrent();
664
665 #ifndef RENDER_TO_DEBUGGING_WINDOW
666 #ifdef USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER
667 // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on Mac OS X
668 GLenum target = GL_TEXTURE_RECTANGLE_ARB;
669 #else
670 GLenum target = GL_TEXTURE_2D;
671 #endif
672 if (!m_texture) {
673 // Generate the texture object
674 m_texture = createTextureObject(target);
675 // Generate the framebuffer object
676 glGenFramebuffersEXT(1, &m_fbo);
677 // Generate the depth buffer
678 glGenRenderbuffersEXT(1, &m_depthBuffer);
679 }
680
681 // Reallocate the color and depth buffers
682 glBindTexture(target, m_texture);
683 glTexImage2D(target, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
684 glBindTexture(target, 0);
685
686 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
687 m_boundFBO = m_fbo;
688 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
689 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
690 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
691
692 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, m_texture, 0);
693 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
694 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
695 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
696 printf("GraphicsContext3D: framebuffer was incomplete\n");
697
698 // FIXME: cleanup.
699 notImplemented();
700 }
701 #endif // RENDER_TO_DEBUGGING_WINDOW
702
703 #ifdef FLIP_FRAMEBUFFER_VERTICALLY
704 if (m_scanline) {
705 delete[] m_scanline;
706 m_scanline = 0;
707 }
708 m_scanline = new unsigned char[width * 4];
709 #endif // FLIP_FRAMEBUFFER_VERTICALLY
710
711 glClear(GL_COLOR_BUFFER_BIT);
712
713 #if PLATFORM(CG)
714 // Need to reallocate the client-side backing store.
715 // FIXME: make this more efficient.
716 if (m_renderOutput) {
717 delete[] m_renderOutput;
718 m_renderOutput = 0;
719 }
720 int rowBytes = width * 4;
721 m_renderOutput = new unsigned char[height * rowBytes];
722 #endif // PLATFORM(CG)
723 }
724
725 #ifdef FLIP_FRAMEBUFFER_VERTICALLY
flipVertically(unsigned char * framebuffer,unsigned int width,unsigned int height)726 void GraphicsContext3DInternal::flipVertically(unsigned char* framebuffer,
727 unsigned int width,
728 unsigned int height)
729 {
730 unsigned char* scanline = m_scanline;
731 if (!scanline)
732 return;
733 unsigned int rowBytes = width * 4;
734 unsigned int count = height / 2;
735 for (unsigned int i = 0; i < count; i++) {
736 unsigned char* rowA = framebuffer + i * rowBytes;
737 unsigned char* rowB = framebuffer + (height - i - 1) * rowBytes;
738 // FIXME: this is where the multiplication of the alpha
739 // channel into the color buffer will need to occur if the
740 // user specifies the "premultiplyAlpha" flag in the context
741 // creation attributes.
742 memcpy(scanline, rowB, rowBytes);
743 memcpy(rowB, rowA, rowBytes);
744 memcpy(rowA, scanline, rowBytes);
745 }
746 }
747 #endif
748
beginPaint(WebGLRenderingContext * context)749 void GraphicsContext3DInternal::beginPaint(WebGLRenderingContext* context)
750 {
751 makeContextCurrent();
752
753 #ifdef RENDER_TO_DEBUGGING_WINDOW
754 SwapBuffers(m_canvasDC);
755 #else
756 // Earlier versions of this code used the GPU to flip the
757 // framebuffer vertically before reading it back for compositing
758 // via software. This code was quite complicated, used a lot of
759 // GPU memory, and didn't provide an obvious speedup. Since this
760 // vertical flip is only a temporary solution anyway until Chrome
761 // is fully GPU composited, it wasn't worth the complexity.
762
763 HTMLCanvasElement* canvas = context->canvas();
764 ImageBuffer* imageBuffer = canvas->buffer();
765 unsigned char* pixels = 0;
766 bool mustRestoreFBO = (m_boundFBO != m_fbo);
767 if (mustRestoreFBO)
768 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
769 #if PLATFORM(SKIA)
770 const SkBitmap* canvasBitmap = imageBuffer->context()->platformContext()->bitmap();
771 const SkBitmap* readbackBitmap = 0;
772 ASSERT(canvasBitmap->config() == SkBitmap::kARGB_8888_Config);
773 if (canvasBitmap->width() == m_cachedWidth && canvasBitmap->height() == m_cachedHeight) {
774 // This is the fastest and most common case. We read back
775 // directly into the canvas's backing store.
776 readbackBitmap = canvasBitmap;
777 if (m_resizingBitmap) {
778 delete m_resizingBitmap;
779 m_resizingBitmap = 0;
780 }
781 } else {
782 // We need to allocate a temporary bitmap for reading back the
783 // pixel data. We will then use Skia to rescale this bitmap to
784 // the size of the canvas's backing store.
785 if (m_resizingBitmap && (m_resizingBitmap->width() != m_cachedWidth || m_resizingBitmap->height() != m_cachedHeight)) {
786 delete m_resizingBitmap;
787 m_resizingBitmap = 0;
788 }
789 if (!m_resizingBitmap) {
790 m_resizingBitmap = new SkBitmap();
791 m_resizingBitmap->setConfig(SkBitmap::kARGB_8888_Config,
792 m_cachedWidth,
793 m_cachedHeight);
794 if (!m_resizingBitmap->allocPixels()) {
795 delete m_resizingBitmap;
796 m_resizingBitmap = 0;
797 return;
798 }
799 }
800 readbackBitmap = m_resizingBitmap;
801 }
802
803 // Read back the frame buffer.
804 SkAutoLockPixels bitmapLock(*readbackBitmap);
805 pixels = static_cast<unsigned char*>(readbackBitmap->getPixels());
806 glReadPixels(0, 0, m_cachedWidth, m_cachedHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
807 #elif PLATFORM(CG)
808 if (m_renderOutput) {
809 pixels = m_renderOutput;
810 glReadPixels(0, 0, m_cachedWidth, m_cachedHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
811 }
812 #else
813 #error Must port to your platform
814 #endif
815
816 if (mustRestoreFBO)
817 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
818
819 #ifdef FLIP_FRAMEBUFFER_VERTICALLY
820 if (pixels)
821 flipVertically(pixels, m_cachedWidth, m_cachedHeight);
822 #endif
823
824 #if PLATFORM(SKIA)
825 if (m_resizingBitmap) {
826 // We need to draw the resizing bitmap into the canvas's backing store.
827 SkCanvas canvas(*canvasBitmap);
828 SkRect dst;
829 dst.set(0, 0, canvasBitmap->width(), canvasBitmap->height());
830 canvas.drawBitmapRect(*m_resizingBitmap, 0, dst);
831 }
832 #elif PLATFORM(CG)
833 if (m_renderOutput) {
834 int rowBytes = m_cachedWidth * 4;
835 CGDataProviderRef dataProvider = CGDataProviderCreateWithData(0, m_renderOutput, rowBytes * m_cachedHeight, 0);
836 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
837 CGImageRef cgImage = CGImageCreate(m_cachedWidth,
838 m_cachedHeight,
839 8,
840 32,
841 rowBytes,
842 colorSpace,
843 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
844 dataProvider,
845 0,
846 false,
847 kCGRenderingIntentDefault);
848 // CSS styling may cause the canvas's content to be resized on
849 // the page. Go back to the Canvas to figure out the correct
850 // width and height to draw.
851 CGRect rect = CGRectMake(0, 0,
852 context->canvas()->width(),
853 context->canvas()->height());
854 // We want to completely overwrite the previous frame's
855 // rendering results.
856 CGContextSetBlendMode(imageBuffer->context()->platformContext(),
857 kCGBlendModeCopy);
858 CGContextSetInterpolationQuality(imageBuffer->context()->platformContext(),
859 kCGInterpolationNone);
860 CGContextDrawImage(imageBuffer->context()->platformContext(),
861 rect, cgImage);
862 CGImageRelease(cgImage);
863 CGColorSpaceRelease(colorSpace);
864 CGDataProviderRelease(dataProvider);
865 }
866 #else
867 #error Must port to your platform
868 #endif
869
870 #endif // RENDER_TO_DEBUGGING_WINDOW
871 }
872
activeTexture(unsigned long texture)873 void GraphicsContext3DInternal::activeTexture(unsigned long texture)
874 {
875 // FIXME: query number of textures available.
876 if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32)
877 // FIXME: raise exception.
878 return;
879
880 makeContextCurrent();
881 glActiveTexture(texture);
882 }
883
bindBuffer(unsigned long target,WebGLBuffer * buffer)884 void GraphicsContext3DInternal::bindBuffer(unsigned long target,
885 WebGLBuffer* buffer)
886 {
887 makeContextCurrent();
888 GLuint bufID = EXTRACT(buffer);
889 if (target == GL_ARRAY_BUFFER)
890 m_boundArrayBuffer = bufID;
891 glBindBuffer(target, bufID);
892 }
893
bindFramebuffer(unsigned long target,WebGLFramebuffer * framebuffer)894 void GraphicsContext3DInternal::bindFramebuffer(unsigned long target,
895 WebGLFramebuffer* framebuffer)
896 {
897 makeContextCurrent();
898 GLuint id = EXTRACT(framebuffer);
899 if (!id)
900 id = m_fbo;
901 glBindFramebufferEXT(target, id);
902 m_boundFBO = id;
903 }
904
905 // If we didn't have to hack GL_TEXTURE_WRAP_R for cube maps,
906 // we could just use:
907 // GL_SAME_METHOD_2_X2(BindTexture, bindTexture, unsigned long, WebGLTexture*)
bindTexture(unsigned long target,WebGLTexture * texture)908 void GraphicsContext3DInternal::bindTexture(unsigned long target,
909 WebGLTexture* texture)
910 {
911 makeContextCurrent();
912 unsigned int textureObject = EXTRACT(texture);
913
914 glBindTexture(target, textureObject);
915
916 // FIXME: GL_TEXTURE_WRAP_R isn't exposed in the OpenGL ES 2.0
917 // API. On desktop OpenGL implementations it seems necessary to
918 // set this wrap mode to GL_CLAMP_TO_EDGE to get correct behavior
919 // of cube maps.
920 if (texture) {
921 if (target == GL_TEXTURE_CUBE_MAP) {
922 if (!texture->isCubeMapRWrapModeInitialized()) {
923 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
924 texture->setCubeMapRWrapModeInitialized(true);
925 }
926 } else
927 texture->setCubeMapRWrapModeInitialized(false);
928 }
929 }
930
bufferDataImpl(unsigned long target,int size,const void * data,unsigned long usage)931 void GraphicsContext3DInternal::bufferDataImpl(unsigned long target, int size, const void* data, unsigned long usage)
932 {
933 makeContextCurrent();
934 // FIXME: make this verification more efficient.
935 GLint binding = 0;
936 GLenum binding_target = GL_ARRAY_BUFFER_BINDING;
937 if (target == GL_ELEMENT_ARRAY_BUFFER)
938 binding_target = GL_ELEMENT_ARRAY_BUFFER_BINDING;
939 glGetIntegerv(binding_target, &binding);
940 if (binding <= 0) {
941 // FIXME: raise exception.
942 // LogMessagef(("bufferData: no buffer bound"));
943 return;
944 }
945
946 glBufferData(target,
947 size,
948 data,
949 usage);
950 }
951
disableVertexAttribArray(unsigned long index)952 void GraphicsContext3DInternal::disableVertexAttribArray(unsigned long index)
953 {
954 makeContextCurrent();
955 if (index < NumTrackedPointerStates)
956 m_vertexAttribPointerState[index].enabled = false;
957 glDisableVertexAttribArray(index);
958 }
959
enableVertexAttribArray(unsigned long index)960 void GraphicsContext3DInternal::enableVertexAttribArray(unsigned long index)
961 {
962 makeContextCurrent();
963 if (index < NumTrackedPointerStates)
964 m_vertexAttribPointerState[index].enabled = true;
965 glEnableVertexAttribArray(index);
966 }
967
getError()968 unsigned long GraphicsContext3DInternal::getError()
969 {
970 if (m_syntheticErrors.size() > 0) {
971 ListHashSet<unsigned long>::iterator iter = m_syntheticErrors.begin();
972 unsigned long err = *iter;
973 m_syntheticErrors.remove(iter);
974 return err;
975 }
976
977 makeContextCurrent();
978 return glGetError();
979 }
980
getContextAttributes()981 GraphicsContext3D::Attributes GraphicsContext3DInternal::getContextAttributes()
982 {
983 return m_attrs;
984 }
985
vertexAttribPointer(unsigned long indx,int size,int type,bool normalized,unsigned long stride,unsigned long offset)986 void GraphicsContext3DInternal::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized,
987 unsigned long stride, unsigned long offset)
988 {
989 makeContextCurrent();
990
991 if (m_boundArrayBuffer <= 0) {
992 // FIXME: raise exception.
993 // LogMessagef(("bufferData: no buffer bound"));
994 return;
995 }
996
997 if (indx < NumTrackedPointerStates) {
998 VertexAttribPointerState& state = m_vertexAttribPointerState[indx];
999 state.buffer = m_boundArrayBuffer;
1000 state.indx = indx;
1001 state.size = size;
1002 state.type = type;
1003 state.normalized = normalized;
1004 state.stride = stride;
1005 state.offset = offset;
1006 }
1007
1008 glVertexAttribPointer(indx, size, type, normalized, stride,
1009 reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
1010 }
1011
viewportImpl(long x,long y,unsigned long width,unsigned long height)1012 void GraphicsContext3DInternal::viewportImpl(long x, long y, unsigned long width, unsigned long height)
1013 {
1014 glViewport(x, y, width, height);
1015 }
1016
synthesizeGLError(unsigned long error)1017 void GraphicsContext3DInternal::synthesizeGLError(unsigned long error)
1018 {
1019 m_syntheticErrors.add(error);
1020 }
1021
1022 // GraphicsContext3D -----------------------------------------------------
1023
1024 /* Helper macros for when we're just wrapping a gl method, so that
1025 * we can avoid having to type this 500 times. Note that these MUST
1026 * NOT BE USED if we need to check any of the parameters.
1027 */
1028
1029 #define GL_SAME_METHOD_0(glname, name) \
1030 void GraphicsContext3D::name() \
1031 { \
1032 makeContextCurrent(); \
1033 gl##glname(); \
1034 }
1035
1036 #define GL_SAME_METHOD_1(glname, name, t1) \
1037 void GraphicsContext3D::name(t1 a1) \
1038 { \
1039 makeContextCurrent(); \
1040 gl##glname(a1); \
1041 }
1042
1043 #define GL_SAME_METHOD_1_X(glname, name, t1) \
1044 void GraphicsContext3D::name(t1 a1) \
1045 { \
1046 makeContextCurrent(); \
1047 gl##glname(EXTRACT(a1)); \
1048 }
1049
1050 #define GL_SAME_METHOD_2(glname, name, t1, t2) \
1051 void GraphicsContext3D::name(t1 a1, t2 a2) \
1052 { \
1053 makeContextCurrent(); \
1054 gl##glname(a1, a2); \
1055 }
1056
1057 #define GL_SAME_METHOD_2_X12(glname, name, t1, t2) \
1058 void GraphicsContext3D::name(t1 a1, t2 a2) \
1059 { \
1060 makeContextCurrent(); \
1061 gl##glname(EXTRACT(a1), EXTRACT(a2)); \
1062 }
1063
1064 #define GL_SAME_METHOD_2_X2(glname, name, t1, t2) \
1065 void GraphicsContext3D::name(t1 a1, t2 a2) \
1066 { \
1067 makeContextCurrent(); \
1068 gl##glname(a1, EXTRACT(a2)); \
1069 }
1070
1071 #define GL_SAME_METHOD_3(glname, name, t1, t2, t3) \
1072 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
1073 { \
1074 makeContextCurrent(); \
1075 gl##glname(a1, a2, a3); \
1076 }
1077
1078 #define GL_SAME_METHOD_3_X12(glname, name, t1, t2, t3) \
1079 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
1080 { \
1081 makeContextCurrent(); \
1082 gl##glname(EXTRACT(a1), EXTRACT(a2), a3); \
1083 }
1084
1085 #define GL_SAME_METHOD_3_X2(glname, name, t1, t2, t3) \
1086 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
1087 { \
1088 makeContextCurrent(); \
1089 gl##glname(a1, EXTRACT(a2), a3); \
1090 }
1091
1092 #define GL_SAME_METHOD_4(glname, name, t1, t2, t3, t4) \
1093 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
1094 { \
1095 makeContextCurrent(); \
1096 gl##glname(a1, a2, a3, a4); \
1097 }
1098
1099 #define GL_SAME_METHOD_4_X4(glname, name, t1, t2, t3, t4) \
1100 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
1101 { \
1102 makeContextCurrent(); \
1103 gl##glname(a1, a2, a3, EXTRACT(a4)); \
1104 }
1105
1106 #define GL_SAME_METHOD_5(glname, name, t1, t2, t3, t4, t5) \
1107 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
1108 { \
1109 makeContextCurrent(); \
1110 gl##glname(a1, a2, a3, a4, a5); \
1111 }
1112
1113 #define GL_SAME_METHOD_5_X4(glname, name, t1, t2, t3, t4, t5) \
1114 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
1115 { \
1116 makeContextCurrent(); \
1117 gl##glname(a1, a2, a3, EXTRACT(a4), a5); \
1118 }
1119
1120 #define GL_SAME_METHOD_6(glname, name, t1, t2, t3, t4, t5, t6) \
1121 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
1122 { \
1123 makeContextCurrent(); \
1124 gl##glname(a1, a2, a3, a4, a5, a6); \
1125 }
1126
1127 #define GL_SAME_METHOD_8(glname, name, t1, t2, t3, t4, t5, t6, t7, t8) \
1128 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \
1129 { \
1130 makeContextCurrent(); \
1131 gl##glname(a1, a2, a3, a4, a5, a6, a7, a8); \
1132 }
1133
create(GraphicsContext3D::Attributes attrs)1134 PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs)
1135 {
1136 PassOwnPtr<GraphicsContext3D> context = new GraphicsContext3D(attrs);
1137 // FIXME: add error checking
1138 return context;
1139 }
1140
GraphicsContext3D(GraphicsContext3D::Attributes attrs)1141 GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs)
1142 : m_currentWidth(0)
1143 , m_currentHeight(0)
1144 , m_internal(new GraphicsContext3DInternal(attrs))
1145 {
1146 }
1147
~GraphicsContext3D()1148 GraphicsContext3D::~GraphicsContext3D()
1149 {
1150 }
1151
platformGraphicsContext3D() const1152 PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() const
1153 {
1154 return m_internal->platformGraphicsContext3D();
1155 }
1156
platformTexture() const1157 Platform3DObject GraphicsContext3D::platformTexture() const
1158 {
1159 return m_internal->platformTexture();
1160 }
1161
makeContextCurrent()1162 void GraphicsContext3D::makeContextCurrent()
1163 {
1164 m_internal->makeContextCurrent();
1165 }
1166
reshape(int width,int height)1167 void GraphicsContext3D::reshape(int width, int height)
1168 {
1169 if (width == m_currentWidth && height == m_currentHeight)
1170 return;
1171
1172 m_currentWidth = width;
1173 m_currentHeight = height;
1174
1175 m_internal->reshape(width, height);
1176 }
1177
beginPaint(WebGLRenderingContext * context)1178 void GraphicsContext3D::beginPaint(WebGLRenderingContext* context)
1179 {
1180 m_internal->beginPaint(context);
1181 }
1182
endPaint()1183 void GraphicsContext3D::endPaint()
1184 {
1185 }
1186
sizeInBytes(int type)1187 int GraphicsContext3D::sizeInBytes(int type)
1188 {
1189 switch (type) {
1190 case GL_BYTE:
1191 return sizeof(GLbyte);
1192 case GL_UNSIGNED_BYTE:
1193 return sizeof(GLubyte);
1194 case GL_SHORT:
1195 return sizeof(GLshort);
1196 case GL_UNSIGNED_SHORT:
1197 return sizeof(GLushort);
1198 case GL_INT:
1199 return sizeof(GLint);
1200 case GL_UNSIGNED_INT:
1201 return sizeof(GLuint);
1202 case GL_FLOAT:
1203 return sizeof(GLfloat);
1204 default: // FIXME: default cases are discouraged in WebKit.
1205 return 0;
1206 }
1207 }
1208
createBuffer()1209 unsigned GraphicsContext3D::createBuffer()
1210 {
1211 makeContextCurrent();
1212 GLuint o;
1213 glGenBuffers(1, &o);
1214 return o;
1215 }
1216
createFramebuffer()1217 unsigned GraphicsContext3D::createFramebuffer()
1218 {
1219 makeContextCurrent();
1220 GLuint o = 0;
1221 glGenFramebuffersEXT(1, &o);
1222 return o;
1223 }
1224
createProgram()1225 unsigned GraphicsContext3D::createProgram()
1226 {
1227 makeContextCurrent();
1228 return glCreateProgram();
1229 }
1230
createRenderbuffer()1231 unsigned GraphicsContext3D::createRenderbuffer()
1232 {
1233 makeContextCurrent();
1234 GLuint o;
1235 glGenRenderbuffersEXT(1, &o);
1236 return o;
1237 }
1238
createShader(unsigned long type)1239 unsigned GraphicsContext3D::createShader(unsigned long type)
1240 {
1241 makeContextCurrent();
1242 return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
1243 }
1244
createTexture()1245 unsigned GraphicsContext3D::createTexture()
1246 {
1247 makeContextCurrent();
1248 GLuint o;
1249 glGenTextures(1, &o);
1250 return o;
1251 }
1252
deleteBuffer(unsigned buffer)1253 void GraphicsContext3D::deleteBuffer(unsigned buffer)
1254 {
1255 makeContextCurrent();
1256 glDeleteBuffers(1, &buffer);
1257 }
1258
deleteFramebuffer(unsigned framebuffer)1259 void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer)
1260 {
1261 makeContextCurrent();
1262 glDeleteFramebuffersEXT(1, &framebuffer);
1263 }
1264
deleteProgram(unsigned program)1265 void GraphicsContext3D::deleteProgram(unsigned program)
1266 {
1267 makeContextCurrent();
1268 glDeleteProgram(program);
1269 }
1270
deleteRenderbuffer(unsigned renderbuffer)1271 void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer)
1272 {
1273 makeContextCurrent();
1274 glDeleteRenderbuffersEXT(1, &renderbuffer);
1275 }
1276
deleteShader(unsigned shader)1277 void GraphicsContext3D::deleteShader(unsigned shader)
1278 {
1279 makeContextCurrent();
1280 glDeleteShader(shader);
1281 }
1282
deleteTexture(unsigned texture)1283 void GraphicsContext3D::deleteTexture(unsigned texture)
1284 {
1285 makeContextCurrent();
1286 glDeleteTextures(1, &texture);
1287 }
1288
activeTexture(unsigned long texture)1289 void GraphicsContext3D::activeTexture(unsigned long texture)
1290 {
1291 m_internal->activeTexture(texture);
1292 }
1293
GL_SAME_METHOD_2_X12(AttachShader,attachShader,WebGLProgram *,WebGLShader *)1294 GL_SAME_METHOD_2_X12(AttachShader, attachShader, WebGLProgram*, WebGLShader*)
1295
1296 void GraphicsContext3D::bindAttribLocation(WebGLProgram* program,
1297 unsigned long index,
1298 const String& name)
1299 {
1300 if (!program)
1301 return;
1302 makeContextCurrent();
1303 glBindAttribLocation(EXTRACT(program), index, name.utf8().data());
1304 }
1305
bindBuffer(unsigned long target,WebGLBuffer * buffer)1306 void GraphicsContext3D::bindBuffer(unsigned long target,
1307 WebGLBuffer* buffer)
1308 {
1309 m_internal->bindBuffer(target, buffer);
1310 }
1311
bindFramebuffer(unsigned long target,WebGLFramebuffer * framebuffer)1312 void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* framebuffer)
1313 {
1314 m_internal->bindFramebuffer(target, framebuffer);
1315 }
1316
GL_SAME_METHOD_2_X2(BindRenderbufferEXT,bindRenderbuffer,unsigned long,WebGLRenderbuffer *)1317 GL_SAME_METHOD_2_X2(BindRenderbufferEXT, bindRenderbuffer, unsigned long, WebGLRenderbuffer*)
1318
1319 // If we didn't have to hack GL_TEXTURE_WRAP_R for cube maps,
1320 // we could just use:
1321 // GL_SAME_METHOD_2_X2(BindTexture, bindTexture, unsigned long, WebGLTexture*)
1322 void GraphicsContext3D::bindTexture(unsigned long target,
1323 WebGLTexture* texture)
1324 {
1325 m_internal->bindTexture(target, texture);
1326 }
1327
GL_SAME_METHOD_4(BlendColor,blendColor,double,double,double,double)1328 GL_SAME_METHOD_4(BlendColor, blendColor, double, double, double, double)
1329
1330 GL_SAME_METHOD_1(BlendEquation, blendEquation, unsigned long)
1331
1332 GL_SAME_METHOD_2(BlendEquationSeparate, blendEquationSeparate, unsigned long, unsigned long)
1333
1334 GL_SAME_METHOD_2(BlendFunc, blendFunc, unsigned long, unsigned long)
1335
1336 GL_SAME_METHOD_4(BlendFuncSeparate, blendFuncSeparate, unsigned long, unsigned long, unsigned long, unsigned long)
1337
1338 void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage)
1339 {
1340 m_internal->bufferDataImpl(target, size, 0, usage);
1341 }
1342
bufferData(unsigned long target,WebGLArray * array,unsigned long usage)1343 void GraphicsContext3D::bufferData(unsigned long target, WebGLArray* array, unsigned long usage)
1344 {
1345 m_internal->bufferDataImpl(target, array->byteLength(), array->baseAddress(), usage);
1346 }
1347
bufferSubData(unsigned long target,long offset,WebGLArray * array)1348 void GraphicsContext3D::bufferSubData(unsigned long target, long offset, WebGLArray* array)
1349 {
1350 if (!array || !array->length())
1351 return;
1352
1353 makeContextCurrent();
1354 // FIXME: make this verification more efficient.
1355 GLint binding = 0;
1356 GLenum binding_target = GL_ARRAY_BUFFER_BINDING;
1357 if (target == GL_ELEMENT_ARRAY_BUFFER)
1358 binding_target = GL_ELEMENT_ARRAY_BUFFER_BINDING;
1359 glGetIntegerv(binding_target, &binding);
1360 if (binding <= 0) {
1361 // FIXME: raise exception.
1362 // LogMessagef(("bufferSubData: no buffer bound"));
1363 return;
1364 }
1365 glBufferSubData(target, offset, array->byteLength(), array->baseAddress());
1366 }
1367
checkFramebufferStatus(unsigned long target)1368 unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
1369 {
1370 makeContextCurrent();
1371 return glCheckFramebufferStatusEXT(target);
1372 }
1373
GL_SAME_METHOD_1(Clear,clear,unsigned long)1374 GL_SAME_METHOD_1(Clear, clear, unsigned long)
1375
1376 GL_SAME_METHOD_4(ClearColor, clearColor, double, double, double, double)
1377
1378 GL_SAME_METHOD_1(ClearDepth, clearDepth, double)
1379
1380 GL_SAME_METHOD_1(ClearStencil, clearStencil, long)
1381
1382 GL_SAME_METHOD_4(ColorMask, colorMask, bool, bool, bool, bool)
1383
1384 GL_SAME_METHOD_1_X(CompileShader, compileShader, WebGLShader*)
1385
1386 GL_SAME_METHOD_8(CopyTexImage2D, copyTexImage2D, unsigned long, long, unsigned long, long, long, unsigned long, unsigned long, long)
1387
1388 GL_SAME_METHOD_8(CopyTexSubImage2D, copyTexSubImage2D, unsigned long, long, long, long, long, long, unsigned long, unsigned long)
1389
1390 GL_SAME_METHOD_1(CullFace, cullFace, unsigned long)
1391
1392 GL_SAME_METHOD_1(DepthFunc, depthFunc, unsigned long)
1393
1394 GL_SAME_METHOD_1(DepthMask, depthMask, bool)
1395
1396 GL_SAME_METHOD_2(DepthRange, depthRange, double, double)
1397
1398 void GraphicsContext3D::detachShader(WebGLProgram* program, WebGLShader* shader)
1399 {
1400 if (!program || !shader)
1401 return;
1402
1403 makeContextCurrent();
1404 glDetachShader(EXTRACT(program), EXTRACT(shader));
1405 }
1406
GL_SAME_METHOD_1(Disable,disable,unsigned long)1407 GL_SAME_METHOD_1(Disable, disable, unsigned long)
1408
1409 void GraphicsContext3D::disableVertexAttribArray(unsigned long index)
1410 {
1411 m_internal->disableVertexAttribArray(index);
1412 }
1413
drawArrays(unsigned long mode,long first,long count)1414 void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count)
1415 {
1416 switch (mode) {
1417 case GL_TRIANGLES:
1418 case GL_TRIANGLE_STRIP:
1419 case GL_TRIANGLE_FAN:
1420 case GL_POINTS:
1421 case GL_LINE_STRIP:
1422 case GL_LINE_LOOP:
1423 case GL_LINES:
1424 break;
1425 default: // FIXME: default cases are discouraged in WebKit.
1426 // FIXME: output log message, raise exception.
1427 // LogMessage(NS_LITERAL_CSTRING("drawArrays: invalid mode"));
1428 // return NS_ERROR_DOM_SYNTAX_ERR;
1429 return;
1430 }
1431
1432 if (first+count < first || first+count < count) {
1433 // FIXME: output log message, raise exception.
1434 // LogMessage(NS_LITERAL_CSTRING("drawArrays: overflow in first+count"));
1435 // return NS_ERROR_INVALID_ARG;
1436 return;
1437 }
1438
1439 // FIXME: validate against currently bound buffer.
1440 // if (!ValidateBuffers(first+count))
1441 // return NS_ERROR_INVALID_ARG;
1442
1443 makeContextCurrent();
1444 glDrawArrays(mode, first, count);
1445 }
1446
drawElements(unsigned long mode,unsigned long count,unsigned long type,long offset)1447 void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset)
1448 {
1449 makeContextCurrent();
1450 // FIXME: make this verification more efficient.
1451 GLint binding = 0;
1452 GLenum binding_target = GL_ELEMENT_ARRAY_BUFFER_BINDING;
1453 glGetIntegerv(binding_target, &binding);
1454 if (binding <= 0) {
1455 // FIXME: raise exception.
1456 // LogMessagef(("bufferData: no buffer bound"));
1457 return;
1458 }
1459 glDrawElements(mode, count, type,
1460 reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
1461 }
1462
GL_SAME_METHOD_1(Enable,enable,unsigned long)1463 GL_SAME_METHOD_1(Enable, enable, unsigned long)
1464
1465 void GraphicsContext3D::enableVertexAttribArray(unsigned long index)
1466 {
1467 m_internal->enableVertexAttribArray(index);
1468 }
1469
GL_SAME_METHOD_0(Finish,finish)1470 GL_SAME_METHOD_0(Finish, finish)
1471
1472 GL_SAME_METHOD_0(Flush, flush)
1473
1474 GL_SAME_METHOD_4_X4(FramebufferRenderbufferEXT, framebufferRenderbuffer, unsigned long, unsigned long, unsigned long, WebGLRenderbuffer*)
1475
1476 GL_SAME_METHOD_5_X4(FramebufferTexture2DEXT, framebufferTexture2D, unsigned long, unsigned long, unsigned long, WebGLTexture*, long)
1477
1478 GL_SAME_METHOD_1(FrontFace, frontFace, unsigned long)
1479
1480 void GraphicsContext3D::generateMipmap(unsigned long target)
1481 {
1482 makeContextCurrent();
1483 if (glGenerateMipmapEXT)
1484 glGenerateMipmapEXT(target);
1485 // FIXME: provide alternative code path? This will be unpleasant
1486 // to implement if glGenerateMipmapEXT is not available -- it will
1487 // require a texture readback and re-upload.
1488 }
1489
getActiveAttrib(WebGLProgram * program,unsigned long index,ActiveInfo & info)1490 bool GraphicsContext3D::getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo& info)
1491 {
1492 if (!program) {
1493 synthesizeGLError(INVALID_VALUE);
1494 return false;
1495 }
1496 GLint maxNameLength = -1;
1497 glGetProgramiv(EXTRACT(program), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength);
1498 if (maxNameLength < 0)
1499 return false;
1500 GLchar* name = 0;
1501 if (!tryFastMalloc(maxNameLength * sizeof(GLchar)).getValue(name)) {
1502 synthesizeGLError(OUT_OF_MEMORY);
1503 return false;
1504 }
1505 GLsizei length = 0;
1506 GLint size = -1;
1507 GLenum type = 0;
1508 glGetActiveAttrib(EXTRACT(program), index, maxNameLength,
1509 &length, &size, &type, name);
1510 if (size < 0) {
1511 fastFree(name);
1512 return false;
1513 }
1514 info.name = String(name, length);
1515 info.type = type;
1516 info.size = size;
1517 fastFree(name);
1518 return true;
1519 }
1520
getActiveUniform(WebGLProgram * program,unsigned long index,ActiveInfo & info)1521 bool GraphicsContext3D::getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo& info)
1522 {
1523 if (!program) {
1524 synthesizeGLError(INVALID_VALUE);
1525 return false;
1526 }
1527 GLint maxNameLength = -1;
1528 glGetProgramiv(EXTRACT(program), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
1529 if (maxNameLength < 0)
1530 return false;
1531 GLchar* name = 0;
1532 if (!tryFastMalloc(maxNameLength * sizeof(GLchar)).getValue(name)) {
1533 synthesizeGLError(OUT_OF_MEMORY);
1534 return false;
1535 }
1536 GLsizei length = 0;
1537 GLint size = -1;
1538 GLenum type = 0;
1539 glGetActiveUniform(EXTRACT(program), index, maxNameLength,
1540 &length, &size, &type, name);
1541 if (size < 0) {
1542 fastFree(name);
1543 return false;
1544 }
1545 info.name = String(name, length);
1546 info.type = type;
1547 info.size = size;
1548 fastFree(name);
1549 return true;
1550 }
1551
getAttribLocation(WebGLProgram * program,const String & name)1552 int GraphicsContext3D::getAttribLocation(WebGLProgram* program, const String& name)
1553 {
1554 if (!program)
1555 return -1;
1556
1557 makeContextCurrent();
1558 return glGetAttribLocation(EXTRACT(program), name.utf8().data());
1559 }
1560
getBooleanv(unsigned long pname,unsigned char * value)1561 void GraphicsContext3D::getBooleanv(unsigned long pname, unsigned char* value)
1562 {
1563 makeContextCurrent();
1564 glGetBooleanv(pname, value);
1565 }
1566
getBufferParameteriv(unsigned long target,unsigned long pname,int * value)1567 void GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname, int* value)
1568 {
1569 makeContextCurrent();
1570 glGetBufferParameteriv(target, pname, value);
1571 }
1572
getContextAttributes()1573 GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
1574 {
1575 return m_internal->getContextAttributes();
1576 }
1577
getError()1578 unsigned long GraphicsContext3D::getError()
1579 {
1580 return m_internal->getError();
1581 }
1582
getFloatv(unsigned long pname,float * value)1583 void GraphicsContext3D::getFloatv(unsigned long pname, float* value)
1584 {
1585 makeContextCurrent();
1586 glGetFloatv(pname, value);
1587 }
1588
getFramebufferAttachmentParameteriv(unsigned long target,unsigned long attachment,unsigned long pname,int * value)1589 void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target,
1590 unsigned long attachment,
1591 unsigned long pname,
1592 int* value)
1593 {
1594 makeContextCurrent();
1595 glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
1596 }
1597
getIntegerv(unsigned long pname,int * value)1598 void GraphicsContext3D::getIntegerv(unsigned long pname, int* value)
1599 {
1600 makeContextCurrent();
1601 glGetIntegerv(pname, value);
1602 }
1603
getProgramiv(WebGLProgram * program,unsigned long pname,int * value)1604 void GraphicsContext3D::getProgramiv(WebGLProgram* program,
1605 unsigned long pname,
1606 int* value)
1607 {
1608 makeContextCurrent();
1609 glGetProgramiv(EXTRACT(program), pname, value);
1610 }
1611
getProgramInfoLog(WebGLProgram * program)1612 String GraphicsContext3D::getProgramInfoLog(WebGLProgram* program)
1613 {
1614 makeContextCurrent();
1615 GLuint programID = EXTRACT(program);
1616 GLint logLength;
1617 glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logLength);
1618 if (!logLength)
1619 return String();
1620 GLchar* log = 0;
1621 if (!tryFastMalloc(logLength * sizeof(GLchar)).getValue(log))
1622 return String();
1623 GLsizei returnedLogLength;
1624 glGetProgramInfoLog(programID, logLength, &returnedLogLength, log);
1625 ASSERT(logLength == returnedLogLength + 1);
1626 String res = String(log, returnedLogLength);
1627 fastFree(log);
1628 return res;
1629 }
1630
getRenderbufferParameteriv(unsigned long target,unsigned long pname,int * value)1631 void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target,
1632 unsigned long pname,
1633 int* value)
1634 {
1635 makeContextCurrent();
1636 glGetRenderbufferParameterivEXT(target, pname, value);
1637 }
1638
getShaderiv(WebGLShader * shader,unsigned long pname,int * value)1639 void GraphicsContext3D::getShaderiv(WebGLShader* shader,
1640 unsigned long pname,
1641 int* value)
1642 {
1643 makeContextCurrent();
1644 glGetShaderiv(EXTRACT(shader), pname, value);
1645 }
1646
getShaderInfoLog(WebGLShader * shader)1647 String GraphicsContext3D::getShaderInfoLog(WebGLShader* shader)
1648 {
1649 makeContextCurrent();
1650 GLuint shaderID = EXTRACT(shader);
1651 GLint logLength;
1652 glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);
1653 if (!logLength)
1654 return String();
1655 GLchar* log = 0;
1656 if (!tryFastMalloc(logLength * sizeof(GLchar)).getValue(log))
1657 return String();
1658 GLsizei returnedLogLength;
1659 glGetShaderInfoLog(shaderID, logLength, &returnedLogLength, log);
1660 ASSERT(logLength == returnedLogLength + 1);
1661 String res = String(log, returnedLogLength);
1662 fastFree(log);
1663 return res;
1664 }
1665
getShaderSource(WebGLShader * shader)1666 String GraphicsContext3D::getShaderSource(WebGLShader* shader)
1667 {
1668 makeContextCurrent();
1669 GLuint shaderID = EXTRACT(shader);
1670 GLint logLength;
1671 glGetShaderiv(shaderID, GL_SHADER_SOURCE_LENGTH, &logLength);
1672 if (!logLength)
1673 return String();
1674 GLchar* log = 0;
1675 if (!tryFastMalloc(logLength * sizeof(GLchar)).getValue(log))
1676 return String();
1677 GLsizei returnedLogLength;
1678 glGetShaderSource(shaderID, logLength, &returnedLogLength, log);
1679 ASSERT(logLength == returnedLogLength + 1);
1680 String res = String(log, returnedLogLength);
1681 fastFree(log);
1682 return res;
1683 }
1684
getString(unsigned long name)1685 String GraphicsContext3D::getString(unsigned long name)
1686 {
1687 makeContextCurrent();
1688 return String(reinterpret_cast<const char*>(glGetString(name)));
1689 }
1690
getTexParameterfv(unsigned long target,unsigned long pname,float * value)1691 void GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname, float* value)
1692 {
1693 makeContextCurrent();
1694 glGetTexParameterfv(target, pname, value);
1695 }
1696
getTexParameteriv(unsigned long target,unsigned long pname,int * value)1697 void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname, int* value)
1698 {
1699 makeContextCurrent();
1700 glGetTexParameteriv(target, pname, value);
1701 }
1702
getUniformfv(WebGLProgram * program,long location,float * value)1703 void GraphicsContext3D::getUniformfv(WebGLProgram* program, long location, float* value)
1704 {
1705 makeContextCurrent();
1706 glGetUniformfv(EXTRACT(program), location, value);
1707 }
1708
getUniformiv(WebGLProgram * program,long location,int * value)1709 void GraphicsContext3D::getUniformiv(WebGLProgram* program, long location, int* value)
1710 {
1711 makeContextCurrent();
1712 glGetUniformiv(EXTRACT(program), location, value);
1713 }
1714
getUniformLocation(WebGLProgram * program,const String & name)1715 long GraphicsContext3D::getUniformLocation(WebGLProgram* program, const String& name)
1716 {
1717 if (!program)
1718 return -1;
1719
1720 makeContextCurrent();
1721 return glGetUniformLocation(EXTRACT(program), name.utf8().data());
1722 }
1723
getVertexAttribfv(unsigned long index,unsigned long pname,float * value)1724 void GraphicsContext3D::getVertexAttribfv(unsigned long index,
1725 unsigned long pname,
1726 float* value)
1727 {
1728 makeContextCurrent();
1729 glGetVertexAttribfv(index, pname, value);
1730 }
1731
getVertexAttribiv(unsigned long index,unsigned long pname,int * value)1732 void GraphicsContext3D::getVertexAttribiv(unsigned long index,
1733 unsigned long pname,
1734 int* value)
1735 {
1736 makeContextCurrent();
1737 glGetVertexAttribiv(index, pname, value);
1738 }
1739
getVertexAttribOffset(unsigned long index,unsigned long pname)1740 long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long pname)
1741 {
1742 // FIXME: implement.
1743 notImplemented();
1744 return 0;
1745 }
1746
1747 GL_SAME_METHOD_2(Hint, hint, unsigned long, unsigned long);
1748
isBuffer(WebGLBuffer * buffer)1749 bool GraphicsContext3D::isBuffer(WebGLBuffer* buffer)
1750 {
1751 makeContextCurrent();
1752 return glIsBuffer(EXTRACT(buffer));
1753 }
1754
isEnabled(unsigned long cap)1755 bool GraphicsContext3D::isEnabled(unsigned long cap)
1756 {
1757 makeContextCurrent();
1758 return glIsEnabled(cap);
1759 }
1760
isFramebuffer(WebGLFramebuffer * framebuffer)1761 bool GraphicsContext3D::isFramebuffer(WebGLFramebuffer* framebuffer)
1762 {
1763 makeContextCurrent();
1764 return glIsFramebufferEXT(EXTRACT(framebuffer));
1765 }
1766
isProgram(WebGLProgram * program)1767 bool GraphicsContext3D::isProgram(WebGLProgram* program)
1768 {
1769 makeContextCurrent();
1770 return glIsProgram(EXTRACT(program));
1771 }
1772
isRenderbuffer(WebGLRenderbuffer * renderbuffer)1773 bool GraphicsContext3D::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
1774 {
1775 makeContextCurrent();
1776 return glIsRenderbufferEXT(EXTRACT(renderbuffer));
1777 }
1778
isShader(WebGLShader * shader)1779 bool GraphicsContext3D::isShader(WebGLShader* shader)
1780 {
1781 makeContextCurrent();
1782 return glIsShader(EXTRACT(shader));
1783 }
1784
isTexture(WebGLTexture * texture)1785 bool GraphicsContext3D::isTexture(WebGLTexture* texture)
1786 {
1787 makeContextCurrent();
1788 return glIsTexture(EXTRACT(texture));
1789 }
1790
GL_SAME_METHOD_1(LineWidth,lineWidth,double)1791 GL_SAME_METHOD_1(LineWidth, lineWidth, double)
1792
1793 GL_SAME_METHOD_1_X(LinkProgram, linkProgram, WebGLProgram*)
1794
1795 void GraphicsContext3D::pixelStorei(unsigned long pname, long param)
1796 {
1797 if (pname != GL_PACK_ALIGNMENT && pname != GL_UNPACK_ALIGNMENT) {
1798 // FIXME: Create a fake GL error and throw an exception.
1799 return;
1800 }
1801
1802 makeContextCurrent();
1803 glPixelStorei(pname, param);
1804 }
1805
GL_SAME_METHOD_2(PolygonOffset,polygonOffset,double,double)1806 GL_SAME_METHOD_2(PolygonOffset, polygonOffset, double, double)
1807
1808 PassRefPtr<WebGLArray> GraphicsContext3D::readPixels(long x, long y,
1809 unsigned long width, unsigned long height,
1810 unsigned long format, unsigned long type) {
1811 // FIXME: support more pixel formats and types.
1812 if (!((format == GL_RGBA) && (type == GL_UNSIGNED_BYTE)))
1813 return 0;
1814
1815 // FIXME: take into account pack alignment.
1816 RefPtr<WebGLUnsignedByteArray> array = WebGLUnsignedByteArray::create(width * height * 4);
1817 glReadPixels(x, y, width, height, format, type, array->baseAddress());
1818 return array;
1819 }
1820
releaseShaderCompiler()1821 void GraphicsContext3D::releaseShaderCompiler()
1822 {
1823 }
1824
GL_SAME_METHOD_4(RenderbufferStorageEXT,renderbufferStorage,unsigned long,unsigned long,unsigned long,unsigned long)1825 GL_SAME_METHOD_4(RenderbufferStorageEXT, renderbufferStorage, unsigned long, unsigned long, unsigned long, unsigned long)
1826
1827 GL_SAME_METHOD_2(SampleCoverage, sampleCoverage, double, bool)
1828
1829 GL_SAME_METHOD_4(Scissor, scissor, long, long, unsigned long, unsigned long)
1830
1831 void GraphicsContext3D::shaderSource(WebGLShader* shader, const String& source)
1832 {
1833 makeContextCurrent();
1834 CString str = source.utf8();
1835 const char* data = str.data();
1836 GLint length = str.length();
1837 glShaderSource(EXTRACT(shader), 1, &data, &length);
1838 }
1839
GL_SAME_METHOD_3(StencilFunc,stencilFunc,unsigned long,long,unsigned long)1840 GL_SAME_METHOD_3(StencilFunc, stencilFunc, unsigned long, long, unsigned long)
1841
1842 GL_SAME_METHOD_4(StencilFuncSeparate, stencilFuncSeparate, unsigned long, unsigned long, long, unsigned long)
1843
1844 GL_SAME_METHOD_1(StencilMask, stencilMask, unsigned long)
1845
1846 GL_SAME_METHOD_2(StencilMaskSeparate, stencilMaskSeparate, unsigned long, unsigned long)
1847
1848 GL_SAME_METHOD_3(StencilOp, stencilOp, unsigned long, unsigned long, unsigned long)
1849
1850 GL_SAME_METHOD_4(StencilOpSeparate, stencilOpSeparate, unsigned long, unsigned long, unsigned long, unsigned long)
1851
1852 void GraphicsContext3D::synthesizeGLError(unsigned long error)
1853 {
1854 m_internal->synthesizeGLError(error);
1855 }
1856
texImage2D(unsigned target,unsigned level,unsigned internalformat,unsigned width,unsigned height,unsigned border,unsigned format,unsigned type,void * pixels)1857 int GraphicsContext3D::texImage2D(unsigned target,
1858 unsigned level,
1859 unsigned internalformat,
1860 unsigned width,
1861 unsigned height,
1862 unsigned border,
1863 unsigned format,
1864 unsigned type,
1865 void* pixels)
1866 {
1867 // FIXME: must do validation similar to JOGL's to ensure that
1868 // the incoming array is of the appropriate length.
1869 glTexImage2D(target,
1870 level,
1871 internalformat,
1872 width,
1873 height,
1874 border,
1875 format,
1876 type,
1877 pixels);
1878 return 0;
1879 }
1880
1881 // Remove premultiplied alpha from color channels.
1882 // FIXME: this is lossy. Must retrieve original values from HTMLImageElement.
unmultiplyAlpha(unsigned char * rgbaData,int numPixels)1883 static void unmultiplyAlpha(unsigned char* rgbaData, int numPixels)
1884 {
1885 for (int j = 0; j < numPixels; j++) {
1886 float b = rgbaData[4*j+0] / 255.0f;
1887 float g = rgbaData[4*j+1] / 255.0f;
1888 float r = rgbaData[4*j+2] / 255.0f;
1889 float a = rgbaData[4*j+3] / 255.0f;
1890 if (a > 0.0f) {
1891 b /= a;
1892 g /= a;
1893 r /= a;
1894 b = (b > 1.0f) ? 1.0f : b;
1895 g = (g > 1.0f) ? 1.0f : g;
1896 r = (r > 1.0f) ? 1.0f : r;
1897 rgbaData[4*j+0] = (unsigned char) (b * 255.0f);
1898 rgbaData[4*j+1] = (unsigned char) (g * 255.0f);
1899 rgbaData[4*j+2] = (unsigned char) (r * 255.0f);
1900 }
1901 }
1902 }
1903
1904 // FIXME: this must be changed to refer to the original image data
1905 // rather than unmultiplying the alpha channel.
texImage2DHelper(unsigned target,unsigned level,int width,int height,int rowBytes,bool flipY,bool premultiplyAlpha,GLenum format,bool skipAlpha,unsigned char * pixels)1906 static int texImage2DHelper(unsigned target, unsigned level,
1907 int width, int height,
1908 int rowBytes,
1909 bool flipY,
1910 bool premultiplyAlpha,
1911 GLenum format,
1912 bool skipAlpha,
1913 unsigned char* pixels)
1914 {
1915 ASSERT(format == GL_RGBA || format == GL_BGRA);
1916 GLint internalFormat = GL_RGBA8;
1917 if (skipAlpha) {
1918 internalFormat = GL_RGB8;
1919 // Ignore the alpha channel
1920 premultiplyAlpha = true;
1921 }
1922 if (flipY) {
1923 // Need to flip images vertically. To avoid making a copy of
1924 // the entire image, we perform a ton of glTexSubImage2D
1925 // calls. FIXME: should rethink this strategy for efficiency.
1926 glTexImage2D(target, level, internalFormat,
1927 width,
1928 height,
1929 0,
1930 format,
1931 GL_UNSIGNED_BYTE,
1932 0);
1933 unsigned char* row = 0;
1934 bool allocatedRow = false;
1935 if (!premultiplyAlpha) {
1936 row = new unsigned char[rowBytes];
1937 allocatedRow = true;
1938 }
1939 for (int i = 0; i < height; i++) {
1940 if (premultiplyAlpha)
1941 row = pixels + (rowBytes * i);
1942 else {
1943 memcpy(row, pixels + (rowBytes * i), rowBytes);
1944 unmultiplyAlpha(row, width);
1945 }
1946 glTexSubImage2D(target, level, 0, height - i - 1,
1947 width, 1,
1948 format,
1949 GL_UNSIGNED_BYTE,
1950 row);
1951 }
1952 if (allocatedRow)
1953 delete[] row;
1954 } else {
1955 // The pixels of cube maps' faces are defined with a top-down
1956 // scanline ordering, unlike GL_TEXTURE_2D, so when uploading
1957 // these, the above vertical flip is the wrong thing to do.
1958 if (premultiplyAlpha)
1959 glTexImage2D(target, level, internalFormat,
1960 width,
1961 height,
1962 0,
1963 format,
1964 GL_UNSIGNED_BYTE,
1965 pixels);
1966 else {
1967 glTexImage2D(target, level, internalFormat,
1968 width,
1969 height,
1970 0,
1971 format,
1972 GL_UNSIGNED_BYTE,
1973 0);
1974 unsigned char* row = new unsigned char[rowBytes];
1975 for (int i = 0; i < height; i++) {
1976 memcpy(row, pixels + (rowBytes * i), rowBytes);
1977 unmultiplyAlpha(row, width);
1978 glTexSubImage2D(target, level, 0, i,
1979 width, 1,
1980 format,
1981 GL_UNSIGNED_BYTE,
1982 row);
1983 }
1984 delete[] row;
1985 }
1986 }
1987 return 0;
1988 }
1989
texImage2D(unsigned target,unsigned level,Image * image,bool flipY,bool premultiplyAlpha)1990 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image,
1991 bool flipY, bool premultiplyAlpha)
1992 {
1993 ASSERT(image);
1994
1995 int res = -1;
1996 #if PLATFORM(SKIA)
1997 NativeImageSkia* skiaImage = image->nativeImageForCurrentFrame();
1998 if (!skiaImage) {
1999 ASSERT_NOT_REACHED();
2000 return -1;
2001 }
2002 SkBitmap::Config skiaConfig = skiaImage->config();
2003 // FIXME: must support more image configurations.
2004 if (skiaConfig != SkBitmap::kARGB_8888_Config) {
2005 ASSERT_NOT_REACHED();
2006 return -1;
2007 }
2008 SkBitmap& skiaImageRef = *skiaImage;
2009 SkAutoLockPixels lock(skiaImageRef);
2010 int width = skiaImage->width();
2011 int height = skiaImage->height();
2012 unsigned char* pixels =
2013 reinterpret_cast<unsigned char*>(skiaImage->getPixels());
2014 int rowBytes = skiaImage->rowBytes();
2015 res = texImage2DHelper(target, level,
2016 width, height,
2017 rowBytes,
2018 flipY, premultiplyAlpha,
2019 GL_BGRA,
2020 false,
2021 pixels);
2022 #elif PLATFORM(CG)
2023 CGImageRef cgImage = image->nativeImageForCurrentFrame();
2024 if (!cgImage) {
2025 ASSERT_NOT_REACHED();
2026 return -1;
2027 }
2028 int width = CGImageGetWidth(cgImage);
2029 int height = CGImageGetHeight(cgImage);
2030 int rowBytes = width * 4;
2031 CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage);
2032 bool skipAlpha = (info == kCGImageAlphaNone
2033 || info == kCGImageAlphaNoneSkipLast
2034 || info == kCGImageAlphaNoneSkipFirst);
2035 unsigned char* imageData = new unsigned char[height * rowBytes];
2036 CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
2037 CGContextRef tmpContext = CGBitmapContextCreate(imageData, width, height, 8, rowBytes,
2038 colorSpace,
2039 kCGImageAlphaPremultipliedLast);
2040 CGColorSpaceRelease(colorSpace);
2041 CGContextSetBlendMode(tmpContext, kCGBlendModeCopy);
2042 CGContextDrawImage(tmpContext,
2043 CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)),
2044 cgImage);
2045 CGContextRelease(tmpContext);
2046 res = texImage2DHelper(target, level, width, height, rowBytes,
2047 flipY, premultiplyAlpha, GL_RGBA, skipAlpha, imageData);
2048 delete[] imageData;
2049 #else
2050 #error Must port to your platform
2051 #endif
2052 return res;
2053 }
2054
2055 GL_SAME_METHOD_3(TexParameterf, texParameterf, unsigned, unsigned, float);
2056
2057 GL_SAME_METHOD_3(TexParameteri, texParameteri, unsigned, unsigned, int);
2058
texSubImage2D(unsigned target,unsigned level,unsigned xoffset,unsigned yoffset,unsigned width,unsigned height,unsigned format,unsigned type,void * pixels)2059 int GraphicsContext3D::texSubImage2D(unsigned target,
2060 unsigned level,
2061 unsigned xoffset,
2062 unsigned yoffset,
2063 unsigned width,
2064 unsigned height,
2065 unsigned format,
2066 unsigned type,
2067 void* pixels)
2068 {
2069 glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
2070 return 0;
2071 }
2072
texSubImage2D(unsigned target,unsigned level,unsigned xoffset,unsigned yoffset,Image * image,bool flipY,bool premultiplyAlpha)2073 int GraphicsContext3D::texSubImage2D(unsigned target,
2074 unsigned level,
2075 unsigned xoffset,
2076 unsigned yoffset,
2077 Image* image,
2078 bool flipY,
2079 bool premultiplyAlpha)
2080 {
2081 // FIXME: implement.
2082 notImplemented();
2083 return -1;
2084 }
2085
GL_SAME_METHOD_2(Uniform1f,uniform1f,long,float)2086 GL_SAME_METHOD_2(Uniform1f, uniform1f, long, float)
2087
2088 void GraphicsContext3D::uniform1fv(long location, float* v, int size)
2089 {
2090 makeContextCurrent();
2091 glUniform1fv(location, size, v);
2092 }
2093
GL_SAME_METHOD_2(Uniform1i,uniform1i,long,int)2094 GL_SAME_METHOD_2(Uniform1i, uniform1i, long, int)
2095
2096 void GraphicsContext3D::uniform1iv(long location, int* v, int size)
2097 {
2098 makeContextCurrent();
2099 glUniform1iv(location, size, v);
2100 }
2101
GL_SAME_METHOD_3(Uniform2f,uniform2f,long,float,float)2102 GL_SAME_METHOD_3(Uniform2f, uniform2f, long, float, float)
2103
2104 void GraphicsContext3D::uniform2fv(long location, float* v, int size)
2105 {
2106 makeContextCurrent();
2107 glUniform2fv(location, size, v);
2108 }
2109
GL_SAME_METHOD_3(Uniform2i,uniform2i,long,int,int)2110 GL_SAME_METHOD_3(Uniform2i, uniform2i, long, int, int)
2111
2112 void GraphicsContext3D::uniform2iv(long location, int* v, int size)
2113 {
2114 makeContextCurrent();
2115 glUniform2iv(location, size, v);
2116 }
2117
GL_SAME_METHOD_4(Uniform3f,uniform3f,long,float,float,float)2118 GL_SAME_METHOD_4(Uniform3f, uniform3f, long, float, float, float)
2119
2120 void GraphicsContext3D::uniform3fv(long location, float* v, int size)
2121 {
2122 makeContextCurrent();
2123 glUniform3fv(location, size, v);
2124 }
2125
GL_SAME_METHOD_4(Uniform3i,uniform3i,long,int,int,int)2126 GL_SAME_METHOD_4(Uniform3i, uniform3i, long, int, int, int)
2127
2128 void GraphicsContext3D::uniform3iv(long location, int* v, int size)
2129 {
2130 makeContextCurrent();
2131 glUniform3iv(location, size, v);
2132 }
2133
GL_SAME_METHOD_5(Uniform4f,uniform4f,long,float,float,float,float)2134 GL_SAME_METHOD_5(Uniform4f, uniform4f, long, float, float, float, float)
2135
2136 void GraphicsContext3D::uniform4fv(long location, float* v, int size)
2137 {
2138 makeContextCurrent();
2139 glUniform4fv(location, size, v);
2140 }
2141
GL_SAME_METHOD_5(Uniform4i,uniform4i,long,int,int,int,int)2142 GL_SAME_METHOD_5(Uniform4i, uniform4i, long, int, int, int, int)
2143
2144 void GraphicsContext3D::uniform4iv(long location, int* v, int size)
2145 {
2146 makeContextCurrent();
2147 glUniform4iv(location, size, v);
2148 }
2149
uniformMatrix2fv(long location,bool transpose,float * value,int size)2150 void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* value, int size)
2151 {
2152 makeContextCurrent();
2153 glUniformMatrix2fv(location, size, transpose, value);
2154 }
2155
uniformMatrix3fv(long location,bool transpose,float * value,int size)2156 void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* value, int size)
2157 {
2158 makeContextCurrent();
2159 glUniformMatrix3fv(location, size, transpose, value);
2160 }
2161
uniformMatrix4fv(long location,bool transpose,float * value,int size)2162 void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* value, int size)
2163 {
2164 makeContextCurrent();
2165 glUniformMatrix4fv(location, size, transpose, value);
2166 }
2167
GL_SAME_METHOD_1_X(UseProgram,useProgram,WebGLProgram *)2168 GL_SAME_METHOD_1_X(UseProgram, useProgram, WebGLProgram*)
2169
2170 GL_SAME_METHOD_1_X(ValidateProgram, validateProgram, WebGLProgram*)
2171
2172 GL_SAME_METHOD_2(VertexAttrib1f, vertexAttrib1f, unsigned long, float)
2173
2174 void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* values)
2175 {
2176 makeContextCurrent();
2177 glVertexAttrib1fv(indx, values);
2178 }
2179
GL_SAME_METHOD_3(VertexAttrib2f,vertexAttrib2f,unsigned long,float,float)2180 GL_SAME_METHOD_3(VertexAttrib2f, vertexAttrib2f, unsigned long, float, float)
2181
2182 void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* values)
2183 {
2184 makeContextCurrent();
2185 glVertexAttrib2fv(indx, values);
2186 }
2187
GL_SAME_METHOD_4(VertexAttrib3f,vertexAttrib3f,unsigned long,float,float,float)2188 GL_SAME_METHOD_4(VertexAttrib3f, vertexAttrib3f, unsigned long, float, float, float)
2189
2190 void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* values)
2191 {
2192 makeContextCurrent();
2193 glVertexAttrib3fv(indx, values);
2194 }
2195
GL_SAME_METHOD_5(VertexAttrib4f,vertexAttrib4f,unsigned long,float,float,float,float)2196 GL_SAME_METHOD_5(VertexAttrib4f, vertexAttrib4f, unsigned long, float, float, float, float)
2197
2198 void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* values)
2199 {
2200 makeContextCurrent();
2201 glVertexAttrib4fv(indx, values);
2202 }
2203
vertexAttribPointer(unsigned long indx,int size,int type,bool normalized,unsigned long stride,unsigned long offset)2204 void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized,
2205 unsigned long stride, unsigned long offset)
2206 {
2207 m_internal->vertexAttribPointer(indx, size, type, normalized, stride, offset);
2208 }
2209
viewport(long x,long y,unsigned long width,unsigned long height)2210 void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height)
2211 {
2212 makeContextCurrent();
2213 m_internal->viewportImpl(x, y, width, height);
2214 }
2215
2216 }
2217
2218 #endif // ENABLE(3D_CANVAS)
2219