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 |