OLD | NEW |
(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 "CanvasBuffer.h" |
| 39 #include "CanvasByteArray.h" |
| 40 #include "CanvasFloatArray.h" |
| 41 #include "CanvasFramebuffer.h" |
| 42 #include "CanvasIntArray.h" |
| 43 #include "CanvasObject.h" |
| 44 #include "CanvasProgram.h" |
| 45 #include "CanvasRenderbuffer.h" |
| 46 #include "CanvasRenderingContext3D.h" |
| 47 #include "CanvasShader.h" |
| 48 #include "CanvasTexture.h" |
| 49 #include "CanvasUnsignedByteArray.h" |
| 50 #include "CString.h" |
| 51 #include "HTMLCanvasElement.h" |
| 52 #include "HTMLImageElement.h" |
| 53 #include "ImageBuffer.h" |
| 54 #include "ImageData.h" |
| 55 #include "NotImplemented.h" |
| 56 #include <wtf/FastMalloc.h> |
| 57 |
| 58 #include <stdio.h> |
| 59 |
| 60 #if PLATFORM(WIN_OS) |
| 61 #include <windows.h> |
| 62 #endif |
| 63 |
| 64 #include "GL/glew.h" |
| 65 |
| 66 #include "NativeImageSkia.h" |
| 67 |
| 68 using namespace std; |
| 69 |
| 70 namespace WebCore { |
| 71 |
| 72 // GraphicsContext3DInternal ----------------------------------------------------- |
| 73 |
| 74 // Uncomment this to render to a separate window for debugging |
| 75 // #define RENDER_TO_DEBUGGING_WINDOW |
| 76 |
| 77 #define EXTRACT(val) (val == NULL ? 0 : val->object()) |
| 78 |
| 79 class GraphicsContext3DInternal { |
| 80 public: |
| 81 GraphicsContext3DInternal(); |
| 82 ~GraphicsContext3DInternal(); |
| 83 |
| 84 void checkError() const; |
| 85 bool makeContextCurrent(); |
| 86 |
| 87 PlatformGraphicsContext3D platformGraphicsContext3D() const; |
| 88 Platform3DObject platformTexture() const; |
| 89 |
| 90 void reshape(int width, int height); |
| 91 |
| 92 void beginPaint(CanvasRenderingContext3D* context); |
| 93 |
| 94 bool validateTextureTarget(int target); |
| 95 bool validateTextureParameter(int param); |
| 96 |
| 97 void activeTexture(unsigned long texture); |
| 98 void bindBuffer(unsigned long target, |
| 99 CanvasBuffer* buffer); |
| 100 void bindTexture(unsigned long target, |
| 101 CanvasTexture* texture); |
| 102 void bufferDataImpl(unsigned long target, int size, const void* data, unsigned long usage); |
| 103 void colorMask(bool red, bool green, bool blue, bool alpha); |
| 104 void depthMask(bool flag); |
| 105 void disable(unsigned long cap); |
| 106 void disableVertexAttribArray(unsigned long index); |
| 107 void enable(unsigned long cap); |
| 108 void enableVertexAttribArray(unsigned long index); |
| 109 void useProgram(CanvasProgram* program); |
| 110 void vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, |
| 111 unsigned long stride, unsigned long offset); |
| 112 void viewportImpl(long x, long y, unsigned long width, unsigned long height); |
| 113 |
| 114 private: |
| 115 unsigned int m_texture; |
| 116 unsigned int m_fbo; |
| 117 unsigned int m_depthBuffer; |
| 118 |
| 119 // Objects for flipping the render output vertically |
| 120 unsigned int m_altTexture; |
| 121 unsigned int m_quadVBO; |
| 122 unsigned int m_quadProgram; |
| 123 unsigned int m_quadTexLocation; |
| 124 |
| 125 // Storage for saving/restoring buffer, vertex attribute, |
| 126 // blending, and program state when drawing flipped quad |
| 127 unsigned int m_currentProgram; |
| 128 bool m_blendEnabled; |
| 129 bool m_depthTestEnabled; |
| 130 bool m_depthMaskEnabled; |
| 131 bool m_colorMask[4]; |
| 132 unsigned int m_boundArrayBuffer; |
| 133 class VertexAttribPointerState { |
| 134 public: |
| 135 VertexAttribPointerState(); |
| 136 |
| 137 bool enabled; |
| 138 unsigned long buffer; |
| 139 unsigned long indx; |
| 140 int size; |
| 141 int type; |
| 142 bool normalized; |
| 143 unsigned long stride; |
| 144 unsigned long offset; |
| 145 }; |
| 146 VertexAttribPointerState m_vertexAttribPointerState[1]; |
| 147 unsigned int m_activeTextureUnit; |
| 148 class TextureUnitState { |
| 149 public: |
| 150 TextureUnitState(); |
| 151 |
| 152 unsigned long target; |
| 153 unsigned int texture; |
| 154 }; |
| 155 TextureUnitState m_textureUnitState[1]; |
| 156 int m_viewport[4]; |
| 157 |
| 158 #if PLATFORM(WIN_OS) |
| 159 HWND m_canvasWindow; |
| 160 HDC m_canvasDC; |
| 161 HGLRC m_contextObj; |
| 162 #else |
| 163 #error Must port GraphicsContext3D to your platform |
| 164 #endif |
| 165 }; |
| 166 |
| 167 GraphicsContext3DInternal::VertexAttribPointerState::VertexAttribPointerState() |
| 168 : enabled(false) |
| 169 , buffer(0) |
| 170 , indx(0) |
| 171 , size(0) |
| 172 , type(0) |
| 173 , normalized(false) |
| 174 , stride(0) |
| 175 , offset(0) |
| 176 { |
| 177 } |
| 178 |
| 179 GraphicsContext3DInternal::TextureUnitState::TextureUnitState() |
| 180 : target(0) |
| 181 , texture(0) |
| 182 { |
| 183 } |
| 184 |
| 185 GraphicsContext3DInternal::GraphicsContext3DInternal() |
| 186 : m_texture(0) |
| 187 , m_fbo(0) |
| 188 , m_depthBuffer(0) |
| 189 , m_altTexture(0) |
| 190 , m_quadVBO(0) |
| 191 , m_quadProgram(0) |
| 192 , m_quadTexLocation(0) |
| 193 , m_currentProgram(0) |
| 194 , m_blendEnabled(false) |
| 195 , m_depthTestEnabled(false) |
| 196 , m_depthMaskEnabled(true) |
| 197 , m_boundArrayBuffer(0) |
| 198 , m_activeTextureUnit(0) |
| 199 #if PLATFORM(WIN_OS) |
| 200 , m_canvasWindow(NULL) |
| 201 , m_canvasDC(NULL) |
| 202 , m_contextObj(NULL) |
| 203 #else |
| 204 #error Must port to your platform |
| 205 #endif |
| 206 { |
| 207 for (int i = 0; i < 4; i++) { |
| 208 m_viewport[i] = 0; |
| 209 m_colorMask[i] = true; |
| 210 } |
| 211 #if PLATFORM(WIN_OS) |
| 212 WNDCLASS wc; |
| 213 if (!GetClassInfo(GetModuleHandle(NULL), L"CANVASGL", &wc)) { |
| 214 ZeroMemory(&wc, sizeof(WNDCLASS)); |
| 215 wc.style = CS_OWNDC; |
| 216 wc.hInstance = GetModuleHandle(NULL); |
| 217 wc.lpfnWndProc = DefWindowProc; |
| 218 wc.lpszClassName = L"CANVASGL"; |
| 219 |
| 220 if (!RegisterClass(&wc)) { |
| 221 printf("GraphicsContext3D: RegisterClass failed\n"); |
| 222 return; |
| 223 } |
| 224 } |
| 225 |
| 226 m_canvasWindow = CreateWindow(L"CANVASGL", L"CANVASGL", |
| 227 WS_CAPTION, |
| 228 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, |
| 229 CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), NULL); |
| 230 if (!m_canvasWindow) { |
| 231 printf("GraphicsContext3DInternal: CreateWindow failed\n"); |
| 232 return; |
| 233 } |
| 234 |
| 235 // get the device context |
| 236 m_canvasDC = GetDC(m_canvasWindow); |
| 237 if (!m_canvasDC) { |
| 238 printf("GraphicsContext3DInternal: GetDC failed\n"); |
| 239 return; |
| 240 } |
| 241 |
| 242 // find default pixel format |
| 243 PIXELFORMATDESCRIPTOR pfd; |
| 244 ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); |
| 245 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); |
| 246 pfd.nVersion = 1; |
| 247 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
| 248 #ifdef RENDER_TO_DEBUGGING_WINDOW |
| 249 | PFD_DOUBLEBUFFER |
| 250 #endif // RENDER_TO_DEBUGGING_WINDOW |
| 251 ; |
| 252 int pixelformat = ChoosePixelFormat(m_canvasDC, &pfd); |
| 253 |
| 254 // set the pixel format for the dc |
| 255 if (!SetPixelFormat(m_canvasDC, pixelformat, &pfd)) { |
| 256 printf("GraphicsContext3D: SetPixelFormat failed\n"); |
| 257 return; |
| 258 } |
| 259 |
| 260 // create rendering context |
| 261 m_contextObj = wglCreateContext(m_canvasDC); |
| 262 if (!m_contextObj) { |
| 263 printf("GraphicsContext3D: wglCreateContext failed\n"); |
| 264 return; |
| 265 } |
| 266 |
| 267 if (!wglMakeCurrent(m_canvasDC, m_contextObj)) { |
| 268 printf("GraphicsContext3D: wglMakeCurrent failed\n"); |
| 269 return; |
| 270 } |
| 271 |
| 272 #ifdef RENDER_TO_DEBUGGING_WINDOW |
| 273 typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); |
| 274 PFNWGLSWAPINTERVALEXTPROC setSwapInterval = NULL; |
| 275 setSwapInterval = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); |
| 276 if (setSwapInterval != NULL) |
| 277 setSwapInterval(1); |
| 278 #endif // RENDER_TO_DEBUGGING_WINDOW |
| 279 |
| 280 #else |
| 281 #error Must port to your platform |
| 282 #endif |
| 283 |
| 284 // Initialize GLEW and check for GL 2.0 support by the drivers. |
| 285 GLenum glewInitResult = glewInit(); |
| 286 if (!glewIsSupported("GL_VERSION_2_0")) { |
| 287 printf("GraphicsContext3D: OpenGL 2.0 not supported\n"); |
| 288 return; |
| 289 } |
| 290 } |
| 291 |
| 292 GraphicsContext3DInternal::~GraphicsContext3DInternal() |
| 293 { |
| 294 makeContextCurrent(); |
| 295 #ifndef RENDER_TO_DEBUGGING_WINDOW |
| 296 glDeleteRenderbuffersEXT(1, &m_depthBuffer); |
| 297 glDeleteTextures(1, &m_texture); |
| 298 glDeleteTextures(1, &m_altTexture); |
| 299 glDeleteFramebuffersEXT(1, &m_fbo); |
| 300 #endif // !RENDER_TO_DEBUGGING_WINDOW |
| 301 #if PLATFORM(WIN_OS) |
| 302 wglMakeCurrent(NULL, NULL); |
| 303 wglDeleteContext(m_contextObj); |
| 304 ReleaseDC(m_canvasWindow, m_canvasDC); |
| 305 DestroyWindow(m_canvasWindow); |
| 306 #else |
| 307 #error Must port to your platform |
| 308 #endif |
| 309 m_contextObj = NULL; |
| 310 } |
| 311 |
| 312 void GraphicsContext3DInternal::checkError() const |
| 313 { |
| 314 // FIXME: This needs to only be done in the debug context. It |
| 315 // will need to throw an exception on error. |
| 316 GLenum error = glGetError(); |
| 317 if (error != GL_NO_ERROR) { |
| 318 printf("GL Error : %x\n", error); |
| 319 notImplemented(); |
| 320 } |
| 321 } |
| 322 |
| 323 bool GraphicsContext3DInternal::makeContextCurrent() |
| 324 { |
| 325 #if PLATFORM(WIN_OS) |
| 326 if (wglGetCurrentContext() != m_contextObj) |
| 327 if (wglMakeCurrent(m_canvasDC, m_contextObj)) |
| 328 return true; |
| 329 #else |
| 330 #error Must port to your platform |
| 331 #endif |
| 332 return false; |
| 333 } |
| 334 |
| 335 PlatformGraphicsContext3D GraphicsContext3DInternal::platformGraphicsContext3D() const |
| 336 { |
| 337 return m_contextObj; |
| 338 } |
| 339 |
| 340 Platform3DObject GraphicsContext3DInternal::platformTexture() const |
| 341 { |
| 342 return m_texture; |
| 343 } |
| 344 |
| 345 static int createTextureObject() |
| 346 { |
| 347 GLuint texture = 0; |
| 348 glGenTextures(1, &texture); |
| 349 glBindTexture(GL_TEXTURE_2D, texture); |
| 350 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 351 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 352 return texture; |
| 353 } |
| 354 |
| 355 void GraphicsContext3DInternal::reshape(int width, int height) |
| 356 { |
| 357 #ifdef RENDER_TO_DEBUGGING_WINDOW |
| 358 SetWindowPos(m_canvasWindow, HWND_TOP, 0, 0, width, height, |
| 359 SWP_NOMOVE); |
| 360 ShowWindow(m_canvasWindow, SW_SHOW); |
| 361 #endif |
| 362 |
| 363 makeContextCurrent(); |
| 364 |
| 365 #ifndef RENDER_TO_DEBUGGING_WINDOW |
| 366 if (m_texture == 0) { |
| 367 // Generate the texture objects |
| 368 m_texture = createTextureObject(); |
| 369 m_altTexture = createTextureObject(); |
| 370 |
| 371 // Generate the framebuffer object |
| 372 glGenFramebuffersEXT(1, &m_fbo); |
| 373 |
| 374 // Generate the depth buffer |
| 375 glGenRenderbuffersEXT(1, &m_depthBuffer); |
| 376 |
| 377 checkError(); |
| 378 } |
| 379 |
| 380 // Reallocate the color and depth buffers |
| 381 glBindTexture(GL_TEXTURE_2D, m_texture); |
| 382 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| 383 glBindTexture(GL_TEXTURE_2D, m_altTexture); |
| 384 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| 385 glBindTexture(GL_TEXTURE_2D, 0); |
| 386 |
| 387 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); |
| 388 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); |
| 389 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); |
| 390 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); |
| 391 |
| 392 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); |
| 393 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); |
| 394 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
| 395 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { |
| 396 printf("GraphicsContext3D: framebuffer was incomplete\n"); |
| 397 |
| 398 // FIXME: cleanup. |
| 399 notImplemented(); |
| 400 } |
| 401 #endif // RENDER_TO_DEBUGGING_WINDOW |
| 402 |
| 403 glClear(GL_COLOR_BUFFER_BIT); |
| 404 viewportImpl(0, 0, width, height); |
| 405 } |
| 406 |
| 407 void GraphicsContext3DInternal::beginPaint(CanvasRenderingContext3D* context) |
| 408 { |
| 409 makeContextCurrent(); |
| 410 |
| 411 #ifdef RENDER_TO_DEBUGGING_WINDOW |
| 412 SwapBuffers(m_canvasDC); |
| 413 #else |
| 414 if (m_quadVBO == 0) { |
| 415 // Prepare necessary objects for rendering. |
| 416 glGenBuffers(1, &m_quadVBO); |
| 417 GLfloat vertices[] = {-1.0f, -1.0f, |
| 418 1.0f, -1.0f, |
| 419 1.0f, 1.0f, |
| 420 -1.0f, -1.0f, |
| 421 1.0f, 1.0f, |
| 422 -1.0f, 1.0f}; |
| 423 glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO); |
| 424 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); |
| 425 // Vertex shader does vertical flip. |
| 426 const GLchar* vertexShaderSrc = |
| 427 "attribute vec2 g_Position;\n" |
| 428 "varying vec2 texCoord;\n" |
| 429 "void main()\n" |
| 430 "{\n" |
| 431 " texCoord = vec2((g_Position.x + 1.0) * 0.5,\n" |
| 432 " (1.0 - g_Position.y) * 0.5);\n" |
| 433 " gl_Position = vec4(g_Position, 0.0, 1.0);\n" |
| 434 "}\n"; |
| 435 // Fragment shader does optional premultiplication of alpha |
| 436 // into color channels. |
| 437 const GLchar* fragmentShaderNoPremultSrc = |
| 438 "varying vec2 texCoord;\n" |
| 439 "uniform sampler2D texSampler;\n" |
| 440 "void main()\n" |
| 441 "{\n" |
| 442 " gl_FragColor = texture2D(texSampler, texCoord);\n" |
| 443 "}\n"; |
| 444 const GLchar* fragmentShaderPremultSrc = |
| 445 "varying vec2 texCoord;\n" |
| 446 "uniform sampler2D texSampler;\n" |
| 447 "void main()\n" |
| 448 "{\n" |
| 449 " vec4 color = texture2D(texSampler, texCoord);\n" |
| 450 " gl_FragColor = vec4(color.r * color.a,\n" |
| 451 " color.g * color.a,\n" |
| 452 " color.b * color.a,\n" |
| 453 " color.a);\n" |
| 454 "}\n"; |
| 455 GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); |
| 456 glShaderSource(vertexShader, 1, &vertexShaderSrc, NULL); |
| 457 checkError(); |
| 458 GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); |
| 459 // FIXME: hook up fragmentShaderPremultSrc based on canvas |
| 460 // context attributes. |
| 461 glShaderSource(fragmentShader, 1, &fragmentShaderNoPremultSrc, NULL); |
| 462 checkError(); |
| 463 m_quadProgram = glCreateProgram(); |
| 464 glAttachShader(m_quadProgram, vertexShader); |
| 465 glAttachShader(m_quadProgram, fragmentShader); |
| 466 glBindAttribLocation(m_quadProgram, 0, "g_Position"); |
| 467 glLinkProgram(m_quadProgram); |
| 468 checkError(); |
| 469 glDeleteShader(vertexShader); |
| 470 glDeleteShader(fragmentShader); |
| 471 m_quadTexLocation = glGetUniformLocation(m_quadProgram, "texSampler"); |
| 472 checkError(); |
| 473 } |
| 474 |
| 475 // We've just rendered a frame into m_texture. Bind m_altTexture |
| 476 // as the framebuffer texture, and draw m_texture on to a quad, |
| 477 // flipping it vertically and performing alpha premultiplication |
| 478 // and color channel swizzling. Then read back the FBO. |
| 479 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_altTexture, 0); |
| 480 glUseProgram(m_quadProgram); |
| 481 glActiveTexture(GL_TEXTURE0); |
| 482 glBindTexture(GL_TEXTURE_2D, m_texture); |
| 483 glUniform1i(m_quadTexLocation, 0); |
| 484 glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO); |
| 485 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); |
| 486 glEnableVertexAttribArray(0); |
| 487 glDisable(GL_DEPTH_TEST); |
| 488 glDisable(GL_BLEND); |
| 489 glDepthMask(false); |
| 490 glColorMask(true, true, true, true); |
| 491 |
| 492 HTMLCanvasElement* canvas = context->canvas(); |
| 493 ImageBuffer* imageBuffer = canvas->buffer(); |
| 494 const SkBitmap& bitmap = *imageBuffer->context()->platformContext()->bitmap(); |
| 495 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); |
| 496 glViewport(0, 0, bitmap.width(), bitmap.height()); |
| 497 |
| 498 glDrawArrays(GL_TRIANGLES, 0, 6); |
| 499 |
| 500 // Read back the frame buffer. |
| 501 SkAutoLockPixels bitmapLock(bitmap); |
| 502 glReadPixels(0, 0, bitmap.width(), bitmap.height(), GL_BGRA, GL_UNSIGNED_BYTE, bitmap.getPixels()); |
| 503 |
| 504 // Restore the previous FBO state. |
| 505 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); |
| 506 |
| 507 // Restore the user's OpenGL state. |
| 508 glUseProgram(m_currentProgram); |
| 509 const VertexAttribPointerState& state = m_vertexAttribPointerState[0]; |
| 510 if (state.buffer) { |
| 511 glBindBuffer(GL_ARRAY_BUFFER, state.buffer); |
| 512 glVertexAttribPointer(state.indx, state.size, state.type, state.normalized, |
| 513 state.stride, reinterpret_cast<void*>(static_cast<intptr_t>(state.offset))); |
| 514 } |
| 515 glBindBuffer(GL_ARRAY_BUFFER, m_boundArrayBuffer); |
| 516 if (state.enabled) |
| 517 glEnableVertexAttribArray(0); |
| 518 else |
| 519 glDisableVertexAttribArray(0); |
| 520 const TextureUnitState& texState = m_textureUnitState[0]; |
| 521 glBindTexture(texState.target, texState.texture); |
| 522 glActiveTexture(m_activeTextureUnit); |
| 523 if (m_blendEnabled) |
| 524 glEnable(GL_BLEND); |
| 525 if (m_depthTestEnabled) |
| 526 glEnable(GL_DEPTH_TEST); |
| 527 glDepthMask(m_depthMaskEnabled); |
| 528 glColorMask(m_colorMask[0], m_colorMask[1], m_colorMask[2], m_colorMask[3]); |
| 529 glViewport(m_viewport[0], m_viewport[1], |
| 530 m_viewport[2], m_viewport[3]); |
| 531 #endif // RENDER_TO_DEBUGGING_WINDOW |
| 532 } |
| 533 |
| 534 bool GraphicsContext3DInternal::validateTextureTarget(int target) |
| 535 { |
| 536 return (target == GL_TEXTURE_2D || |
| 537 target == GL_TEXTURE_CUBE_MAP); |
| 538 } |
| 539 |
| 540 bool GraphicsContext3DInternal::validateTextureParameter(int param) |
| 541 { |
| 542 return (param == GL_TEXTURE_MAG_FILTER || |
| 543 param == GL_TEXTURE_MIN_FILTER || |
| 544 param == GL_TEXTURE_WRAP_S || |
| 545 param == GL_TEXTURE_WRAP_T); |
| 546 } |
| 547 |
| 548 void GraphicsContext3DInternal::activeTexture(unsigned long texture) |
| 549 { |
| 550 // FIXME: query number of textures available. |
| 551 if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32) |
| 552 // FIXME: raise exception. |
| 553 return; |
| 554 |
| 555 makeContextCurrent(); |
| 556 m_activeTextureUnit = texture; |
| 557 glActiveTexture(texture); |
| 558 } |
| 559 |
| 560 void GraphicsContext3DInternal::bindBuffer(unsigned long target, |
| 561 CanvasBuffer* buffer) |
| 562 { |
| 563 makeContextCurrent(); |
| 564 GLuint bufID = EXTRACT(buffer); |
| 565 if (target == GL_ARRAY_BUFFER) |
| 566 m_boundArrayBuffer = bufID; |
| 567 glBindBuffer(target, bufID); |
| 568 } |
| 569 |
| 570 // If we didn't have to hack GL_TEXTURE_WRAP_R for cube maps, |
| 571 // we could just use: |
| 572 // GL_SAME_METHOD_2_X2(BindTexture, bindTexture, unsigned long, CanvasTexture*) |
| 573 void GraphicsContext3DInternal::bindTexture(unsigned long target, |
| 574 CanvasTexture* texture) |
| 575 { |
| 576 makeContextCurrent(); |
| 577 unsigned int textureObject = EXTRACT(texture); |
| 578 |
| 579 if (m_activeTextureUnit == 0) { |
| 580 TextureUnitState& state = m_textureUnitState[m_activeTextureUnit]; |
| 581 state.target = target; |
| 582 state.texture = textureObject; |
| 583 } |
| 584 |
| 585 glBindTexture(target, textureObject); |
| 586 |
| 587 // FIXME: GL_TEXTURE_WRAP_R isn't exposed in the OpenGL ES 2.0 |
| 588 // API. On desktop OpenGL implementations it seems necessary to |
| 589 // set this wrap mode to GL_CLAMP_TO_EDGE to get correct behavior |
| 590 // of cube maps. |
| 591 if (texture != NULL) { |
| 592 if (target == GL_TEXTURE_CUBE_MAP) { |
| 593 if (!texture->isCubeMapRWrapModeInitialized()) { |
| 594 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); |
| 595 texture->setCubeMapRWrapModeInitialized(true); |
| 596 } |
| 597 } else |
| 598 texture->setCubeMapRWrapModeInitialized(false); |
| 599 } |
| 600 } |
| 601 |
| 602 void GraphicsContext3DInternal::bufferDataImpl(unsigned long target, int size, const void* data, unsigned long usage) |
| 603 { |
| 604 makeContextCurrent(); |
| 605 // FIXME: make this verification more efficient. |
| 606 GLint binding = 0; |
| 607 GLenum binding_target = GL_ARRAY_BUFFER_BINDING; |
| 608 if (target == GL_ELEMENT_ARRAY_BUFFER) |
| 609 binding_target = GL_ELEMENT_ARRAY_BUFFER_BINDING; |
| 610 glGetIntegerv(binding_target, &binding); |
| 611 if (binding <= 0) { |
| 612 // FIXME: raise exception. |
| 613 // LogMessagef(("bufferData: no buffer bound")); |
| 614 return; |
| 615 } |
| 616 |
| 617 glBufferData(target, |
| 618 size, |
| 619 data, |
| 620 usage); |
| 621 } |
| 622 |
| 623 void GraphicsContext3DInternal::colorMask(bool red, bool green, bool blue, bool alpha) |
| 624 { |
| 625 makeContextCurrent(); |
| 626 m_colorMask[0] = red; |
| 627 m_colorMask[1] = green; |
| 628 m_colorMask[2] = blue; |
| 629 m_colorMask[3] = alpha; |
| 630 glColorMask(red, green, blue, alpha); |
| 631 } |
| 632 |
| 633 void GraphicsContext3DInternal::depthMask(bool flag) |
| 634 { |
| 635 makeContextCurrent(); |
| 636 m_depthMaskEnabled = flag; |
| 637 glDepthMask(flag); |
| 638 } |
| 639 |
| 640 void GraphicsContext3DInternal::disable(unsigned long cap) |
| 641 { |
| 642 makeContextCurrent(); |
| 643 switch (cap) { |
| 644 case GL_BLEND: |
| 645 m_blendEnabled = false; |
| 646 case GL_DEPTH_TEST: |
| 647 m_depthTestEnabled = false; |
| 648 default: |
| 649 break; |
| 650 } |
| 651 glDisable(cap); |
| 652 } |
| 653 |
| 654 void GraphicsContext3DInternal::disableVertexAttribArray(unsigned long index) |
| 655 { |
| 656 makeContextCurrent(); |
| 657 if (index == 0) { |
| 658 m_vertexAttribPointerState[0].enabled = false; |
| 659 } |
| 660 glDisableVertexAttribArray(index); |
| 661 } |
| 662 |
| 663 void GraphicsContext3DInternal::enable(unsigned long cap) |
| 664 { |
| 665 makeContextCurrent(); |
| 666 switch (cap) { |
| 667 case GL_BLEND: |
| 668 m_blendEnabled = true; |
| 669 case GL_DEPTH_TEST: |
| 670 m_depthTestEnabled = true; |
| 671 default: |
| 672 break; |
| 673 } |
| 674 glEnable(cap); |
| 675 } |
| 676 |
| 677 void GraphicsContext3DInternal::enableVertexAttribArray(unsigned long index) |
| 678 { |
| 679 makeContextCurrent(); |
| 680 if (index == 0) |
| 681 m_vertexAttribPointerState[0].enabled = true; |
| 682 glEnableVertexAttribArray(index); |
| 683 } |
| 684 |
| 685 void GraphicsContext3DInternal::useProgram(CanvasProgram* program) |
| 686 { |
| 687 makeContextCurrent(); |
| 688 m_currentProgram = EXTRACT(program); |
| 689 glUseProgram(m_currentProgram); |
| 690 } |
| 691 |
| 692 void GraphicsContext3DInternal::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, |
| 693 unsigned long stride, unsigned long offset) |
| 694 { |
| 695 makeContextCurrent(); |
| 696 |
| 697 if (m_boundArrayBuffer <= 0) { |
| 698 // FIXME: raise exception. |
| 699 // LogMessagef(("bufferData: no buffer bound")); |
| 700 return; |
| 701 } |
| 702 |
| 703 if (indx == 0) { |
| 704 VertexAttribPointerState& state = m_vertexAttribPointerState[0]; |
| 705 state.buffer = m_boundArrayBuffer; |
| 706 state.indx = indx; |
| 707 state.size = size; |
| 708 state.type = type; |
| 709 state.normalized = normalized; |
| 710 state.stride = stride; |
| 711 state.offset = offset; |
| 712 } |
| 713 |
| 714 glVertexAttribPointer(indx, size, type, normalized, stride, |
| 715 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); |
| 716 } |
| 717 |
| 718 void GraphicsContext3DInternal::viewportImpl(long x, long y, unsigned long width, unsigned long height) |
| 719 { |
| 720 m_viewport[0] = x; |
| 721 m_viewport[1] = y; |
| 722 m_viewport[2] = width; |
| 723 m_viewport[3] = height; |
| 724 glViewport(x, y, width, height); |
| 725 } |
| 726 |
| 727 // GraphicsContext3D ----------------------------------------------------- |
| 728 |
| 729 #define GRAPHICS_CONTEXT_NAME GraphicsContext3D |
| 730 |
| 731 /* Helper macros for when we're just wrapping a gl method, so that |
| 732 * we can avoid having to type this 500 times. Note that these MUST |
| 733 * NOT BE USED if we need to check any of the parameters. |
| 734 */ |
| 735 |
| 736 #define GL_SAME_METHOD_0(glname, name) \ |
| 737 void GRAPHICS_CONTEXT_NAME::##name() \ |
| 738 { \ |
| 739 makeContextCurrent(); gl##glname(); \ |
| 740 } |
| 741 |
| 742 #define GL_SAME_METHOD_1(glname, name, t1) \ |
| 743 void GRAPHICS_CONTEXT_NAME::##name(t1 a1) \ |
| 744 { \ |
| 745 makeContextCurrent(); gl##glname(a1); \ |
| 746 } |
| 747 |
| 748 #define GL_SAME_METHOD_1_X(glname, name, t1) \ |
| 749 void GRAPHICS_CONTEXT_NAME::##name(t1 a1) \ |
| 750 { \ |
| 751 makeContextCurrent(); gl##glname(EXTRACT(a1)); \ |
| 752 } |
| 753 |
| 754 #define GL_SAME_METHOD_2(glname, name, t1, t2) \ |
| 755 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \ |
| 756 { \ |
| 757 makeContextCurrent(); gl##glname(a1,a2); \ |
| 758 } |
| 759 |
| 760 #define GL_SAME_METHOD_2_X12(glname, name, t1, t2) \ |
| 761 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \ |
| 762 { \ |
| 763 makeContextCurrent(); gl##glname(EXTRACT(a1),EXTRACT(a2)); \ |
| 764 } |
| 765 |
| 766 #define GL_SAME_METHOD_2_X2(glname, name, t1, t2) \ |
| 767 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \ |
| 768 { \ |
| 769 makeContextCurrent(); gl##glname(a1,EXTRACT(a2)); \ |
| 770 } |
| 771 |
| 772 #define GL_SAME_METHOD_3(glname, name, t1, t2, t3) \ |
| 773 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \ |
| 774 { \ |
| 775 makeContextCurrent(); gl##glname(a1,a2,a3); \ |
| 776 } |
| 777 |
| 778 #define GL_SAME_METHOD_3_X12(glname, name, t1, t2, t3) \ |
| 779 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \ |
| 780 { \ |
| 781 makeContextCurrent(); gl##glname(EXTRACT(a1),EXTRACT(a2),a3); \ |
| 782 } |
| 783 |
| 784 #define GL_SAME_METHOD_3_X2(glname, name, t1, t2, t3) \ |
| 785 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \ |
| 786 { \ |
| 787 makeContextCurrent(); gl##glname(a1,EXTRACT(a2),a3); \ |
| 788 } |
| 789 |
| 790 #define GL_SAME_METHOD_4(glname, name, t1, t2, t3, t4) \ |
| 791 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4) \ |
| 792 { \ |
| 793 makeContextCurrent(); gl##glname(a1,a2,a3,a4); \ |
| 794 } |
| 795 |
| 796 #define GL_SAME_METHOD_4_X4(glname, name, t1, t2, t3, t4) \ |
| 797 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4) \ |
| 798 { \ |
| 799 makeContextCurrent(); gl##glname(a1,a2,a3,EXTRACT(a4)); \ |
| 800 } |
| 801 |
| 802 #define GL_SAME_METHOD_5(glname, name, t1, t2, t3, t4, t5) \ |
| 803 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \ |
| 804 { \ |
| 805 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5); \ |
| 806 } |
| 807 |
| 808 #define GL_SAME_METHOD_5_X4(glname, name, t1, t2, t3, t4, t5) \ |
| 809 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \ |
| 810 { \ |
| 811 makeContextCurrent(); gl##glname(a1,a2,a3,EXTRACT(a4),a5); \ |
| 812 } |
| 813 |
| 814 #define GL_SAME_METHOD_6(glname, name, t1, t2, t3, t4, t5, t6) \ |
| 815 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \ |
| 816 { \ |
| 817 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5,a6); \ |
| 818 } |
| 819 |
| 820 #define GL_SAME_METHOD_8(glname, name, t1, t2, t3, t4, t5, t6, t7, t8) \ |
| 821 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \ |
| 822 { \ |
| 823 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5,a6,a7,a8); \ |
| 824 } |
| 825 |
| 826 GraphicsContext3D::GraphicsContext3D() |
| 827 : m_currentWidth(0) |
| 828 , m_currentHeight(0) |
| 829 , m_internal(new GraphicsContext3DInternal()) |
| 830 { |
| 831 } |
| 832 |
| 833 GraphicsContext3D::~GraphicsContext3D() |
| 834 { |
| 835 } |
| 836 |
| 837 PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() const |
| 838 { |
| 839 return m_internal->platformGraphicsContext3D(); |
| 840 } |
| 841 |
| 842 Platform3DObject GraphicsContext3D::platformTexture() const |
| 843 { |
| 844 return m_internal->platformTexture(); |
| 845 } |
| 846 |
| 847 void GraphicsContext3D::checkError() const |
| 848 { |
| 849 m_internal->checkError(); |
| 850 } |
| 851 |
| 852 void GraphicsContext3D::makeContextCurrent() |
| 853 { |
| 854 m_internal->makeContextCurrent(); |
| 855 } |
| 856 |
| 857 void GraphicsContext3D::reshape(int width, int height) |
| 858 { |
| 859 if (width == m_currentWidth && height == m_currentHeight) |
| 860 return; |
| 861 |
| 862 m_currentWidth = width; |
| 863 m_currentHeight = height; |
| 864 |
| 865 m_internal->reshape(width, height); |
| 866 } |
| 867 |
| 868 void GraphicsContext3D::beginPaint(CanvasRenderingContext3D* context) |
| 869 { |
| 870 m_internal->beginPaint(context); |
| 871 } |
| 872 |
| 873 void GraphicsContext3D::endPaint() |
| 874 { |
| 875 } |
| 876 |
| 877 int GraphicsContext3D::sizeInBytes(int type) |
| 878 { |
| 879 switch (type) { |
| 880 case GL_BYTE: |
| 881 return sizeof(GLbyte); |
| 882 case GL_UNSIGNED_BYTE: |
| 883 return sizeof(GLubyte); |
| 884 case GL_SHORT: |
| 885 return sizeof(GLshort); |
| 886 case GL_UNSIGNED_SHORT: |
| 887 return sizeof(GLushort); |
| 888 case GL_INT: |
| 889 return sizeof(GLint); |
| 890 case GL_UNSIGNED_INT: |
| 891 return sizeof(GLuint); |
| 892 case GL_FLOAT: |
| 893 return sizeof(GLfloat); |
| 894 default: |
| 895 return 0; |
| 896 } |
| 897 } |
| 898 |
| 899 unsigned GraphicsContext3D::createBuffer() |
| 900 { |
| 901 makeContextCurrent(); |
| 902 GLuint o; |
| 903 glGenBuffers(1, &o); |
| 904 return o; |
| 905 } |
| 906 |
| 907 unsigned GraphicsContext3D::createFramebuffer() |
| 908 { |
| 909 makeContextCurrent(); |
| 910 GLuint o; |
| 911 glGenFramebuffers(1, &o); |
| 912 return o; |
| 913 } |
| 914 |
| 915 unsigned GraphicsContext3D::createProgram() |
| 916 { |
| 917 makeContextCurrent(); |
| 918 return glCreateProgram(); |
| 919 } |
| 920 |
| 921 unsigned GraphicsContext3D::createRenderbuffer() |
| 922 { |
| 923 makeContextCurrent(); |
| 924 GLuint o; |
| 925 glGenRenderbuffers(1, &o); |
| 926 return o; |
| 927 } |
| 928 |
| 929 unsigned GraphicsContext3D::createShader(ShaderType type) |
| 930 { |
| 931 makeContextCurrent(); |
| 932 return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER); |
| 933 } |
| 934 |
| 935 unsigned GraphicsContext3D::createTexture() |
| 936 { |
| 937 makeContextCurrent(); |
| 938 GLuint o; |
| 939 glGenTextures(1, &o); |
| 940 return o; |
| 941 } |
| 942 |
| 943 void GraphicsContext3D::deleteBuffer(unsigned buffer) |
| 944 { |
| 945 makeContextCurrent(); |
| 946 glDeleteBuffers(1, &buffer); |
| 947 } |
| 948 |
| 949 void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer) |
| 950 { |
| 951 makeContextCurrent(); |
| 952 glDeleteFramebuffers(1, &framebuffer); |
| 953 } |
| 954 |
| 955 void GraphicsContext3D::deleteProgram(unsigned program) |
| 956 { |
| 957 makeContextCurrent(); |
| 958 glDeleteProgram(program); |
| 959 } |
| 960 |
| 961 void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer) |
| 962 { |
| 963 makeContextCurrent(); |
| 964 glDeleteRenderbuffers(1, &renderbuffer); |
| 965 } |
| 966 |
| 967 void GraphicsContext3D::deleteShader(unsigned shader) |
| 968 { |
| 969 makeContextCurrent(); |
| 970 glDeleteShader(shader); |
| 971 } |
| 972 |
| 973 void GraphicsContext3D::deleteTexture(unsigned texture) |
| 974 { |
| 975 makeContextCurrent(); |
| 976 glDeleteTextures(1, &texture); |
| 977 } |
| 978 |
| 979 void GraphicsContext3D::activeTexture(unsigned long texture) |
| 980 { |
| 981 m_internal->activeTexture(texture); |
| 982 } |
| 983 |
| 984 GL_SAME_METHOD_2_X12(AttachShader, attachShader, CanvasProgram*, CanvasShader*) |
| 985 |
| 986 void GraphicsContext3D::bindAttribLocation(CanvasProgram* program, |
| 987 unsigned long index, |
| 988 const String& name) |
| 989 { |
| 990 if (!program) |
| 991 return; |
| 992 makeContextCurrent(); |
| 993 glBindAttribLocation(EXTRACT(program), index, name.utf8().data()); |
| 994 } |
| 995 |
| 996 void GraphicsContext3D::bindBuffer(unsigned long target, |
| 997 CanvasBuffer* buffer) |
| 998 { |
| 999 m_internal->bindBuffer(target, buffer); |
| 1000 } |
| 1001 |
| 1002 GL_SAME_METHOD_2_X2(BindFramebuffer, bindFramebuffer, unsigned long, CanvasFramebuffer*) |
| 1003 |
| 1004 GL_SAME_METHOD_2_X2(BindRenderbuffer, bindRenderbuffer, unsigned long, CanvasRenderbuffer*) |
| 1005 |
| 1006 // If we didn't have to hack GL_TEXTURE_WRAP_R for cube maps, |
| 1007 // we could just use: |
| 1008 // GL_SAME_METHOD_2_X2(BindTexture, bindTexture, unsigned long, CanvasTexture*) |
| 1009 void GraphicsContext3D::bindTexture(unsigned long target, |
| 1010 CanvasTexture* texture) |
| 1011 { |
| 1012 m_internal->bindTexture(target, texture); |
| 1013 } |
| 1014 |
| 1015 GL_SAME_METHOD_4(BlendColor, blendColor, double, double, double, double) |
| 1016 |
| 1017 GL_SAME_METHOD_1(BlendEquation, blendEquation, unsigned long) |
| 1018 |
| 1019 GL_SAME_METHOD_2(BlendEquationSeparate, blendEquationSeparate, unsigned long, unsigned long) |
| 1020 |
| 1021 GL_SAME_METHOD_2(BlendFunc, blendFunc, unsigned long, unsigned long) |
| 1022 |
| 1023 GL_SAME_METHOD_4(BlendFuncSeparate, blendFuncSeparate, unsigned long, unsigned long, unsigned long, unsigned long) |
| 1024 |
| 1025 void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage) |
| 1026 { |
| 1027 m_internal->bufferDataImpl(target, size, NULL, usage); |
| 1028 } |
| 1029 |
| 1030 void GraphicsContext3D::bufferData(unsigned long target, CanvasArray* array, unsigned long usage) |
| 1031 { |
| 1032 m_internal->bufferDataImpl(target, array->sizeInBytes(), array->baseAddress(), usage); |
| 1033 } |
| 1034 |
| 1035 void GraphicsContext3D::bufferSubData(unsigned long target, long offset, CanvasArray* array) |
| 1036 { |
| 1037 if (!array || !array->length()) |
| 1038 return; |
| 1039 |
| 1040 makeContextCurrent(); |
| 1041 // FIXME: make this verification more efficient. |
| 1042 GLint binding = 0; |
| 1043 GLenum binding_target = GL_ARRAY_BUFFER_BINDING; |
| 1044 if (target == GL_ELEMENT_ARRAY_BUFFER) |
| 1045 binding_target = GL_ELEMENT_ARRAY_BUFFER_BINDING; |
| 1046 glGetIntegerv(binding_target, &binding); |
| 1047 if (binding <= 0) { |
| 1048 // FIXME: raise exception. |
| 1049 // LogMessagef(("bufferSubData: no buffer bound")); |
| 1050 return; |
| 1051 } |
| 1052 glBufferSubData(target, offset, array->sizeInBytes(), array->baseAddress()); |
| 1053 } |
| 1054 |
| 1055 unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target) |
| 1056 { |
| 1057 makeContextCurrent(); |
| 1058 return glCheckFramebufferStatus(target); |
| 1059 } |
| 1060 |
| 1061 GL_SAME_METHOD_1(Clear, clear, unsigned long) |
| 1062 |
| 1063 GL_SAME_METHOD_4(ClearColor, clearColor, double, double, double, double) |
| 1064 |
| 1065 GL_SAME_METHOD_1(ClearDepth, clearDepth, double) |
| 1066 |
| 1067 GL_SAME_METHOD_1(ClearStencil, clearStencil, long) |
| 1068 |
| 1069 void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha) |
| 1070 { |
| 1071 m_internal->colorMask(red, green, blue, alpha); |
| 1072 } |
| 1073 |
| 1074 GL_SAME_METHOD_1_X(CompileShader, compileShader, CanvasShader*) |
| 1075 |
| 1076 GL_SAME_METHOD_8(CopyTexImage2D, copyTexImage2D, unsigned long, long, unsigned long, long, long, unsigned long, unsigned long, long) |
| 1077 |
| 1078 GL_SAME_METHOD_8(CopyTexSubImage2D, copyTexSubImage2D, unsigned long, long, long, long, long, long, unsigned long, unsigned long) |
| 1079 |
| 1080 GL_SAME_METHOD_1(CullFace, cullFace, unsigned long) |
| 1081 |
| 1082 GL_SAME_METHOD_1(DepthFunc, depthFunc, unsigned long) |
| 1083 |
| 1084 void GraphicsContext3D::depthMask(bool flag) |
| 1085 { |
| 1086 m_internal->depthMask(flag); |
| 1087 } |
| 1088 |
| 1089 GL_SAME_METHOD_2(DepthRange, depthRange, double, double) |
| 1090 |
| 1091 void GraphicsContext3D::detachShader(CanvasProgram* program, CanvasShader* shader) |
| 1092 { |
| 1093 if (!program || !shader) |
| 1094 return; |
| 1095 |
| 1096 makeContextCurrent(); |
| 1097 glDetachShader(EXTRACT(program), EXTRACT(shader)); |
| 1098 } |
| 1099 |
| 1100 void GraphicsContext3D::disable(unsigned long cap) |
| 1101 { |
| 1102 m_internal->disable(cap); |
| 1103 } |
| 1104 |
| 1105 void GraphicsContext3D::disableVertexAttribArray(unsigned long index) |
| 1106 { |
| 1107 m_internal->disableVertexAttribArray(index); |
| 1108 } |
| 1109 |
| 1110 void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count) |
| 1111 { |
| 1112 switch (mode) { |
| 1113 case GL_TRIANGLES: |
| 1114 case GL_TRIANGLE_STRIP: |
| 1115 case GL_TRIANGLE_FAN: |
| 1116 case GL_POINTS: |
| 1117 case GL_LINE_STRIP: |
| 1118 case GL_LINE_LOOP: |
| 1119 case GL_LINES: |
| 1120 break; |
| 1121 default: |
| 1122 // FIXME: output log message, raise exception. |
| 1123 // LogMessage(NS_LITERAL_CSTRING("drawArrays: invalid mode")); |
| 1124 // return NS_ERROR_DOM_SYNTAX_ERR; |
| 1125 return; |
| 1126 } |
| 1127 |
| 1128 if (first+count < first || first+count < count) { |
| 1129 // FIXME: output log message, raise exception. |
| 1130 // LogMessage(NS_LITERAL_CSTRING("drawArrays: overflow in first+count")); |
| 1131 // return NS_ERROR_INVALID_ARG; |
| 1132 return; |
| 1133 } |
| 1134 |
| 1135 // FIXME: validate against currently bound buffer. |
| 1136 // if (!ValidateBuffers(first+count)) |
| 1137 // return NS_ERROR_INVALID_ARG; |
| 1138 |
| 1139 makeContextCurrent(); |
| 1140 glDrawArrays(mode, first, count); |
| 1141 } |
| 1142 |
| 1143 void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset) |
| 1144 { |
| 1145 makeContextCurrent(); |
| 1146 // FIXME: make this verification more efficient. |
| 1147 GLint binding = 0; |
| 1148 GLenum binding_target = GL_ELEMENT_ARRAY_BUFFER_BINDING; |
| 1149 glGetIntegerv(binding_target, &binding); |
| 1150 if (binding <= 0) { |
| 1151 // FIXME: raise exception. |
| 1152 // LogMessagef(("bufferData: no buffer bound")); |
| 1153 return; |
| 1154 } |
| 1155 glDrawElements(mode, count, type, |
| 1156 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); |
| 1157 } |
| 1158 |
| 1159 void GraphicsContext3D::enable(unsigned long cap) |
| 1160 { |
| 1161 m_internal->enable(cap); |
| 1162 } |
| 1163 |
| 1164 void GraphicsContext3D::enableVertexAttribArray(unsigned long index) |
| 1165 { |
| 1166 m_internal->enableVertexAttribArray(index); |
| 1167 } |
| 1168 |
| 1169 GL_SAME_METHOD_0(Finish, finish) |
| 1170 |
| 1171 GL_SAME_METHOD_0(Flush, flush) |
| 1172 |
| 1173 GL_SAME_METHOD_4_X4(FramebufferRenderbuffer, framebufferRenderbuffer, unsigned long, unsigned long, unsigned long, CanvasRenderbuffer*) |
| 1174 |
| 1175 GL_SAME_METHOD_5_X4(FramebufferTexture2D, framebufferTexture2D, unsigned long, unsigned long, unsigned long, CanvasTexture*, long) |
| 1176 |
| 1177 GL_SAME_METHOD_1(FrontFace, frontFace, unsigned long) |
| 1178 |
| 1179 void GraphicsContext3D::generateMipmap(unsigned long target) |
| 1180 { |
| 1181 makeContextCurrent(); |
| 1182 if (glGenerateMipmapEXT) { |
| 1183 glGenerateMipmapEXT(target); |
| 1184 } |
| 1185 // FIXME: provide alternative code path? This will be unpleasant |
| 1186 // to implement if glGenerateMipmapEXT is not available -- it will |
| 1187 // require a texture readback and re-upload. |
| 1188 } |
| 1189 |
| 1190 int GraphicsContext3D::getAttribLocation(CanvasProgram* program, const String& name) |
| 1191 { |
| 1192 if (!program) |
| 1193 return -1; |
| 1194 |
| 1195 makeContextCurrent(); |
| 1196 return glGetAttribLocation(EXTRACT(program), name.utf8().data()); |
| 1197 } |
| 1198 |
| 1199 bool GraphicsContext3D::getBoolean(unsigned long pname) |
| 1200 { |
| 1201 makeContextCurrent(); |
| 1202 GLboolean val; |
| 1203 // FIXME: validate pname to ensure it returns only a single value. |
| 1204 glGetBooleanv(pname, &val); |
| 1205 return static_cast<bool>(val); |
| 1206 } |
| 1207 |
| 1208 PassRefPtr<CanvasUnsignedByteArray> GraphicsContext3D::getBooleanv(unsigned long pname) |
| 1209 { |
| 1210 // FIXME: implement. |
| 1211 notImplemented(); |
| 1212 return NULL; |
| 1213 } |
| 1214 |
| 1215 int GraphicsContext3D::getBufferParameteri(unsigned long target, unsigned long pname) |
| 1216 { |
| 1217 makeContextCurrent(); |
| 1218 GLint data; |
| 1219 glGetBufferParameteriv(target, pname, &data); |
| 1220 return static_cast<int>(data); |
| 1221 } |
| 1222 |
| 1223 PassRefPtr<CanvasIntArray> GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname) |
| 1224 { |
| 1225 // FIXME: implement. |
| 1226 notImplemented(); |
| 1227 return NULL; |
| 1228 } |
| 1229 |
| 1230 unsigned long GraphicsContext3D::getError() |
| 1231 { |
| 1232 makeContextCurrent(); |
| 1233 return glGetError(); |
| 1234 } |
| 1235 |
| 1236 float GraphicsContext3D::getFloat(unsigned long pname) |
| 1237 { |
| 1238 makeContextCurrent(); |
| 1239 GLfloat val; |
| 1240 // FIXME: validate pname to ensure it returns only a single value. |
| 1241 glGetFloatv(pname, &val); |
| 1242 return static_cast<float>(val); |
| 1243 } |
| 1244 |
| 1245 PassRefPtr<CanvasFloatArray> GraphicsContext3D::getFloatv(unsigned long pname) |
| 1246 { |
| 1247 // FIXME: implement. |
| 1248 notImplemented(); |
| 1249 return NULL; |
| 1250 } |
| 1251 |
| 1252 int GraphicsContext3D::getFramebufferAttachmentParameteri(unsigned long target, |
| 1253 unsigned long attachment, |
| 1254 unsigned long pname) |
| 1255 { |
| 1256 makeContextCurrent(); |
| 1257 GLint data; |
| 1258 glGetFramebufferAttachmentParameteriv(target, attachment, pname, &data); |
| 1259 return static_cast<int>(data); |
| 1260 } |
| 1261 |
| 1262 PassRefPtr<CanvasIntArray> GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, |
| 1263 unsigned long attachment, |
| 1264 unsigned long pname) |
| 1265 { |
| 1266 // FIXME: implement. |
| 1267 notImplemented(); |
| 1268 return NULL; |
| 1269 } |
| 1270 |
| 1271 int GraphicsContext3D::getInteger(unsigned long pname) |
| 1272 { |
| 1273 makeContextCurrent(); |
| 1274 GLint val; |
| 1275 // FIXME: validate pname to ensure it returns only a single value. |
| 1276 glGetIntegerv(pname, &val); |
| 1277 return static_cast<int>(val); |
| 1278 } |
| 1279 |
| 1280 PassRefPtr<CanvasIntArray> GraphicsContext3D::getIntegerv(unsigned long pname) |
| 1281 { |
| 1282 // FIXME: implement. |
| 1283 notImplemented(); |
| 1284 return NULL; |
| 1285 } |
| 1286 |
| 1287 int GraphicsContext3D::getProgrami(CanvasProgram* program, |
| 1288 unsigned long pname) |
| 1289 { |
| 1290 makeContextCurrent(); |
| 1291 GLint param; |
| 1292 glGetProgramiv(EXTRACT(program), pname, ¶m); |
| 1293 return static_cast<int>(param); |
| 1294 } |
| 1295 |
| 1296 PassRefPtr<CanvasIntArray> GraphicsContext3D::getProgramiv(CanvasProgram* program, |
| 1297 unsigned long pname) |
| 1298 { |
| 1299 // FIXME: implement. |
| 1300 notImplemented(); |
| 1301 return NULL; |
| 1302 } |
| 1303 |
| 1304 String GraphicsContext3D::getProgramInfoLog(CanvasProgram* program) |
| 1305 { |
| 1306 makeContextCurrent(); |
| 1307 GLuint programID = EXTRACT(program); |
| 1308 GLint logLength; |
| 1309 glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logLength); |
| 1310 if (logLength == 0) |
| 1311 return String(); |
| 1312 GLchar* log = NULL; |
| 1313 if (!tryFastMalloc(logLength * sizeof(GLchar)).getValue(log)) |
| 1314 return String(); |
| 1315 GLsizei returnedLogLength; |
| 1316 glGetProgramInfoLog(programID, logLength, &returnedLogLength, log); |
| 1317 ASSERT(logLength == returnedLogLength + 1); |
| 1318 String res = String::fromUTF8(log, returnedLogLength); |
| 1319 fastFree(log); |
| 1320 return res; |
| 1321 } |
| 1322 |
| 1323 int GraphicsContext3D::getRenderbufferParameteri(unsigned long target, |
| 1324 unsigned long pname) |
| 1325 { |
| 1326 makeContextCurrent(); |
| 1327 GLint param; |
| 1328 glGetRenderbufferParameteriv(target, pname, ¶m); |
| 1329 return static_cast<int>(param); |
| 1330 } |
| 1331 |
| 1332 PassRefPtr<CanvasIntArray> GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, |
| 1333 unsigned long pname) |
| 1334 { |
| 1335 // FIXME: implement. |
| 1336 notImplemented(); |
| 1337 return NULL; |
| 1338 } |
| 1339 |
| 1340 int GraphicsContext3D::getShaderi(CanvasShader* shader, |
| 1341 unsigned long pname) |
| 1342 { |
| 1343 makeContextCurrent(); |
| 1344 GLint param; |
| 1345 glGetShaderiv(EXTRACT(shader), pname, ¶m); |
| 1346 return static_cast<int>(param); |
| 1347 } |
| 1348 |
| 1349 PassRefPtr<CanvasIntArray> GraphicsContext3D::getShaderiv(CanvasShader* shader, |
| 1350 unsigned long pname) |
| 1351 { |
| 1352 // FIXME: implement. |
| 1353 notImplemented(); |
| 1354 return NULL; |
| 1355 } |
| 1356 |
| 1357 String GraphicsContext3D::getShaderInfoLog(CanvasShader* shader) |
| 1358 { |
| 1359 makeContextCurrent(); |
| 1360 GLuint shaderID = EXTRACT(shader); |
| 1361 GLint logLength; |
| 1362 glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength); |
| 1363 if (logLength == 0) |
| 1364 return String(); |
| 1365 GLchar* log = NULL; |
| 1366 if (!tryFastMalloc(logLength * sizeof(GLchar)).getValue(log)) |
| 1367 return String(); |
| 1368 GLsizei returnedLogLength; |
| 1369 glGetShaderInfoLog(shaderID, logLength, &returnedLogLength, log); |
| 1370 ASSERT(logLength == returnedLogLength + 1); |
| 1371 String res = String::fromUTF8(log, returnedLogLength); |
| 1372 fastFree(log); |
| 1373 return res; |
| 1374 } |
| 1375 |
| 1376 String GraphicsContext3D::getShaderSource(CanvasShader* shader) |
| 1377 { |
| 1378 makeContextCurrent(); |
| 1379 GLuint shaderID = EXTRACT(shader); |
| 1380 GLint logLength; |
| 1381 glGetShaderiv(shaderID, GL_SHADER_SOURCE_LENGTH, &logLength); |
| 1382 if (logLength == 0) |
| 1383 return String(); |
| 1384 GLchar* log = NULL; |
| 1385 if (!tryFastMalloc(logLength * sizeof(GLchar)).getValue(log)) |
| 1386 return String(); |
| 1387 GLsizei returnedLogLength; |
| 1388 glGetShaderSource(shaderID, logLength, &returnedLogLength, log); |
| 1389 ASSERT(logLength == returnedLogLength + 1); |
| 1390 String res = String::fromUTF8(log, returnedLogLength); |
| 1391 fastFree(log); |
| 1392 return res; |
| 1393 } |
| 1394 |
| 1395 String GraphicsContext3D::getString(unsigned long name) |
| 1396 { |
| 1397 makeContextCurrent(); |
| 1398 return String::fromUTF8(reinterpret_cast<const char*>(glGetString(name))); |
| 1399 } |
| 1400 |
| 1401 float GraphicsContext3D::getTexParameterf(unsigned long target, unsigned long pname) |
| 1402 { |
| 1403 makeContextCurrent(); |
| 1404 if (!m_internal->validateTextureTarget(target)) { |
| 1405 // FIXME: throw exception. |
| 1406 return 0; |
| 1407 } |
| 1408 |
| 1409 if (!m_internal->validateTextureParameter(pname)) { |
| 1410 // FIXME: throw exception. |
| 1411 return 0; |
| 1412 } |
| 1413 |
| 1414 GLfloat param; |
| 1415 glGetTexParameterfv(target, pname, ¶m); |
| 1416 return static_cast<float>(param); |
| 1417 } |
| 1418 |
| 1419 PassRefPtr<CanvasFloatArray> GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname) |
| 1420 { |
| 1421 // FIXME: implement. |
| 1422 notImplemented(); |
| 1423 return NULL; |
| 1424 } |
| 1425 |
| 1426 int GraphicsContext3D::getTexParameteri(unsigned long target, unsigned long pname) |
| 1427 { |
| 1428 makeContextCurrent(); |
| 1429 if (!m_internal->validateTextureTarget(target)) { |
| 1430 // FIXME: throw exception. |
| 1431 return 0; |
| 1432 } |
| 1433 |
| 1434 if (!m_internal->validateTextureParameter(pname)) { |
| 1435 // FIXME: throw exception. |
| 1436 return 0; |
| 1437 } |
| 1438 |
| 1439 GLint param; |
| 1440 glGetTexParameteriv(target, pname, ¶m); |
| 1441 return static_cast<int>(param); |
| 1442 } |
| 1443 |
| 1444 PassRefPtr<CanvasIntArray> GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname) |
| 1445 { |
| 1446 // FIXME: implement. |
| 1447 notImplemented(); |
| 1448 return NULL; |
| 1449 } |
| 1450 |
| 1451 float GraphicsContext3D::getUniformf(CanvasProgram* program, long location) |
| 1452 { |
| 1453 // FIXME: implement. |
| 1454 notImplemented(); |
| 1455 return 0; |
| 1456 } |
| 1457 |
| 1458 PassRefPtr<CanvasFloatArray> GraphicsContext3D::getUniformfv(CanvasProgram* program, long location) |
| 1459 { |
| 1460 // FIXME: implement. |
| 1461 notImplemented(); |
| 1462 return NULL; |
| 1463 } |
| 1464 |
| 1465 int GraphicsContext3D::getUniformi(CanvasProgram* program, long location) |
| 1466 { |
| 1467 // FIXME: implement. |
| 1468 notImplemented(); |
| 1469 return 0; |
| 1470 } |
| 1471 |
| 1472 PassRefPtr<CanvasIntArray> GraphicsContext3D::getUniformiv(CanvasProgram* program, long location) |
| 1473 { |
| 1474 // FIXME: implement. |
| 1475 notImplemented(); |
| 1476 return NULL; |
| 1477 } |
| 1478 |
| 1479 long GraphicsContext3D::getUniformLocation(CanvasProgram* program, const String& name) |
| 1480 { |
| 1481 if (!program) |
| 1482 return -1; |
| 1483 |
| 1484 makeContextCurrent(); |
| 1485 return glGetUniformLocation(EXTRACT(program), name.utf8().data()); |
| 1486 } |
| 1487 |
| 1488 float GraphicsContext3D::getVertexAttribf(unsigned long index, |
| 1489 unsigned long pname) |
| 1490 { |
| 1491 // FIXME: implement. |
| 1492 notImplemented(); |
| 1493 return 0; |
| 1494 } |
| 1495 |
| 1496 PassRefPtr<CanvasFloatArray> GraphicsContext3D::getVertexAttribfv(unsigned long index, |
| 1497 unsigned long pname) |
| 1498 { |
| 1499 // FIXME: implement. |
| 1500 notImplemented(); |
| 1501 return NULL; |
| 1502 } |
| 1503 |
| 1504 int GraphicsContext3D::getVertexAttribi(unsigned long index, |
| 1505 unsigned long pname) |
| 1506 { |
| 1507 // FIXME: implement. |
| 1508 notImplemented(); |
| 1509 return NULL; |
| 1510 } |
| 1511 |
| 1512 PassRefPtr<CanvasIntArray> GraphicsContext3D::getVertexAttribiv(unsigned long index, |
| 1513 unsigned long pname) |
| 1514 { |
| 1515 // FIXME: implement. |
| 1516 notImplemented(); |
| 1517 return NULL; |
| 1518 } |
| 1519 |
| 1520 long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long pname) |
| 1521 { |
| 1522 // FIXME: implement. |
| 1523 notImplemented(); |
| 1524 return 0; |
| 1525 } |
| 1526 |
| 1527 GL_SAME_METHOD_2(Hint, hint, unsigned long, unsigned long); |
| 1528 |
| 1529 bool GraphicsContext3D::isBuffer(CanvasBuffer* buffer) |
| 1530 { |
| 1531 makeContextCurrent(); |
| 1532 return glIsBuffer(EXTRACT(buffer)); |
| 1533 } |
| 1534 |
| 1535 bool GraphicsContext3D::isEnabled(unsigned long cap) |
| 1536 { |
| 1537 makeContextCurrent(); |
| 1538 return glIsEnabled(cap); |
| 1539 } |
| 1540 |
| 1541 bool GraphicsContext3D::isFramebuffer(CanvasFramebuffer* framebuffer) |
| 1542 { |
| 1543 makeContextCurrent(); |
| 1544 return glIsFramebuffer(EXTRACT(framebuffer)); |
| 1545 } |
| 1546 |
| 1547 bool GraphicsContext3D::isProgram(CanvasProgram* program) |
| 1548 { |
| 1549 makeContextCurrent(); |
| 1550 return glIsProgram(EXTRACT(program)); |
| 1551 } |
| 1552 |
| 1553 bool GraphicsContext3D::isRenderbuffer(CanvasRenderbuffer* renderbuffer) |
| 1554 { |
| 1555 makeContextCurrent(); |
| 1556 return glIsRenderbuffer(EXTRACT(renderbuffer)); |
| 1557 } |
| 1558 |
| 1559 bool GraphicsContext3D::isShader(CanvasShader* shader) |
| 1560 { |
| 1561 makeContextCurrent(); |
| 1562 return glIsShader(EXTRACT(shader)); |
| 1563 } |
| 1564 |
| 1565 bool GraphicsContext3D::isTexture(CanvasTexture* texture) |
| 1566 { |
| 1567 makeContextCurrent(); |
| 1568 return glIsTexture(EXTRACT(texture)); |
| 1569 } |
| 1570 |
| 1571 GL_SAME_METHOD_1(LineWidth, lineWidth, double) |
| 1572 |
| 1573 GL_SAME_METHOD_1_X(LinkProgram, linkProgram, CanvasProgram*) |
| 1574 |
| 1575 void GraphicsContext3D::pixelStorei(unsigned long pname, long param) |
| 1576 { |
| 1577 if (pname != GL_PACK_ALIGNMENT && |
| 1578 pname != GL_UNPACK_ALIGNMENT) { |
| 1579 // FIXME: force fake GL error to be produced and throw |
| 1580 // exception. |
| 1581 return; |
| 1582 } |
| 1583 |
| 1584 makeContextCurrent(); |
| 1585 glPixelStorei(pname, param); |
| 1586 } |
| 1587 |
| 1588 GL_SAME_METHOD_2(PolygonOffset, polygonOffset, double, double) |
| 1589 |
| 1590 void GraphicsContext3D::releaseShaderCompiler() |
| 1591 { |
| 1592 } |
| 1593 |
| 1594 GL_SAME_METHOD_4(RenderbufferStorage, renderbufferStorage, unsigned long, unsigned long, unsigned long, unsigned long) |
| 1595 |
| 1596 GL_SAME_METHOD_2(SampleCoverage, sampleCoverage, double, bool) |
| 1597 |
| 1598 GL_SAME_METHOD_4(Scissor, scissor, long, long, unsigned long, unsigned long) |
| 1599 |
| 1600 void GraphicsContext3D::shaderSource(CanvasShader* shader, const String& source) |
| 1601 { |
| 1602 makeContextCurrent(); |
| 1603 CString str = source.utf8(); |
| 1604 const char* data = str.data(); |
| 1605 GLint length = str.length(); |
| 1606 glShaderSource(EXTRACT(shader), 1, &data, &length); |
| 1607 } |
| 1608 |
| 1609 GL_SAME_METHOD_3(StencilFunc, stencilFunc, unsigned long, long, unsigned long) |
| 1610 |
| 1611 GL_SAME_METHOD_4(StencilFuncSeparate, stencilFuncSeparate, unsigned long, unsigned long, long, unsigned long) |
| 1612 |
| 1613 GL_SAME_METHOD_1(StencilMask, stencilMask, unsigned long) |
| 1614 |
| 1615 GL_SAME_METHOD_2(StencilMaskSeparate, stencilMaskSeparate, unsigned long, unsigned long) |
| 1616 |
| 1617 GL_SAME_METHOD_3(StencilOp, stencilOp, unsigned long, unsigned long, unsigned long) |
| 1618 |
| 1619 GL_SAME_METHOD_4(StencilOpSeparate, stencilOpSeparate, unsigned long, unsigned long, unsigned long, unsigned long) |
| 1620 |
| 1621 int GraphicsContext3D::texImage2D(unsigned target, |
| 1622 unsigned level, |
| 1623 unsigned internalformat, |
| 1624 unsigned width, |
| 1625 unsigned height, |
| 1626 unsigned border, |
| 1627 unsigned format, |
| 1628 unsigned type, |
| 1629 CanvasArray* pixels) |
| 1630 { |
| 1631 // FIXME: must do validation similar to JOGL's to ensure that |
| 1632 // the incoming array is of the appropriate length. |
| 1633 glTexImage2D(target, |
| 1634 level, |
| 1635 internalformat, |
| 1636 width, |
| 1637 height, |
| 1638 border, |
| 1639 format, |
| 1640 type, |
| 1641 pixels->baseAddress()); |
| 1642 return 0; |
| 1643 } |
| 1644 |
| 1645 int GraphicsContext3D::texImage2D(unsigned target, |
| 1646 unsigned level, |
| 1647 unsigned internalformat, |
| 1648 unsigned width, |
| 1649 unsigned height, |
| 1650 unsigned border, |
| 1651 unsigned format, |
| 1652 unsigned type, |
| 1653 ImageData* pixels) |
| 1654 { |
| 1655 // FIXME: implement. |
| 1656 notImplemented(); |
| 1657 return -1; |
| 1658 } |
| 1659 |
| 1660 // Remove premultiplied alpha from color channels. |
| 1661 // FIXME: this is lossy. Must retrieve original values from HTMLImageElement. |
| 1662 static void unmultiplyAlpha(unsigned char* rgbaData, int numPixels) |
| 1663 { |
| 1664 for (int j = 0; j < numPixels; j++) { |
| 1665 float b = rgbaData[4*j+0] / 255.0f; |
| 1666 float g = rgbaData[4*j+1] / 255.0f; |
| 1667 float r = rgbaData[4*j+2] / 255.0f; |
| 1668 float a = rgbaData[4*j+3] / 255.0f; |
| 1669 if (a > 0.0f) { |
| 1670 b /= a; |
| 1671 g /= a; |
| 1672 r /= a; |
| 1673 b = (b > 1.0f) ? 1.0f : b; |
| 1674 g = (g > 1.0f) ? 1.0f : g; |
| 1675 r = (r > 1.0f) ? 1.0f : r; |
| 1676 rgbaData[4*j+0] = (unsigned char) (b * 255.0f); |
| 1677 rgbaData[4*j+1] = (unsigned char) (g * 255.0f); |
| 1678 rgbaData[4*j+2] = (unsigned char) (r * 255.0f); |
| 1679 } |
| 1680 } |
| 1681 } |
| 1682 |
| 1683 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, |
| 1684 bool flipY, bool premultiplyAlpha) |
| 1685 { |
| 1686 CachedImage* cachedImage = image->cachedImage(); |
| 1687 if (cachedImage == NULL) { |
| 1688 ASSERT_NOT_REACHED(); |
| 1689 return -1; |
| 1690 } |
| 1691 Image* img = cachedImage->image(); |
| 1692 NativeImageSkia* skiaImage = img->nativeImageForCurrentFrame(); |
| 1693 if (skiaImage == NULL) { |
| 1694 ASSERT_NOT_REACHED(); |
| 1695 return -1; |
| 1696 } |
| 1697 SkBitmap::Config skiaConfig = skiaImage->config(); |
| 1698 // FIXME: must support more image configurations. |
| 1699 if (skiaConfig != SkBitmap::kARGB_8888_Config) { |
| 1700 ASSERT_NOT_REACHED(); |
| 1701 return -1; |
| 1702 } |
| 1703 SkBitmap& skiaImageRef = *skiaImage; |
| 1704 SkAutoLockPixels lock(skiaImageRef); |
| 1705 int width = skiaImage->width(); |
| 1706 int height = skiaImage->height(); |
| 1707 if (flipY) { |
| 1708 // Need to flip images vertically. To avoid making a copy of |
| 1709 // the entire image, we perform a ton of glTexSubImage2D |
| 1710 // calls. FIXME: should rethink this strategy for efficiency. |
| 1711 glTexImage2D(target, level, GL_RGBA8, |
| 1712 width, |
| 1713 height, |
| 1714 0, |
| 1715 GL_BGRA, |
| 1716 GL_UNSIGNED_BYTE, |
| 1717 NULL); |
| 1718 unsigned char* pixels = |
| 1719 reinterpret_cast<unsigned char*>(skiaImage->getPixels()); |
| 1720 int rowBytes = skiaImage->rowBytes(); |
| 1721 |
| 1722 unsigned char* row = NULL; |
| 1723 bool allocatedRow = false; |
| 1724 if (!premultiplyAlpha) { |
| 1725 row = new unsigned char[rowBytes]; |
| 1726 allocatedRow = true; |
| 1727 } |
| 1728 for (int i = 0; i < height; i++) { |
| 1729 if (premultiplyAlpha) |
| 1730 row = pixels + (rowBytes * i); |
| 1731 else { |
| 1732 memcpy(row, pixels + (rowBytes * i), rowBytes); |
| 1733 unmultiplyAlpha(row, width); |
| 1734 } |
| 1735 glTexSubImage2D(target, level, 0, height - i - 1, |
| 1736 width, 1, |
| 1737 GL_BGRA, |
| 1738 GL_UNSIGNED_BYTE, |
| 1739 row); |
| 1740 } |
| 1741 if (allocatedRow) |
| 1742 delete[] row; |
| 1743 } else { |
| 1744 // The pixels of cube maps' faces are defined with a top-down |
| 1745 // scanline ordering, unlike GL_TEXTURE_2D, so when uploading |
| 1746 // these, the above vertical flip is the wrong thing to do. |
| 1747 if (premultiplyAlpha) |
| 1748 glTexImage2D(target, level, GL_RGBA8, |
| 1749 width, |
| 1750 height, |
| 1751 0, |
| 1752 GL_BGRA, |
| 1753 GL_UNSIGNED_BYTE, |
| 1754 skiaImage->getPixels()); |
| 1755 else { |
| 1756 glTexImage2D(target, level, GL_RGBA8, |
| 1757 width, |
| 1758 height, |
| 1759 0, |
| 1760 GL_BGRA, |
| 1761 GL_UNSIGNED_BYTE, |
| 1762 NULL); |
| 1763 unsigned char* pixels = |
| 1764 reinterpret_cast<unsigned char*>(skiaImage->getPixels()); |
| 1765 int rowBytes = skiaImage->rowBytes(); |
| 1766 unsigned char* row = new unsigned char[rowBytes]; |
| 1767 for (int i = 0; i < height; i++) { |
| 1768 memcpy(row, pixels + (rowBytes * i), rowBytes); |
| 1769 unmultiplyAlpha(row, width); |
| 1770 glTexSubImage2D(target, level, 0, i, |
| 1771 width, 1, |
| 1772 GL_BGRA, |
| 1773 GL_UNSIGNED_BYTE, |
| 1774 row); |
| 1775 } |
| 1776 delete[] row; |
| 1777 } |
| 1778 } |
| 1779 return 0; |
| 1780 } |
| 1781 |
| 1782 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, |
| 1783 bool flipY, bool premultiplyAlpha) |
| 1784 { |
| 1785 // FIXME: implement. |
| 1786 notImplemented(); |
| 1787 return -1; |
| 1788 } |
| 1789 |
| 1790 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, |
| 1791 bool flipY, bool premultiplyAlpha) |
| 1792 { |
| 1793 // FIXME: implement. |
| 1794 notImplemented(); |
| 1795 return -1; |
| 1796 } |
| 1797 |
| 1798 GL_SAME_METHOD_3(TexParameterf, texParameterf, unsigned, unsigned, float); |
| 1799 |
| 1800 GL_SAME_METHOD_3(TexParameteri, texParameteri, unsigned, unsigned, int); |
| 1801 |
| 1802 int GraphicsContext3D::texSubImage2D(unsigned target, |
| 1803 unsigned level, |
| 1804 unsigned xoffset, |
| 1805 unsigned yoffset, |
| 1806 unsigned width, |
| 1807 unsigned height, |
| 1808 unsigned format, |
| 1809 unsigned type, |
| 1810 CanvasArray* pixels) |
| 1811 { |
| 1812 // FIXME: implement. |
| 1813 notImplemented(); |
| 1814 return -1; |
| 1815 } |
| 1816 |
| 1817 int GraphicsContext3D::texSubImage2D(unsigned target, |
| 1818 unsigned level, |
| 1819 unsigned xoffset, |
| 1820 unsigned yoffset, |
| 1821 unsigned width, |
| 1822 unsigned height, |
| 1823 unsigned format, |
| 1824 unsigned type, |
| 1825 ImageData* pixels) |
| 1826 { |
| 1827 // FIXME: implement. |
| 1828 notImplemented(); |
| 1829 return -1; |
| 1830 } |
| 1831 |
| 1832 int GraphicsContext3D::texSubImage2D(unsigned target, |
| 1833 unsigned level, |
| 1834 unsigned xoffset, |
| 1835 unsigned yoffset, |
| 1836 unsigned width, |
| 1837 unsigned height, |
| 1838 HTMLImageElement* image, |
| 1839 bool flipY, |
| 1840 bool premultiplyAlpha) |
| 1841 { |
| 1842 // FIXME: implement. |
| 1843 notImplemented(); |
| 1844 return -1; |
| 1845 } |
| 1846 |
| 1847 int GraphicsContext3D::texSubImage2D(unsigned target, |
| 1848 unsigned level, |
| 1849 unsigned xoffset, |
| 1850 unsigned yoffset, |
| 1851 unsigned width, |
| 1852 unsigned height, |
| 1853 HTMLCanvasElement* canvas, |
| 1854 bool flipY, |
| 1855 bool premultiplyAlpha) |
| 1856 { |
| 1857 // FIXME: implement. |
| 1858 notImplemented(); |
| 1859 return -1; |
| 1860 } |
| 1861 |
| 1862 int GraphicsContext3D::texSubImage2D(unsigned target, |
| 1863 unsigned level, |
| 1864 unsigned xoffset, |
| 1865 unsigned yoffset, |
| 1866 unsigned width, |
| 1867 unsigned height, |
| 1868 HTMLVideoElement* video, |
| 1869 bool flipY, |
| 1870 bool premultiplyAlpha) |
| 1871 { |
| 1872 // FIXME: implement. |
| 1873 notImplemented(); |
| 1874 return -1; |
| 1875 } |
| 1876 |
| 1877 GL_SAME_METHOD_2(Uniform1f, uniform1f, long, float) |
| 1878 |
| 1879 void GraphicsContext3D::uniform1fv(long location, float* v, int size) |
| 1880 { |
| 1881 makeContextCurrent(); |
| 1882 glUniform1fv(location, size, v); |
| 1883 } |
| 1884 |
| 1885 GL_SAME_METHOD_2(Uniform1i, uniform1i, long, int) |
| 1886 |
| 1887 void GraphicsContext3D::uniform1iv(long location, int* v, int size) |
| 1888 { |
| 1889 makeContextCurrent(); |
| 1890 glUniform1iv(location, size, v); |
| 1891 } |
| 1892 |
| 1893 GL_SAME_METHOD_3(Uniform2f, uniform2f, long, float, float) |
| 1894 |
| 1895 void GraphicsContext3D::uniform2fv(long location, float* v, int size) |
| 1896 { |
| 1897 makeContextCurrent(); |
| 1898 glUniform2fv(location, size, v); |
| 1899 } |
| 1900 |
| 1901 GL_SAME_METHOD_3(Uniform2i, uniform2i, long, int, int) |
| 1902 |
| 1903 void GraphicsContext3D::uniform2iv(long location, int* v, int size) |
| 1904 { |
| 1905 makeContextCurrent(); |
| 1906 glUniform2iv(location, size, v); |
| 1907 } |
| 1908 |
| 1909 GL_SAME_METHOD_4(Uniform3f, uniform3f, long, float, float, float) |
| 1910 |
| 1911 void GraphicsContext3D::uniform3fv(long location, float* v, int size) |
| 1912 { |
| 1913 makeContextCurrent(); |
| 1914 glUniform3fv(location, size, v); |
| 1915 } |
| 1916 |
| 1917 GL_SAME_METHOD_4(Uniform3i, uniform3i, long, int, int, int) |
| 1918 |
| 1919 void GraphicsContext3D::uniform3iv(long location, int* v, int size) |
| 1920 { |
| 1921 makeContextCurrent(); |
| 1922 glUniform3iv(location, size, v); |
| 1923 } |
| 1924 |
| 1925 GL_SAME_METHOD_5(Uniform4f, uniform4f, long, float, float, float, float) |
| 1926 |
| 1927 void GraphicsContext3D::uniform4fv(long location, float* v, int size) |
| 1928 { |
| 1929 makeContextCurrent(); |
| 1930 glUniform4fv(location, size, v); |
| 1931 } |
| 1932 |
| 1933 GL_SAME_METHOD_5(Uniform4i, uniform4i, long, int, int, int, int) |
| 1934 |
| 1935 void GraphicsContext3D::uniform4iv(long location, int* v, int size) |
| 1936 { |
| 1937 makeContextCurrent(); |
| 1938 glUniform4iv(location, size, v); |
| 1939 } |
| 1940 |
| 1941 void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* value, int size) |
| 1942 { |
| 1943 makeContextCurrent(); |
| 1944 glUniformMatrix2fv(location, size, transpose, value); |
| 1945 } |
| 1946 |
| 1947 void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* value, int size) |
| 1948 { |
| 1949 makeContextCurrent(); |
| 1950 glUniformMatrix3fv(location, size, transpose, value); |
| 1951 } |
| 1952 |
| 1953 void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* value, int size) |
| 1954 { |
| 1955 makeContextCurrent(); |
| 1956 glUniformMatrix4fv(location, size, transpose, value); |
| 1957 } |
| 1958 |
| 1959 void GraphicsContext3D::useProgram(CanvasProgram* program) |
| 1960 { |
| 1961 m_internal->useProgram(program); |
| 1962 } |
| 1963 |
| 1964 GL_SAME_METHOD_1_X(ValidateProgram, validateProgram, CanvasProgram*) |
| 1965 |
| 1966 GL_SAME_METHOD_2(VertexAttrib1f, vertexAttrib1f, unsigned long, float) |
| 1967 |
| 1968 void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* values) |
| 1969 { |
| 1970 makeContextCurrent(); |
| 1971 glVertexAttrib1fv(indx, values); |
| 1972 } |
| 1973 |
| 1974 GL_SAME_METHOD_3(VertexAttrib2f, vertexAttrib2f, unsigned long, float, float) |
| 1975 |
| 1976 void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* values) |
| 1977 { |
| 1978 makeContextCurrent(); |
| 1979 glVertexAttrib2fv(indx, values); |
| 1980 } |
| 1981 |
| 1982 GL_SAME_METHOD_4(VertexAttrib3f, vertexAttrib3f, unsigned long, float, float, float) |
| 1983 |
| 1984 void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* values) |
| 1985 { |
| 1986 makeContextCurrent(); |
| 1987 glVertexAttrib3fv(indx, values); |
| 1988 } |
| 1989 |
| 1990 GL_SAME_METHOD_5(VertexAttrib4f, vertexAttrib4f, unsigned long, float, float, float, float) |
| 1991 |
| 1992 void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* values) |
| 1993 { |
| 1994 makeContextCurrent(); |
| 1995 glVertexAttrib4fv(indx, values); |
| 1996 } |
| 1997 |
| 1998 void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, |
| 1999 unsigned long stride, unsigned long offset) |
| 2000 { |
| 2001 m_internal->vertexAttribPointer(indx, size, type, normalized, stride, offset); |
| 2002 } |
| 2003 |
| 2004 void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height) |
| 2005 { |
| 2006 makeContextCurrent(); |
| 2007 m_internal->viewportImpl(x, y, width, height); |
| 2008 } |
| 2009 |
| 2010 } |
| 2011 |
| 2012 #endif // ENABLE(3D_CANVAS) |
OLD | NEW |