| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 #include <wtf/FastMalloc.h> | 56 #include <wtf/FastMalloc.h> |
| 57 | 57 |
| 58 #include <stdio.h> | 58 #include <stdio.h> |
| 59 | 59 |
| 60 #if PLATFORM(WIN_OS) | 60 #if PLATFORM(WIN_OS) |
| 61 #include <windows.h> | 61 #include <windows.h> |
| 62 #endif | 62 #endif |
| 63 | 63 |
| 64 #include "GL/glew.h" | 64 #include "GL/glew.h" |
| 65 | 65 |
| 66 #if PLATFORM(CG) |
| 67 #include "GraphicsContext.h" |
| 68 #include <CoreGraphics/CGContext.h> |
| 69 #include <CoreGraphics/CGBitmapContext.h> |
| 70 #include <CoreGraphics/CGImage.h> |
| 71 #include <OpenGL/OpenGL.h> |
| 72 #else |
| 73 #define FLIP_FRAMEBUFFER_VERTICALLY |
| 74 #endif |
| 75 |
| 76 #if PLATFORM(SKIA) |
| 66 #include "NativeImageSkia.h" | 77 #include "NativeImageSkia.h" |
| 78 #endif |
| 79 |
| 80 #if PLATFORM(DARWIN) |
| 81 #define USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER |
| 82 #endif |
| 67 | 83 |
| 68 using namespace std; | 84 using namespace std; |
| 69 | 85 |
| 70 namespace WebCore { | 86 namespace WebCore { |
| 71 | 87 |
| 72 // GraphicsContext3DInternal ----------------------------------------------------- | 88 // GraphicsContext3DInternal ----------------------------------------------------- |
| 73 | 89 |
| 74 // Uncomment this to render to a separate window for debugging | 90 // Uncomment this to render to a separate window for debugging |
| 75 // #define RENDER_TO_DEBUGGING_WINDOW | 91 // #define RENDER_TO_DEBUGGING_WINDOW |
| 76 | 92 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 93 | 109 |
| 94 bool validateTextureTarget(int target); | 110 bool validateTextureTarget(int target); |
| 95 bool validateTextureParameter(int param); | 111 bool validateTextureParameter(int param); |
| 96 | 112 |
| 97 void activeTexture(unsigned long texture); | 113 void activeTexture(unsigned long texture); |
| 98 void bindBuffer(unsigned long target, | 114 void bindBuffer(unsigned long target, |
| 99 CanvasBuffer* buffer); | 115 CanvasBuffer* buffer); |
| 100 void bindTexture(unsigned long target, | 116 void bindTexture(unsigned long target, |
| 101 CanvasTexture* texture); | 117 CanvasTexture* texture); |
| 102 void bufferDataImpl(unsigned long target, int size, const void* data, unsigned long usage); | 118 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); | 119 void disableVertexAttribArray(unsigned long index); |
| 107 void enable(unsigned long cap); | |
| 108 void enableVertexAttribArray(unsigned long index); | 120 void enableVertexAttribArray(unsigned long index); |
| 109 void useProgram(CanvasProgram* program); | |
| 110 void vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, | 121 void vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, |
| 111 unsigned long stride, unsigned long offset); | 122 unsigned long stride, unsigned long offset); |
| 112 void viewportImpl(long x, long y, unsigned long width, unsigned long height); | 123 void viewportImpl(long x, long y, unsigned long width, unsigned long height); |
| 113 | 124 |
| 114 private: | 125 private: |
| 115 unsigned int m_texture; | 126 unsigned int m_texture; |
| 116 unsigned int m_fbo; | 127 unsigned int m_fbo; |
| 117 unsigned int m_depthBuffer; | 128 unsigned int m_depthBuffer; |
| 129 unsigned int m_cachedWidth, m_cachedHeight; |
| 118 | 130 |
| 119 // Objects for flipping the render output vertically | 131 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| 120 unsigned int m_altTexture; | 132 unsigned char* m_scanline; |
| 121 unsigned int m_quadVBO; | 133 void flipVertically(unsigned char* framebuffer, |
| 122 unsigned int m_quadProgram; | 134 unsigned int width, |
| 123 unsigned int m_quadTexLocation; | 135 unsigned int height); |
| 136 #endif |
| 124 | 137 |
| 125 // Storage for saving/restoring buffer, vertex attribute, | 138 // Note: we aren't currently using this information, but we will |
| 126 // blending, and program state when drawing flipped quad | 139 // need to in order to verify that all enabled vertex arrays have |
| 127 unsigned int m_currentProgram; | 140 // a valid buffer bound -- to avoid crashes on certain cards. |
| 128 bool m_blendEnabled; | |
| 129 bool m_depthTestEnabled; | |
| 130 bool m_depthMaskEnabled; | |
| 131 bool m_colorMask[4]; | |
| 132 unsigned int m_boundArrayBuffer; | 141 unsigned int m_boundArrayBuffer; |
| 133 class VertexAttribPointerState { | 142 class VertexAttribPointerState { |
| 134 public: | 143 public: |
| 135 VertexAttribPointerState(); | 144 VertexAttribPointerState(); |
| 136 | 145 |
| 137 bool enabled; | 146 bool enabled; |
| 138 unsigned long buffer; | 147 unsigned long buffer; |
| 139 unsigned long indx; | 148 unsigned long indx; |
| 140 int size; | 149 int size; |
| 141 int type; | 150 int type; |
| 142 bool normalized; | 151 bool normalized; |
| 143 unsigned long stride; | 152 unsigned long stride; |
| 144 unsigned long offset; | 153 unsigned long offset; |
| 145 }; | 154 }; |
| 146 VertexAttribPointerState m_vertexAttribPointerState[1]; | |
| 147 unsigned int m_activeTextureUnit; | |
| 148 class TextureUnitState { | |
| 149 public: | |
| 150 TextureUnitState(); | |
| 151 | 155 |
| 152 unsigned long target; | 156 enum { |
| 153 unsigned int texture; | 157 NumTrackedPointerStates = 2 |
| 154 }; | 158 }; |
| 155 TextureUnitState m_textureUnitState[1]; | 159 VertexAttribPointerState m_vertexAttribPointerState[NumTrackedPointerStates]; |
| 156 int m_viewport[4]; | |
| 157 | 160 |
| 158 #if PLATFORM(WIN_OS) | 161 #if PLATFORM(WIN_OS) |
| 159 HWND m_canvasWindow; | 162 HWND m_canvasWindow; |
| 160 HDC m_canvasDC; | 163 HDC m_canvasDC; |
| 161 HGLRC m_contextObj; | 164 HGLRC m_contextObj; |
| 165 #elif PLATFORM(CG) |
| 166 CGLPBufferObj m_pbuffer; |
| 167 CGLContextObj m_contextObj; |
| 168 unsigned char* m_renderOutput; |
| 169 CGContextRef m_cgContext; |
| 162 #else | 170 #else |
| 163 #error Must port GraphicsContext3D to your platform | 171 #error Must port GraphicsContext3D to your platform |
| 164 #endif | 172 #endif |
| 165 }; | 173 }; |
| 166 | 174 |
| 167 GraphicsContext3DInternal::VertexAttribPointerState::VertexAttribPointerState() | 175 GraphicsContext3DInternal::VertexAttribPointerState::VertexAttribPointerState() |
| 168 : enabled(false) | 176 : enabled(false) |
| 169 , buffer(0) | 177 , buffer(0) |
| 170 , indx(0) | 178 , indx(0) |
| 171 , size(0) | 179 , size(0) |
| 172 , type(0) | 180 , type(0) |
| 173 , normalized(false) | 181 , normalized(false) |
| 174 , stride(0) | 182 , stride(0) |
| 175 , offset(0) | 183 , offset(0) |
| 176 { | 184 { |
| 177 } | 185 } |
| 178 | 186 |
| 179 GraphicsContext3DInternal::TextureUnitState::TextureUnitState() | |
| 180 : target(0) | |
| 181 , texture(0) | |
| 182 { | |
| 183 } | |
| 184 | |
| 185 GraphicsContext3DInternal::GraphicsContext3DInternal() | 187 GraphicsContext3DInternal::GraphicsContext3DInternal() |
| 186 : m_texture(0) | 188 : m_texture(0) |
| 187 , m_fbo(0) | 189 , m_fbo(0) |
| 188 , m_depthBuffer(0) | 190 , m_depthBuffer(0) |
| 189 , m_altTexture(0) | 191 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| 190 , m_quadVBO(0) | 192 , m_scanline(NULL) |
| 191 , m_quadProgram(0) | 193 #endif |
| 192 , m_quadTexLocation(0) | |
| 193 , m_currentProgram(0) | |
| 194 , m_blendEnabled(false) | |
| 195 , m_depthTestEnabled(false) | |
| 196 , m_depthMaskEnabled(true) | |
| 197 , m_boundArrayBuffer(0) | 194 , m_boundArrayBuffer(0) |
| 198 , m_activeTextureUnit(0) | |
| 199 #if PLATFORM(WIN_OS) | 195 #if PLATFORM(WIN_OS) |
| 200 , m_canvasWindow(NULL) | 196 , m_canvasWindow(NULL) |
| 201 , m_canvasDC(NULL) | 197 , m_canvasDC(NULL) |
| 202 , m_contextObj(NULL) | 198 , m_contextObj(NULL) |
| 199 #elif PLATFORM(CG) |
| 200 , m_pbuffer(NULL) |
| 201 , m_contextObj(NULL) |
| 202 , m_renderOutput(NULL) |
| 203 , m_cgContext(NULL) |
| 203 #else | 204 #else |
| 204 #error Must port to your platform | 205 #error Must port to your platform |
| 205 #endif | 206 #endif |
| 206 { | 207 { |
| 207 for (int i = 0; i < 4; i++) { | |
| 208 m_viewport[i] = 0; | |
| 209 m_colorMask[i] = true; | |
| 210 } | |
| 211 #if PLATFORM(WIN_OS) | 208 #if PLATFORM(WIN_OS) |
| 212 WNDCLASS wc; | 209 WNDCLASS wc; |
| 213 if (!GetClassInfo(GetModuleHandle(NULL), L"CANVASGL", &wc)) { | 210 if (!GetClassInfo(GetModuleHandle(NULL), L"CANVASGL", &wc)) { |
| 214 ZeroMemory(&wc, sizeof(WNDCLASS)); | 211 ZeroMemory(&wc, sizeof(WNDCLASS)); |
| 215 wc.style = CS_OWNDC; | 212 wc.style = CS_OWNDC; |
| 216 wc.hInstance = GetModuleHandle(NULL); | 213 wc.hInstance = GetModuleHandle(NULL); |
| 217 wc.lpfnWndProc = DefWindowProc; | 214 wc.lpfnWndProc = DefWindowProc; |
| 218 wc.lpszClassName = L"CANVASGL"; | 215 wc.lpszClassName = L"CANVASGL"; |
| 219 | 216 |
| 220 if (!RegisterClass(&wc)) { | 217 if (!RegisterClass(&wc)) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 } | 267 } |
| 271 | 268 |
| 272 #ifdef RENDER_TO_DEBUGGING_WINDOW | 269 #ifdef RENDER_TO_DEBUGGING_WINDOW |
| 273 typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); | 270 typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); |
| 274 PFNWGLSWAPINTERVALEXTPROC setSwapInterval = NULL; | 271 PFNWGLSWAPINTERVALEXTPROC setSwapInterval = NULL; |
| 275 setSwapInterval = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); | 272 setSwapInterval = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); |
| 276 if (setSwapInterval != NULL) | 273 if (setSwapInterval != NULL) |
| 277 setSwapInterval(1); | 274 setSwapInterval(1); |
| 278 #endif // RENDER_TO_DEBUGGING_WINDOW | 275 #endif // RENDER_TO_DEBUGGING_WINDOW |
| 279 | 276 |
| 277 #elif PLATFORM(CG) |
| 278 // Create a 1x1 pbuffer and associated context to bootstrap things |
| 279 CGLPixelFormatAttribute attribs[] = { |
| 280 (CGLPixelFormatAttribute) kCGLPFAPBuffer, |
| 281 (CGLPixelFormatAttribute) 0 |
| 282 }; |
| 283 CGLPixelFormatObj pixelFormat; |
| 284 GLint numPixelFormats; |
| 285 if (CGLChoosePixelFormat(attribs, &pixelFormat, &numPixelFormats) != kCGLNoError) { |
| 286 printf("GraphicsContext3D: error choosing pixel format\n"); |
| 287 return; |
| 288 } |
| 289 if (pixelFormat == NULL) { |
| 290 printf("GraphicsContext3D: no pixel format selected\n"); |
| 291 return; |
| 292 } |
| 293 CGLContextObj context; |
| 294 CGLError res = CGLCreateContext(pixelFormat, NULL, &context); |
| 295 CGLDestroyPixelFormat(pixelFormat); |
| 296 if (res != kCGLNoError) { |
| 297 printf("GraphicsContext3D: error creating context\n"); |
| 298 return; |
| 299 } |
| 300 CGLPBufferObj pbuffer; |
| 301 if (CGLCreatePBuffer(1, 1, GL_TEXTURE_2D, GL_RGBA, 0, &pbuffer) != kCGLNoError) { |
| 302 CGLDestroyContext(context); |
| 303 printf("GraphicsContext3D: error creating pbuffer\n"); |
| 304 return; |
| 305 } |
| 306 if (CGLSetPBuffer(context, pbuffer, 0, 0, 0) != kCGLNoError) { |
| 307 CGLDestroyContext(context); |
| 308 CGLDestroyPBuffer(pbuffer); |
| 309 printf("GraphicsContext3D: error attaching pbuffer to context\n"); |
| 310 return; |
| 311 } |
| 312 if (CGLSetCurrentContext(context) != kCGLNoError) { |
| 313 CGLDestroyContext(context); |
| 314 CGLDestroyPBuffer(pbuffer); |
| 315 printf("GraphicsContext3D: error making context current\n"); |
| 316 return; |
| 317 } |
| 318 m_pbuffer = pbuffer; |
| 319 m_contextObj = context; |
| 280 #else | 320 #else |
| 281 #error Must port to your platform | 321 #error Must port to your platform |
| 282 #endif | 322 #endif |
| 283 | 323 |
| 284 // Initialize GLEW and check for GL 2.0 support by the drivers. | 324 // Initialize GLEW and check for GL 2.0 support by the drivers. |
| 285 GLenum glewInitResult = glewInit(); | 325 GLenum glewInitResult = glewInit(); |
| 326 if (glewInitResult != GLEW_OK) { |
| 327 printf("GraphicsContext3D: GLEW initialization failed\n"); |
| 328 return; |
| 329 } |
| 286 if (!glewIsSupported("GL_VERSION_2_0")) { | 330 if (!glewIsSupported("GL_VERSION_2_0")) { |
| 287 printf("GraphicsContext3D: OpenGL 2.0 not supported\n"); | 331 printf("GraphicsContext3D: OpenGL 2.0 not supported\n"); |
| 288 return; | 332 return; |
| 289 } | 333 } |
| 290 } | 334 } |
| 291 | 335 |
| 292 GraphicsContext3DInternal::~GraphicsContext3DInternal() | 336 GraphicsContext3DInternal::~GraphicsContext3DInternal() |
| 293 { | 337 { |
| 294 makeContextCurrent(); | 338 makeContextCurrent(); |
| 295 #ifndef RENDER_TO_DEBUGGING_WINDOW | 339 #ifndef RENDER_TO_DEBUGGING_WINDOW |
| 296 glDeleteRenderbuffersEXT(1, &m_depthBuffer); | 340 glDeleteRenderbuffersEXT(1, &m_depthBuffer); |
| 297 glDeleteTextures(1, &m_texture); | 341 glDeleteTextures(1, &m_texture); |
| 298 glDeleteTextures(1, &m_altTexture); | 342 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| 343 if (m_scanline != NULL) |
| 344 delete[] m_scanline; |
| 345 #endif |
| 299 glDeleteFramebuffersEXT(1, &m_fbo); | 346 glDeleteFramebuffersEXT(1, &m_fbo); |
| 300 #endif // !RENDER_TO_DEBUGGING_WINDOW | 347 #endif // !RENDER_TO_DEBUGGING_WINDOW |
| 301 #if PLATFORM(WIN_OS) | 348 #if PLATFORM(WIN_OS) |
| 302 wglMakeCurrent(NULL, NULL); | 349 wglMakeCurrent(NULL, NULL); |
| 303 wglDeleteContext(m_contextObj); | 350 wglDeleteContext(m_contextObj); |
| 304 ReleaseDC(m_canvasWindow, m_canvasDC); | 351 ReleaseDC(m_canvasWindow, m_canvasDC); |
| 305 DestroyWindow(m_canvasWindow); | 352 DestroyWindow(m_canvasWindow); |
| 353 #elif PLATFORM(CG) |
| 354 CGLSetCurrentContext(NULL); |
| 355 CGLDestroyContext(m_contextObj); |
| 356 CGLDestroyPBuffer(m_pbuffer); |
| 357 if (m_cgContext != NULL) |
| 358 CGContextRelease(m_cgContext); |
| 359 if (m_renderOutput != NULL) |
| 360 delete[] m_renderOutput; |
| 306 #else | 361 #else |
| 307 #error Must port to your platform | 362 #error Must port to your platform |
| 308 #endif | 363 #endif |
| 309 m_contextObj = NULL; | 364 m_contextObj = NULL; |
| 310 } | 365 } |
| 311 | 366 |
| 312 void GraphicsContext3DInternal::checkError() const | 367 void GraphicsContext3DInternal::checkError() const |
| 313 { | 368 { |
| 314 // FIXME: This needs to only be done in the debug context. It | 369 // FIXME: This needs to only be done in the debug context. It |
| 315 // will need to throw an exception on error. | 370 // will need to throw an exception on error. |
| 316 GLenum error = glGetError(); | 371 GLenum error = glGetError(); |
| 317 if (error != GL_NO_ERROR) { | 372 if (error != GL_NO_ERROR) { |
| 318 printf("GL Error : %x\n", error); | 373 printf("GraphicsContext3DInternal: GL Error : %x\n", error); |
| 319 notImplemented(); | 374 notImplemented(); |
| 320 } | 375 } |
| 321 } | 376 } |
| 322 | 377 |
| 323 bool GraphicsContext3DInternal::makeContextCurrent() | 378 bool GraphicsContext3DInternal::makeContextCurrent() |
| 324 { | 379 { |
| 325 #if PLATFORM(WIN_OS) | 380 #if PLATFORM(WIN_OS) |
| 326 if (wglGetCurrentContext() != m_contextObj) | 381 if (wglGetCurrentContext() != m_contextObj) |
| 327 if (wglMakeCurrent(m_canvasDC, m_contextObj)) | 382 if (wglMakeCurrent(m_canvasDC, m_contextObj)) |
| 328 return true; | 383 return true; |
| 384 #elif PLATFORM(CG) |
| 385 if (CGLGetCurrentContext() != m_contextObj) |
| 386 if (CGLSetCurrentContext(m_contextObj) == kCGLNoError) |
| 387 return true; |
| 329 #else | 388 #else |
| 330 #error Must port to your platform | 389 #error Must port to your platform |
| 331 #endif | 390 #endif |
| 332 return false; | 391 return false; |
| 333 } | 392 } |
| 334 | 393 |
| 335 PlatformGraphicsContext3D GraphicsContext3DInternal::platformGraphicsContext3D() const | 394 PlatformGraphicsContext3D GraphicsContext3DInternal::platformGraphicsContext3D() const |
| 336 { | 395 { |
| 337 return m_contextObj; | 396 return m_contextObj; |
| 338 } | 397 } |
| 339 | 398 |
| 340 Platform3DObject GraphicsContext3DInternal::platformTexture() const | 399 Platform3DObject GraphicsContext3DInternal::platformTexture() const |
| 341 { | 400 { |
| 342 return m_texture; | 401 return m_texture; |
| 343 } | 402 } |
| 344 | 403 |
| 345 static int createTextureObject() | 404 static int createTextureObject(GLenum target) |
| 346 { | 405 { |
| 347 GLuint texture = 0; | 406 GLuint texture = 0; |
| 348 glGenTextures(1, &texture); | 407 glGenTextures(1, &texture); |
| 349 glBindTexture(GL_TEXTURE_2D, texture); | 408 glBindTexture(target, texture); |
| 350 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 409 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 351 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 410 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 352 return texture; | 411 return texture; |
| 353 } | 412 } |
| 354 | 413 |
| 355 void GraphicsContext3DInternal::reshape(int width, int height) | 414 void GraphicsContext3DInternal::reshape(int width, int height) |
| 356 { | 415 { |
| 357 #ifdef RENDER_TO_DEBUGGING_WINDOW | 416 #ifdef RENDER_TO_DEBUGGING_WINDOW |
| 358 SetWindowPos(m_canvasWindow, HWND_TOP, 0, 0, width, height, | 417 SetWindowPos(m_canvasWindow, HWND_TOP, 0, 0, width, height, |
| 359 SWP_NOMOVE); | 418 SWP_NOMOVE); |
| 360 ShowWindow(m_canvasWindow, SW_SHOW); | 419 ShowWindow(m_canvasWindow, SW_SHOW); |
| 361 #endif | 420 #endif |
| 362 | 421 |
| 422 m_cachedWidth = width; |
| 423 m_cachedHeight = height; |
| 363 makeContextCurrent(); | 424 makeContextCurrent(); |
| 364 | 425 |
| 365 #ifndef RENDER_TO_DEBUGGING_WINDOW | 426 #ifndef RENDER_TO_DEBUGGING_WINDOW |
| 427 #ifdef USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER |
| 428 // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on Mac OS X |
| 429 GLenum target = GL_TEXTURE_RECTANGLE_ARB; |
| 430 #else |
| 431 GLenum target = GL_TEXTURE_2D; |
| 432 #endif |
| 366 if (m_texture == 0) { | 433 if (m_texture == 0) { |
| 367 // Generate the texture objects | 434 // Generate the texture object |
| 368 m_texture = createTextureObject(); | 435 m_texture = createTextureObject(target); |
| 369 m_altTexture = createTextureObject(); | |
| 370 | |
| 371 // Generate the framebuffer object | 436 // Generate the framebuffer object |
| 372 glGenFramebuffersEXT(1, &m_fbo); | 437 glGenFramebuffersEXT(1, &m_fbo); |
| 373 | |
| 374 // Generate the depth buffer | 438 // Generate the depth buffer |
| 375 glGenRenderbuffersEXT(1, &m_depthBuffer); | 439 glGenRenderbuffersEXT(1, &m_depthBuffer); |
| 376 | |
| 377 checkError(); | 440 checkError(); |
| 378 } | 441 } |
| 379 | 442 |
| 380 // Reallocate the color and depth buffers | 443 // Reallocate the color and depth buffers |
| 381 glBindTexture(GL_TEXTURE_2D, m_texture); | 444 glBindTexture(target, m_texture); |
| 382 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); | 445 glTexImage2D(target, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
| 383 glBindTexture(GL_TEXTURE_2D, m_altTexture); | 446 glBindTexture(target, 0); |
| 384 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); | |
| 385 glBindTexture(GL_TEXTURE_2D, 0); | |
| 386 | 447 |
| 387 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); | 448 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); |
| 388 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); | 449 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); |
| 389 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); | 450 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); |
| 390 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); | 451 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); |
| 391 | 452 |
| 392 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); | 453 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target, m_texture, 0); |
| 393 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); | 454 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); |
| 394 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | 455 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
| 395 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { | 456 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { |
| 396 printf("GraphicsContext3D: framebuffer was incomplete\n"); | 457 printf("GraphicsContext3D: framebuffer was incomplete\n"); |
| 397 | 458 |
| 398 // FIXME: cleanup. | 459 // FIXME: cleanup. |
| 399 notImplemented(); | 460 notImplemented(); |
| 400 } | 461 } |
| 401 #endif // RENDER_TO_DEBUGGING_WINDOW | 462 #endif // RENDER_TO_DEBUGGING_WINDOW |
| 463 |
| 464 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| 465 if (m_scanline != NULL) { |
| 466 delete[] m_scanline; |
| 467 m_scanline = NULL; |
| 468 } |
| 469 m_scanline = new unsigned char[width * 4]; |
| 470 #endif // FLIP_FRAMEBUFFER_VERTICALLY |
| 402 | 471 |
| 403 glClear(GL_COLOR_BUFFER_BIT); | 472 glClear(GL_COLOR_BUFFER_BIT); |
| 404 viewportImpl(0, 0, width, height); | 473 viewportImpl(0, 0, width, height); |
| 474 |
| 475 #if PLATFORM(CG) |
| 476 // Need to reallocate the client-side backing store. |
| 477 // FIXME: make this more efficient. |
| 478 if (m_cgContext != NULL) { |
| 479 CGContextRelease(m_cgContext); |
| 480 m_cgContext = NULL; |
| 481 } |
| 482 if (m_renderOutput != NULL) { |
| 483 delete[] m_renderOutput; |
| 484 m_renderOutput = NULL; |
| 485 } |
| 486 int rowBytes = width * 4; |
| 487 m_renderOutput = new unsigned char[height * rowBytes]; |
| 488 CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); |
| 489 m_cgContext = CGBitmapContextCreate(m_renderOutput, width, height, 8, rowBytes, |
| 490 colorSpace, kCGImageAlphaPremultipliedLast); |
| 491 CGColorSpaceRelease(colorSpace); |
| 492 #endif // PLATFORM(CG) |
| 405 } | 493 } |
| 406 | 494 |
| 495 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| 496 void GraphicsContext3DInternal::flipVertically(unsigned char* framebuffer, |
| 497 unsigned int width, |
| 498 unsigned int height) |
| 499 { |
| 500 unsigned char* scanline = m_scanline; |
| 501 if (scanline == NULL) |
| 502 return; |
| 503 unsigned int rowBytes = width * 4; |
| 504 unsigned int count = height / 2; |
| 505 for (unsigned int i = 0; i < count; i++) { |
| 506 unsigned char* rowA = framebuffer + i * rowBytes; |
| 507 unsigned char* rowB = framebuffer + (height - i - 1) * rowBytes; |
| 508 // FIXME: this is where the multiplication of the alpha |
| 509 // channel into the color buffer will need to occur if the |
| 510 // user specifies the "premultiplyAlpha" flag in the context |
| 511 // creation attributes. |
| 512 memcpy(scanline, rowB, rowBytes); |
| 513 memcpy(rowB, rowA, rowBytes); |
| 514 memcpy(rowA, scanline, rowBytes); |
| 515 } |
| 516 } |
| 517 #endif |
| 518 |
| 407 void GraphicsContext3DInternal::beginPaint(CanvasRenderingContext3D* context) | 519 void GraphicsContext3DInternal::beginPaint(CanvasRenderingContext3D* context) |
| 408 { | 520 { |
| 409 makeContextCurrent(); | 521 makeContextCurrent(); |
| 410 | 522 |
| 411 #ifdef RENDER_TO_DEBUGGING_WINDOW | 523 #ifdef RENDER_TO_DEBUGGING_WINDOW |
| 412 SwapBuffers(m_canvasDC); | 524 SwapBuffers(m_canvasDC); |
| 413 #else | 525 #else |
| 414 if (m_quadVBO == 0) { | 526 // Earlier versions of this code used the GPU to flip the |
| 415 // Prepare necessary objects for rendering. | 527 // framebuffer vertically before reading it back for compositing |
| 416 glGenBuffers(1, &m_quadVBO); | 528 // via software. This code was quite complicated, used a lot of |
| 417 GLfloat vertices[] = {-1.0f, -1.0f, | 529 // GPU memory, and didn't provide an obvious speedup. Since this |
| 418 1.0f, -1.0f, | 530 // vertical flip is only a temporary solution anyway until Chrome |
| 419 1.0f, 1.0f, | 531 // is fully GPU composited, it wasn't worth the complexity. |
| 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 | 532 |
| 492 HTMLCanvasElement* canvas = context->canvas(); | 533 HTMLCanvasElement* canvas = context->canvas(); |
| 493 ImageBuffer* imageBuffer = canvas->buffer(); | 534 ImageBuffer* imageBuffer = canvas->buffer(); |
| 535 unsigned char* pixels = NULL; |
| 536 #if PLATFORM(SKIA) |
| 494 const SkBitmap& bitmap = *imageBuffer->context()->platformContext()->bitmap(); | 537 const SkBitmap& bitmap = *imageBuffer->context()->platformContext()->bitmap(); |
| 495 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); | 538 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); |
| 496 glViewport(0, 0, bitmap.width(), bitmap.height()); | 539 ASSERT(bitmap.width() == m_cachedWidth); |
| 497 | 540 ASSERT(bitmap.height() == m_cachedHeight); |
| 498 glDrawArrays(GL_TRIANGLES, 0, 6); | |
| 499 | 541 |
| 500 // Read back the frame buffer. | 542 // Read back the frame buffer. |
| 501 SkAutoLockPixels bitmapLock(bitmap); | 543 SkAutoLockPixels bitmapLock(bitmap); |
| 502 glReadPixels(0, 0, bitmap.width(), bitmap.height(), GL_BGRA, GL_UNSIGNED_BYTE, bitmap.getPixels()); | 544 pixels = static_cast<unsigned char*>(bitmap.getPixels()); |
| 545 glReadPixels(0, 0, m_cachedWidth, m_cachedHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels); |
| 546 #elif PLATFORM(CG) |
| 547 if (m_renderOutput != NULL) { |
| 548 ASSERT(CGBitmapContextGetWidth(m_cgContext) == m_cachedWidth); |
| 549 ASSERT(CGBitmapContextGetHeight(m_cgContext) == m_cachedHeight); |
| 550 pixels = m_renderOutput; |
| 551 glReadPixels(0, 0, m_cachedWidth, m_cachedHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
| 552 } |
| 553 #else |
| 554 #error Must port to your platform |
| 555 #endif |
| 503 | 556 |
| 504 // Restore the previous FBO state. | 557 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
| 505 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); | 558 if (pixels != NULL) |
| 559 flipVertically(pixels, m_cachedWidth, m_cachedHeight); |
| 560 #endif |
| 506 | 561 |
| 507 // Restore the user's OpenGL state. | 562 #if PLATFORM(SKIA) |
| 508 glUseProgram(m_currentProgram); | 563 // No further work necessary |
| 509 const VertexAttribPointerState& state = m_vertexAttribPointerState[0]; | 564 #elif PLATFORM(CG) |
| 510 if (state.buffer) { | 565 if (m_renderOutput != NULL) { |
| 511 glBindBuffer(GL_ARRAY_BUFFER, state.buffer); | 566 CGImageRef cgImage = CGBitmapContextCreateImage(m_cgContext); |
| 512 glVertexAttribPointer(state.indx, state.size, state.type, state.normalized, | 567 CGRect rect = CGRectMake(0, 0, m_cachedWidth, m_cachedHeight); |
| 513 state.stride, reinterpret_cast<void*>(static_cast<intptr_t>(state.offset))); | 568 // We want to completely overwrite the previous frame's |
| 569 // rendering results. |
| 570 CGContextSetBlendMode(imageBuffer->context()->platformContext(), |
| 571 kCGBlendModeCopy); |
| 572 CGContextDrawImage(imageBuffer->context()->platformContext(), |
| 573 rect, cgImage); |
| 574 CGImageRelease(cgImage); |
| 514 } | 575 } |
| 515 glBindBuffer(GL_ARRAY_BUFFER, m_boundArrayBuffer); | 576 #else |
| 516 if (state.enabled) | 577 #error Must port to your platform |
| 517 glEnableVertexAttribArray(0); | 578 #endif |
| 518 else | 579 |
| 519 glDisableVertexAttribArray(0); | 580 #endif // RENDER_TO_DEBUGGING_WINDOW |
| 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 } | 581 } |
| 533 | 582 |
| 534 bool GraphicsContext3DInternal::validateTextureTarget(int target) | 583 bool GraphicsContext3DInternal::validateTextureTarget(int target) |
| 535 { | 584 { |
| 536 return (target == GL_TEXTURE_2D || | 585 return (target == GL_TEXTURE_2D || |
| 537 target == GL_TEXTURE_CUBE_MAP); | 586 target == GL_TEXTURE_CUBE_MAP); |
| 538 } | 587 } |
| 539 | 588 |
| 540 bool GraphicsContext3DInternal::validateTextureParameter(int param) | 589 bool GraphicsContext3DInternal::validateTextureParameter(int param) |
| 541 { | 590 { |
| 542 return (param == GL_TEXTURE_MAG_FILTER || | 591 return (param == GL_TEXTURE_MAG_FILTER || |
| 543 param == GL_TEXTURE_MIN_FILTER || | 592 param == GL_TEXTURE_MIN_FILTER || |
| 544 param == GL_TEXTURE_WRAP_S || | 593 param == GL_TEXTURE_WRAP_S || |
| 545 param == GL_TEXTURE_WRAP_T); | 594 param == GL_TEXTURE_WRAP_T); |
| 546 } | 595 } |
| 547 | 596 |
| 548 void GraphicsContext3DInternal::activeTexture(unsigned long texture) | 597 void GraphicsContext3DInternal::activeTexture(unsigned long texture) |
| 549 { | 598 { |
| 550 // FIXME: query number of textures available. | 599 // FIXME: query number of textures available. |
| 551 if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32) | 600 if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0+32) |
| 552 // FIXME: raise exception. | 601 // FIXME: raise exception. |
| 553 return; | 602 return; |
| 554 | 603 |
| 555 makeContextCurrent(); | 604 makeContextCurrent(); |
| 556 m_activeTextureUnit = texture; | |
| 557 glActiveTexture(texture); | 605 glActiveTexture(texture); |
| 558 } | 606 } |
| 559 | 607 |
| 560 void GraphicsContext3DInternal::bindBuffer(unsigned long target, | 608 void GraphicsContext3DInternal::bindBuffer(unsigned long target, |
| 561 CanvasBuffer* buffer) | 609 CanvasBuffer* buffer) |
| 562 { | 610 { |
| 563 makeContextCurrent(); | 611 makeContextCurrent(); |
| 564 GLuint bufID = EXTRACT(buffer); | 612 GLuint bufID = EXTRACT(buffer); |
| 565 if (target == GL_ARRAY_BUFFER) | 613 if (target == GL_ARRAY_BUFFER) |
| 566 m_boundArrayBuffer = bufID; | 614 m_boundArrayBuffer = bufID; |
| 567 glBindBuffer(target, bufID); | 615 glBindBuffer(target, bufID); |
| 568 } | 616 } |
| 569 | 617 |
| 570 // If we didn't have to hack GL_TEXTURE_WRAP_R for cube maps, | 618 // If we didn't have to hack GL_TEXTURE_WRAP_R for cube maps, |
| 571 // we could just use: | 619 // we could just use: |
| 572 // GL_SAME_METHOD_2_X2(BindTexture, bindTexture, unsigned long, CanvasTexture*) | 620 // GL_SAME_METHOD_2_X2(BindTexture, bindTexture, unsigned long, CanvasTexture*) |
| 573 void GraphicsContext3DInternal::bindTexture(unsigned long target, | 621 void GraphicsContext3DInternal::bindTexture(unsigned long target, |
| 574 CanvasTexture* texture) | 622 CanvasTexture* texture) |
| 575 { | 623 { |
| 576 makeContextCurrent(); | 624 makeContextCurrent(); |
| 577 unsigned int textureObject = EXTRACT(texture); | 625 unsigned int textureObject = EXTRACT(texture); |
| 578 | 626 |
| 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); | 627 glBindTexture(target, textureObject); |
| 586 | 628 |
| 587 // FIXME: GL_TEXTURE_WRAP_R isn't exposed in the OpenGL ES 2.0 | 629 // FIXME: GL_TEXTURE_WRAP_R isn't exposed in the OpenGL ES 2.0 |
| 588 // API. On desktop OpenGL implementations it seems necessary to | 630 // API. On desktop OpenGL implementations it seems necessary to |
| 589 // set this wrap mode to GL_CLAMP_TO_EDGE to get correct behavior | 631 // set this wrap mode to GL_CLAMP_TO_EDGE to get correct behavior |
| 590 // of cube maps. | 632 // of cube maps. |
| 591 if (texture != NULL) { | 633 if (texture != NULL) { |
| 592 if (target == GL_TEXTURE_CUBE_MAP) { | 634 if (target == GL_TEXTURE_CUBE_MAP) { |
| 593 if (!texture->isCubeMapRWrapModeInitialized()) { | 635 if (!texture->isCubeMapRWrapModeInitialized()) { |
| 594 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); | 636 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 613 // LogMessagef(("bufferData: no buffer bound")); | 655 // LogMessagef(("bufferData: no buffer bound")); |
| 614 return; | 656 return; |
| 615 } | 657 } |
| 616 | 658 |
| 617 glBufferData(target, | 659 glBufferData(target, |
| 618 size, | 660 size, |
| 619 data, | 661 data, |
| 620 usage); | 662 usage); |
| 621 } | 663 } |
| 622 | 664 |
| 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) | 665 void GraphicsContext3DInternal::disableVertexAttribArray(unsigned long index) |
| 655 { | 666 { |
| 656 makeContextCurrent(); | 667 makeContextCurrent(); |
| 657 if (index == 0) { | 668 if (index < NumTrackedPointerStates) { |
| 658 m_vertexAttribPointerState[0].enabled = false; | 669 m_vertexAttribPointerState[index].enabled = false; |
| 659 } | 670 } |
| 660 glDisableVertexAttribArray(index); | 671 glDisableVertexAttribArray(index); |
| 661 } | 672 } |
| 662 | 673 |
| 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) | 674 void GraphicsContext3DInternal::enableVertexAttribArray(unsigned long index) |
| 678 { | 675 { |
| 679 makeContextCurrent(); | 676 makeContextCurrent(); |
| 680 if (index == 0) | 677 if (index < NumTrackedPointerStates) |
| 681 m_vertexAttribPointerState[0].enabled = true; | 678 m_vertexAttribPointerState[index].enabled = true; |
| 682 glEnableVertexAttribArray(index); | 679 glEnableVertexAttribArray(index); |
| 683 } | 680 } |
| 684 | 681 |
| 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, | 682 void GraphicsContext3DInternal::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, |
| 693 unsigned long stride, unsigned long offset) | 683 unsigned long stride, unsigned long offset) |
| 694 { | 684 { |
| 695 makeContextCurrent(); | 685 makeContextCurrent(); |
| 696 | 686 |
| 697 if (m_boundArrayBuffer <= 0) { | 687 if (m_boundArrayBuffer <= 0) { |
| 698 // FIXME: raise exception. | 688 // FIXME: raise exception. |
| 699 // LogMessagef(("bufferData: no buffer bound")); | 689 // LogMessagef(("bufferData: no buffer bound")); |
| 700 return; | 690 return; |
| 701 } | 691 } |
| 702 | 692 |
| 703 if (indx == 0) { | 693 if (indx < NumTrackedPointerStates) { |
| 704 VertexAttribPointerState& state = m_vertexAttribPointerState[0]; | 694 VertexAttribPointerState& state = m_vertexAttribPointerState[indx]; |
| 705 state.buffer = m_boundArrayBuffer; | 695 state.buffer = m_boundArrayBuffer; |
| 706 state.indx = indx; | 696 state.indx = indx; |
| 707 state.size = size; | 697 state.size = size; |
| 708 state.type = type; | 698 state.type = type; |
| 709 state.normalized = normalized; | 699 state.normalized = normalized; |
| 710 state.stride = stride; | 700 state.stride = stride; |
| 711 state.offset = offset; | 701 state.offset = offset; |
| 712 } | 702 } |
| 713 | 703 |
| 714 glVertexAttribPointer(indx, size, type, normalized, stride, | 704 glVertexAttribPointer(indx, size, type, normalized, stride, |
| 715 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | 705 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); |
| 716 } | 706 } |
| 717 | 707 |
| 718 void GraphicsContext3DInternal::viewportImpl(long x, long y, unsigned long width, unsigned long height) | 708 void GraphicsContext3DInternal::viewportImpl(long x, long y, unsigned long width, unsigned long height) |
| 719 { | 709 { |
| 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); | 710 glViewport(x, y, width, height); |
| 725 } | 711 } |
| 726 | 712 |
| 727 // GraphicsContext3D ----------------------------------------------------- | 713 // GraphicsContext3D ----------------------------------------------------- |
| 728 | 714 |
| 729 #define GRAPHICS_CONTEXT_NAME GraphicsContext3D | |
| 730 | |
| 731 /* Helper macros for when we're just wrapping a gl method, so that | 715 /* 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 | 716 * 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. | 717 * NOT BE USED if we need to check any of the parameters. |
| 734 */ | 718 */ |
| 735 | 719 |
| 736 #define GL_SAME_METHOD_0(glname, name) \ | 720 #define GL_SAME_METHOD_0(glname, name) \ |
| 737 void GRAPHICS_CONTEXT_NAME::##name() \ | 721 void GraphicsContext3D::name() \ |
| 738 { \ | 722 { \ |
| 739 makeContextCurrent(); gl##glname(); \ | 723 makeContextCurrent(); gl##glname(); \ |
| 740 } | 724 } |
| 741 | 725 |
| 742 #define GL_SAME_METHOD_1(glname, name, t1) \ | 726 #define GL_SAME_METHOD_1(glname, name, t1) \ |
| 743 void GRAPHICS_CONTEXT_NAME::##name(t1 a1) \ | 727 void GraphicsContext3D::name(t1 a1) \ |
| 744 { \ | 728 { \ |
| 745 makeContextCurrent(); gl##glname(a1); \ | 729 makeContextCurrent(); gl##glname(a1); \ |
| 746 } | 730 } |
| 747 | 731 |
| 748 #define GL_SAME_METHOD_1_X(glname, name, t1) \ | 732 #define GL_SAME_METHOD_1_X(glname, name, t1) \ |
| 749 void GRAPHICS_CONTEXT_NAME::##name(t1 a1) \ | 733 void GraphicsContext3D::name(t1 a1) \ |
| 750 { \ | 734 { \ |
| 751 makeContextCurrent(); gl##glname(EXTRACT(a1)); \ | 735 makeContextCurrent(); gl##glname(EXTRACT(a1)); \ |
| 752 } | 736 } |
| 753 | 737 |
| 754 #define GL_SAME_METHOD_2(glname, name, t1, t2) \ | 738 #define GL_SAME_METHOD_2(glname, name, t1, t2) \ |
| 755 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \ | 739 void GraphicsContext3D::name(t1 a1, t2 a2) \ |
| 756 { \ | 740 { \ |
| 757 makeContextCurrent(); gl##glname(a1,a2); \ | 741 makeContextCurrent(); gl##glname(a1,a2); \ |
| 758 } | 742 } |
| 759 | 743 |
| 760 #define GL_SAME_METHOD_2_X12(glname, name, t1, t2) \ | 744 #define GL_SAME_METHOD_2_X12(glname, name, t1, t2) \ |
| 761 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \ | 745 void GraphicsContext3D::name(t1 a1, t2 a2) \ |
| 762 { \ | 746 { \ |
| 763 makeContextCurrent(); gl##glname(EXTRACT(a1),EXTRACT(a2)); \ | 747 makeContextCurrent(); gl##glname(EXTRACT(a1),EXTRACT(a2)); \ |
| 764 } | 748 } |
| 765 | 749 |
| 766 #define GL_SAME_METHOD_2_X2(glname, name, t1, t2) \ | 750 #define GL_SAME_METHOD_2_X2(glname, name, t1, t2) \ |
| 767 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2) \ | 751 void GraphicsContext3D::name(t1 a1, t2 a2) \ |
| 768 { \ | 752 { \ |
| 769 makeContextCurrent(); gl##glname(a1,EXTRACT(a2)); \ | 753 makeContextCurrent(); gl##glname(a1,EXTRACT(a2)); \ |
| 770 } | 754 } |
| 771 | 755 |
| 772 #define GL_SAME_METHOD_3(glname, name, t1, t2, t3) \ | 756 #define GL_SAME_METHOD_3(glname, name, t1, t2, t3) \ |
| 773 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \ | 757 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \ |
| 774 { \ | 758 { \ |
| 775 makeContextCurrent(); gl##glname(a1,a2,a3); \ | 759 makeContextCurrent(); gl##glname(a1,a2,a3); \ |
| 776 } | 760 } |
| 777 | 761 |
| 778 #define GL_SAME_METHOD_3_X12(glname, name, t1, t2, t3) \ | 762 #define GL_SAME_METHOD_3_X12(glname, name, t1, t2, t3) \ |
| 779 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \ | 763 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \ |
| 780 { \ | 764 { \ |
| 781 makeContextCurrent(); gl##glname(EXTRACT(a1),EXTRACT(a2),a3); \ | 765 makeContextCurrent(); gl##glname(EXTRACT(a1),EXTRACT(a2),a3); \ |
| 782 } | 766 } |
| 783 | 767 |
| 784 #define GL_SAME_METHOD_3_X2(glname, name, t1, t2, t3) \ | 768 #define GL_SAME_METHOD_3_X2(glname, name, t1, t2, t3) \ |
| 785 void GRAPHICS_CONTEXT_NAME::##name(t1 a1, t2 a2, t3 a3) \ | 769 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \ |
| 786 { \ | 770 { \ |
| 787 makeContextCurrent(); gl##glname(a1,EXTRACT(a2),a3); \ | 771 makeContextCurrent(); gl##glname(a1,EXTRACT(a2),a3); \ |
| 788 } | 772 } |
| 789 | 773 |
| 790 #define GL_SAME_METHOD_4(glname, name, t1, t2, t3, t4) \ | 774 #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) \ | 775 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \ |
| 792 { \ | 776 { \ |
| 793 makeContextCurrent(); gl##glname(a1,a2,a3,a4); \ | 777 makeContextCurrent(); gl##glname(a1,a2,a3,a4); \ |
| 794 } | 778 } |
| 795 | 779 |
| 796 #define GL_SAME_METHOD_4_X4(glname, name, t1, t2, t3, t4) \ | 780 #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) \ | 781 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \ |
| 798 { \ | 782 { \ |
| 799 makeContextCurrent(); gl##glname(a1,a2,a3,EXTRACT(a4)); \ | 783 makeContextCurrent(); gl##glname(a1,a2,a3,EXTRACT(a4)); \ |
| 800 } | 784 } |
| 801 | 785 |
| 802 #define GL_SAME_METHOD_5(glname, name, t1, t2, t3, t4, t5) \ | 786 #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) \ | 787 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \ |
| 804 { \ | 788 { \ |
| 805 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5); \ | 789 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5); \ |
| 806 } | 790 } |
| 807 | 791 |
| 808 #define GL_SAME_METHOD_5_X4(glname, name, t1, t2, t3, t4, t5) \ | 792 #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) \ | 793 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \ |
| 810 { \ | 794 { \ |
| 811 makeContextCurrent(); gl##glname(a1,a2,a3,EXTRACT(a4),a5); \ | 795 makeContextCurrent(); gl##glname(a1,a2,a3,EXTRACT(a4),a5); \ |
| 812 } | 796 } |
| 813 | 797 |
| 814 #define GL_SAME_METHOD_6(glname, name, t1, t2, t3, t4, t5, t6) \ | 798 #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) \ | 799 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \ |
| 816 { \ | 800 { \ |
| 817 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5,a6); \ | 801 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5,a6); \ |
| 818 } | 802 } |
| 819 | 803 |
| 820 #define GL_SAME_METHOD_8(glname, name, t1, t2, t3, t4, t5, t6, t7, t8) \ | 804 #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) \ | 805 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \ |
| 822 { \ | 806 { \ |
| 823 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5,a6,a7,a8); \ | 807 makeContextCurrent(); gl##glname(a1,a2,a3,a4,a5,a6,a7,a8); \ |
| 824 } | 808 } |
| 825 | 809 |
| 826 GraphicsContext3D::GraphicsContext3D() | 810 GraphicsContext3D::GraphicsContext3D() |
| 827 : m_currentWidth(0) | 811 : m_currentWidth(0) |
| 828 , m_currentHeight(0) | 812 , m_currentHeight(0) |
| 829 , m_internal(new GraphicsContext3DInternal()) | 813 , m_internal(new GraphicsContext3DInternal()) |
| 830 { | 814 { |
| 831 } | 815 } |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1059 } | 1043 } |
| 1060 | 1044 |
| 1061 GL_SAME_METHOD_1(Clear, clear, unsigned long) | 1045 GL_SAME_METHOD_1(Clear, clear, unsigned long) |
| 1062 | 1046 |
| 1063 GL_SAME_METHOD_4(ClearColor, clearColor, double, double, double, double) | 1047 GL_SAME_METHOD_4(ClearColor, clearColor, double, double, double, double) |
| 1064 | 1048 |
| 1065 GL_SAME_METHOD_1(ClearDepth, clearDepth, double) | 1049 GL_SAME_METHOD_1(ClearDepth, clearDepth, double) |
| 1066 | 1050 |
| 1067 GL_SAME_METHOD_1(ClearStencil, clearStencil, long) | 1051 GL_SAME_METHOD_1(ClearStencil, clearStencil, long) |
| 1068 | 1052 |
| 1069 void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha) | 1053 GL_SAME_METHOD_4(ColorMask, colorMask, bool, bool, bool, bool) |
| 1070 { | |
| 1071 m_internal->colorMask(red, green, blue, alpha); | |
| 1072 } | |
| 1073 | 1054 |
| 1074 GL_SAME_METHOD_1_X(CompileShader, compileShader, CanvasShader*) | 1055 GL_SAME_METHOD_1_X(CompileShader, compileShader, CanvasShader*) |
| 1075 | 1056 |
| 1076 GL_SAME_METHOD_8(CopyTexImage2D, copyTexImage2D, unsigned long, long, unsigned long, long, long, unsigned long, unsigned long, long) | 1057 GL_SAME_METHOD_8(CopyTexImage2D, copyTexImage2D, unsigned long, long, unsigned long, long, long, unsigned long, unsigned long, long) |
| 1077 | 1058 |
| 1078 GL_SAME_METHOD_8(CopyTexSubImage2D, copyTexSubImage2D, unsigned long, long, long, long, long, long, unsigned long, unsigned long) | 1059 GL_SAME_METHOD_8(CopyTexSubImage2D, copyTexSubImage2D, unsigned long, long, long, long, long, long, unsigned long, unsigned long) |
| 1079 | 1060 |
| 1080 GL_SAME_METHOD_1(CullFace, cullFace, unsigned long) | 1061 GL_SAME_METHOD_1(CullFace, cullFace, unsigned long) |
| 1081 | 1062 |
| 1082 GL_SAME_METHOD_1(DepthFunc, depthFunc, unsigned long) | 1063 GL_SAME_METHOD_1(DepthFunc, depthFunc, unsigned long) |
| 1083 | 1064 |
| 1084 void GraphicsContext3D::depthMask(bool flag) | 1065 GL_SAME_METHOD_1(DepthMask, depthMask, bool) |
| 1085 { | |
| 1086 m_internal->depthMask(flag); | |
| 1087 } | |
| 1088 | 1066 |
| 1089 GL_SAME_METHOD_2(DepthRange, depthRange, double, double) | 1067 GL_SAME_METHOD_2(DepthRange, depthRange, double, double) |
| 1090 | 1068 |
| 1091 void GraphicsContext3D::detachShader(CanvasProgram* program, CanvasShader* shader) | 1069 void GraphicsContext3D::detachShader(CanvasProgram* program, CanvasShader* shader) |
| 1092 { | 1070 { |
| 1093 if (!program || !shader) | 1071 if (!program || !shader) |
| 1094 return; | 1072 return; |
| 1095 | 1073 |
| 1096 makeContextCurrent(); | 1074 makeContextCurrent(); |
| 1097 glDetachShader(EXTRACT(program), EXTRACT(shader)); | 1075 glDetachShader(EXTRACT(program), EXTRACT(shader)); |
| 1098 } | 1076 } |
| 1099 | 1077 |
| 1100 void GraphicsContext3D::disable(unsigned long cap) | 1078 GL_SAME_METHOD_1(Disable, disable, unsigned long) |
| 1101 { | |
| 1102 m_internal->disable(cap); | |
| 1103 } | |
| 1104 | 1079 |
| 1105 void GraphicsContext3D::disableVertexAttribArray(unsigned long index) | 1080 void GraphicsContext3D::disableVertexAttribArray(unsigned long index) |
| 1106 { | 1081 { |
| 1107 m_internal->disableVertexAttribArray(index); | 1082 m_internal->disableVertexAttribArray(index); |
| 1108 } | 1083 } |
| 1109 | 1084 |
| 1110 void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count) | 1085 void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count) |
| 1111 { | 1086 { |
| 1112 switch (mode) { | 1087 switch (mode) { |
| 1113 case GL_TRIANGLES: | 1088 case GL_TRIANGLES: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 glGetIntegerv(binding_target, &binding); | 1124 glGetIntegerv(binding_target, &binding); |
| 1150 if (binding <= 0) { | 1125 if (binding <= 0) { |
| 1151 // FIXME: raise exception. | 1126 // FIXME: raise exception. |
| 1152 // LogMessagef(("bufferData: no buffer bound")); | 1127 // LogMessagef(("bufferData: no buffer bound")); |
| 1153 return; | 1128 return; |
| 1154 } | 1129 } |
| 1155 glDrawElements(mode, count, type, | 1130 glDrawElements(mode, count, type, |
| 1156 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); | 1131 reinterpret_cast<void*>(static_cast<intptr_t>(offset))); |
| 1157 } | 1132 } |
| 1158 | 1133 |
| 1159 void GraphicsContext3D::enable(unsigned long cap) | 1134 GL_SAME_METHOD_1(Enable, enable, unsigned long) |
| 1160 { | |
| 1161 m_internal->enable(cap); | |
| 1162 } | |
| 1163 | 1135 |
| 1164 void GraphicsContext3D::enableVertexAttribArray(unsigned long index) | 1136 void GraphicsContext3D::enableVertexAttribArray(unsigned long index) |
| 1165 { | 1137 { |
| 1166 m_internal->enableVertexAttribArray(index); | 1138 m_internal->enableVertexAttribArray(index); |
| 1167 } | 1139 } |
| 1168 | 1140 |
| 1169 GL_SAME_METHOD_0(Finish, finish) | 1141 GL_SAME_METHOD_0(Finish, finish) |
| 1170 | 1142 |
| 1171 GL_SAME_METHOD_0(Flush, flush) | 1143 GL_SAME_METHOD_0(Flush, flush) |
| 1172 | 1144 |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1673 b = (b > 1.0f) ? 1.0f : b; | 1645 b = (b > 1.0f) ? 1.0f : b; |
| 1674 g = (g > 1.0f) ? 1.0f : g; | 1646 g = (g > 1.0f) ? 1.0f : g; |
| 1675 r = (r > 1.0f) ? 1.0f : r; | 1647 r = (r > 1.0f) ? 1.0f : r; |
| 1676 rgbaData[4*j+0] = (unsigned char) (b * 255.0f); | 1648 rgbaData[4*j+0] = (unsigned char) (b * 255.0f); |
| 1677 rgbaData[4*j+1] = (unsigned char) (g * 255.0f); | 1649 rgbaData[4*j+1] = (unsigned char) (g * 255.0f); |
| 1678 rgbaData[4*j+2] = (unsigned char) (r * 255.0f); | 1650 rgbaData[4*j+2] = (unsigned char) (r * 255.0f); |
| 1679 } | 1651 } |
| 1680 } | 1652 } |
| 1681 } | 1653 } |
| 1682 | 1654 |
| 1683 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, | 1655 // FIXME: this must be changed to refer to the original image data |
| 1684 bool flipY, bool premultiplyAlpha) | 1656 // rather than unmultiplying the alpha channel. |
| 1657 static int texImage2DHelper(unsigned target, unsigned level, |
| 1658 int width, int height, |
| 1659 int rowBytes, |
| 1660 bool flipY, |
| 1661 bool premultiplyAlpha, |
| 1662 GLenum format, |
| 1663 bool skipAlpha, |
| 1664 unsigned char* pixels) |
| 1685 { | 1665 { |
| 1686 CachedImage* cachedImage = image->cachedImage(); | 1666 ASSERT(format == GL_RGBA || format == GL_BGRA); |
| 1687 if (cachedImage == NULL) { | 1667 GLint internalFormat = GL_RGBA8; |
| 1688 ASSERT_NOT_REACHED(); | 1668 if (skipAlpha) { |
| 1689 return -1; | 1669 internalFormat = GL_RGB8; |
| 1670 // Ignore the alpha channel |
| 1671 premultiplyAlpha = true; |
| 1690 } | 1672 } |
| 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) { | 1673 if (flipY) { |
| 1708 // Need to flip images vertically. To avoid making a copy of | 1674 // Need to flip images vertically. To avoid making a copy of |
| 1709 // the entire image, we perform a ton of glTexSubImage2D | 1675 // the entire image, we perform a ton of glTexSubImage2D |
| 1710 // calls. FIXME: should rethink this strategy for efficiency. | 1676 // calls. FIXME: should rethink this strategy for efficiency. |
| 1711 glTexImage2D(target, level, GL_RGBA8, | 1677 glTexImage2D(target, level, internalFormat, |
| 1712 width, | 1678 width, |
| 1713 height, | 1679 height, |
| 1714 0, | 1680 0, |
| 1715 GL_BGRA, | 1681 format, |
| 1716 GL_UNSIGNED_BYTE, | 1682 GL_UNSIGNED_BYTE, |
| 1717 NULL); | 1683 NULL); |
| 1718 unsigned char* pixels = | |
| 1719 reinterpret_cast<unsigned char*>(skiaImage->getPixels()); | |
| 1720 int rowBytes = skiaImage->rowBytes(); | |
| 1721 | |
| 1722 unsigned char* row = NULL; | 1684 unsigned char* row = NULL; |
| 1723 bool allocatedRow = false; | 1685 bool allocatedRow = false; |
| 1724 if (!premultiplyAlpha) { | 1686 if (!premultiplyAlpha) { |
| 1725 row = new unsigned char[rowBytes]; | 1687 row = new unsigned char[rowBytes]; |
| 1726 allocatedRow = true; | 1688 allocatedRow = true; |
| 1727 } | 1689 } |
| 1728 for (int i = 0; i < height; i++) { | 1690 for (int i = 0; i < height; i++) { |
| 1729 if (premultiplyAlpha) | 1691 if (premultiplyAlpha) |
| 1730 row = pixels + (rowBytes * i); | 1692 row = pixels + (rowBytes * i); |
| 1731 else { | 1693 else { |
| 1732 memcpy(row, pixels + (rowBytes * i), rowBytes); | 1694 memcpy(row, pixels + (rowBytes * i), rowBytes); |
| 1733 unmultiplyAlpha(row, width); | 1695 unmultiplyAlpha(row, width); |
| 1734 } | 1696 } |
| 1735 glTexSubImage2D(target, level, 0, height - i - 1, | 1697 glTexSubImage2D(target, level, 0, height - i - 1, |
| 1736 width, 1, | 1698 width, 1, |
| 1737 GL_BGRA, | 1699 format, |
| 1738 GL_UNSIGNED_BYTE, | 1700 GL_UNSIGNED_BYTE, |
| 1739 row); | 1701 row); |
| 1740 } | 1702 } |
| 1741 if (allocatedRow) | 1703 if (allocatedRow) |
| 1742 delete[] row; | 1704 delete[] row; |
| 1743 } else { | 1705 } else { |
| 1744 // The pixels of cube maps' faces are defined with a top-down | 1706 // The pixels of cube maps' faces are defined with a top-down |
| 1745 // scanline ordering, unlike GL_TEXTURE_2D, so when uploading | 1707 // scanline ordering, unlike GL_TEXTURE_2D, so when uploading |
| 1746 // these, the above vertical flip is the wrong thing to do. | 1708 // these, the above vertical flip is the wrong thing to do. |
| 1747 if (premultiplyAlpha) | 1709 if (premultiplyAlpha) |
| 1748 glTexImage2D(target, level, GL_RGBA8, | 1710 glTexImage2D(target, level, internalFormat, |
| 1749 width, | 1711 width, |
| 1750 height, | 1712 height, |
| 1751 0, | 1713 0, |
| 1752 GL_BGRA, | 1714 format, |
| 1753 GL_UNSIGNED_BYTE, | 1715 GL_UNSIGNED_BYTE, |
| 1754 skiaImage->getPixels()); | 1716 pixels); |
| 1755 else { | 1717 else { |
| 1756 glTexImage2D(target, level, GL_RGBA8, | 1718 glTexImage2D(target, level, internalFormat, |
| 1757 width, | 1719 width, |
| 1758 height, | 1720 height, |
| 1759 0, | 1721 0, |
| 1760 GL_BGRA, | 1722 format, |
| 1761 GL_UNSIGNED_BYTE, | 1723 GL_UNSIGNED_BYTE, |
| 1762 NULL); | 1724 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]; | 1725 unsigned char* row = new unsigned char[rowBytes]; |
| 1767 for (int i = 0; i < height; i++) { | 1726 for (int i = 0; i < height; i++) { |
| 1768 memcpy(row, pixels + (rowBytes * i), rowBytes); | 1727 memcpy(row, pixels + (rowBytes * i), rowBytes); |
| 1769 unmultiplyAlpha(row, width); | 1728 unmultiplyAlpha(row, width); |
| 1770 glTexSubImage2D(target, level, 0, i, | 1729 glTexSubImage2D(target, level, 0, i, |
| 1771 width, 1, | 1730 width, 1, |
| 1772 GL_BGRA, | 1731 format, |
| 1773 GL_UNSIGNED_BYTE, | 1732 GL_UNSIGNED_BYTE, |
| 1774 row); | 1733 row); |
| 1775 } | 1734 } |
| 1776 delete[] row; | 1735 delete[] row; |
| 1777 } | 1736 } |
| 1778 } | 1737 } |
| 1779 return 0; | 1738 return 0; |
| 1780 } | 1739 } |
| 1781 | 1740 |
| 1741 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, |
| 1742 bool flipY, bool premultiplyAlpha) |
| 1743 { |
| 1744 CachedImage* cachedImage = image->cachedImage(); |
| 1745 if (cachedImage == NULL) { |
| 1746 ASSERT_NOT_REACHED(); |
| 1747 return -1; |
| 1748 } |
| 1749 Image* img = cachedImage->image(); |
| 1750 int res = -1; |
| 1751 #if PLATFORM(SKIA) |
| 1752 NativeImageSkia* skiaImage = img->nativeImageForCurrentFrame(); |
| 1753 if (skiaImage == NULL) { |
| 1754 ASSERT_NOT_REACHED(); |
| 1755 return -1; |
| 1756 } |
| 1757 SkBitmap::Config skiaConfig = skiaImage->config(); |
| 1758 // FIXME: must support more image configurations. |
| 1759 if (skiaConfig != SkBitmap::kARGB_8888_Config) { |
| 1760 ASSERT_NOT_REACHED(); |
| 1761 return -1; |
| 1762 } |
| 1763 SkBitmap& skiaImageRef = *skiaImage; |
| 1764 SkAutoLockPixels lock(skiaImageRef); |
| 1765 int width = skiaImage->width(); |
| 1766 int height = skiaImage->height(); |
| 1767 unsigned char* pixels = |
| 1768 reinterpret_cast<unsigned char*>(skiaImage->getPixels()); |
| 1769 int rowBytes = skiaImage->rowBytes(); |
| 1770 res = texImage2DHelper(target, level, |
| 1771 width, height, |
| 1772 rowBytes, |
| 1773 flipY, premultiplyAlpha, |
| 1774 GL_BGRA, |
| 1775 false, |
| 1776 pixels); |
| 1777 #elif PLATFORM(CG) |
| 1778 CGImageRef cgImage = img->nativeImageForCurrentFrame(); |
| 1779 if (cgImage == NULL) { |
| 1780 ASSERT_NOT_REACHED(); |
| 1781 return -1; |
| 1782 } |
| 1783 int width = CGImageGetWidth(cgImage); |
| 1784 int height = CGImageGetHeight(cgImage); |
| 1785 int rowBytes = width * 4; |
| 1786 CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage); |
| 1787 bool skipAlpha = (info == kCGImageAlphaNone || |
| 1788 info == kCGImageAlphaNoneSkipLast || |
| 1789 info == kCGImageAlphaNoneSkipFirst); |
| 1790 unsigned char* imageData = new unsigned char[height * rowBytes]; |
| 1791 CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); |
| 1792 CGContextRef tmpContext = CGBitmapContextCreate(imageData, width, height, 8, rowBytes, |
| 1793 colorSpace, |
| 1794 kCGImageAlphaPremultipliedLast); |
| 1795 CGColorSpaceRelease(colorSpace); |
| 1796 CGContextDrawImage(tmpContext, |
| 1797 CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), |
| 1798 cgImage); |
| 1799 CGContextRelease(tmpContext); |
| 1800 res = texImage2DHelper(target, level, width, height, rowBytes, |
| 1801 flipY, premultiplyAlpha, GL_RGBA, skipAlpha, imageData); |
| 1802 delete[] imageData; |
| 1803 #else |
| 1804 #error Must port to your platform |
| 1805 #endif |
| 1806 return res; |
| 1807 } |
| 1808 |
| 1782 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, | 1809 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, |
| 1783 bool flipY, bool premultiplyAlpha) | 1810 bool flipY, bool premultiplyAlpha) |
| 1784 { | 1811 { |
| 1785 // FIXME: implement. | 1812 // FIXME: implement. |
| 1786 notImplemented(); | 1813 notImplemented(); |
| 1787 return -1; | 1814 return -1; |
| 1788 } | 1815 } |
| 1789 | 1816 |
| 1790 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, | 1817 int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, |
| 1791 bool flipY, bool premultiplyAlpha) | 1818 bool flipY, bool premultiplyAlpha) |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1949 makeContextCurrent(); | 1976 makeContextCurrent(); |
| 1950 glUniformMatrix3fv(location, size, transpose, value); | 1977 glUniformMatrix3fv(location, size, transpose, value); |
| 1951 } | 1978 } |
| 1952 | 1979 |
| 1953 void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* value, int size) | 1980 void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* value, int size) |
| 1954 { | 1981 { |
| 1955 makeContextCurrent(); | 1982 makeContextCurrent(); |
| 1956 glUniformMatrix4fv(location, size, transpose, value); | 1983 glUniformMatrix4fv(location, size, transpose, value); |
| 1957 } | 1984 } |
| 1958 | 1985 |
| 1959 void GraphicsContext3D::useProgram(CanvasProgram* program) | 1986 GL_SAME_METHOD_1_X(UseProgram, useProgram, CanvasProgram*) |
| 1960 { | |
| 1961 m_internal->useProgram(program); | |
| 1962 } | |
| 1963 | 1987 |
| 1964 GL_SAME_METHOD_1_X(ValidateProgram, validateProgram, CanvasProgram*) | 1988 GL_SAME_METHOD_1_X(ValidateProgram, validateProgram, CanvasProgram*) |
| 1965 | 1989 |
| 1966 GL_SAME_METHOD_2(VertexAttrib1f, vertexAttrib1f, unsigned long, float) | 1990 GL_SAME_METHOD_2(VertexAttrib1f, vertexAttrib1f, unsigned long, float) |
| 1967 | 1991 |
| 1968 void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* values) | 1992 void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* values) |
| 1969 { | 1993 { |
| 1970 makeContextCurrent(); | 1994 makeContextCurrent(); |
| 1971 glVertexAttrib1fv(indx, values); | 1995 glVertexAttrib1fv(indx, values); |
| 1972 } | 1996 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2003 | 2027 |
| 2004 void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height) | 2028 void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height) |
| 2005 { | 2029 { |
| 2006 makeContextCurrent(); | 2030 makeContextCurrent(); |
| 2007 m_internal->viewportImpl(x, y, width, height); | 2031 m_internal->viewportImpl(x, y, width, height); |
| 2008 } | 2032 } |
| 2009 | 2033 |
| 2010 } | 2034 } |
| 2011 | 2035 |
| 2012 #endif // ENABLE(3D_CANVAS) | 2036 #endif // ENABLE(3D_CANVAS) |
| OLD | NEW |