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

Side by Side Diff: webkit/api/src/GraphicsContext3D.cpp

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

Powered by Google App Engine
This is Rietveld 408576698