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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 #endif | 74 #endif |
75 | 75 |
76 #if PLATFORM(SKIA) | 76 #if PLATFORM(SKIA) |
77 #include "NativeImageSkia.h" | 77 #include "NativeImageSkia.h" |
78 #endif | 78 #endif |
79 | 79 |
80 #if PLATFORM(DARWIN) | 80 #if PLATFORM(DARWIN) |
81 #define USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER | 81 #define USE_TEXTURE_RECTANGLE_FOR_FRAMEBUFFER |
82 #endif | 82 #endif |
83 | 83 |
| 84 #if PLATFORM(LINUX) |
| 85 #include <dlfcn.h> |
| 86 #include "GL/glxew.h" |
| 87 #endif |
| 88 |
84 using namespace std; | 89 using namespace std; |
85 | 90 |
86 namespace WebCore { | 91 namespace WebCore { |
87 | 92 |
88 // GraphicsContext3DInternal ----------------------------------------------------- | 93 // GraphicsContext3DInternal ----------------------------------------------------- |
89 | 94 |
90 // Uncomment this to render to a separate window for debugging | 95 // Uncomment this to render to a separate window for debugging |
91 // #define RENDER_TO_DEBUGGING_WINDOW | 96 // #define RENDER_TO_DEBUGGING_WINDOW |
92 | 97 |
93 #define EXTRACT(val) (val == NULL ? 0 : val->object()) | 98 #define EXTRACT(val) (val == NULL ? 0 : val->object()) |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 | 165 |
161 #if PLATFORM(WIN_OS) | 166 #if PLATFORM(WIN_OS) |
162 HWND m_canvasWindow; | 167 HWND m_canvasWindow; |
163 HDC m_canvasDC; | 168 HDC m_canvasDC; |
164 HGLRC m_contextObj; | 169 HGLRC m_contextObj; |
165 #elif PLATFORM(CG) | 170 #elif PLATFORM(CG) |
166 CGLPBufferObj m_pbuffer; | 171 CGLPBufferObj m_pbuffer; |
167 CGLContextObj m_contextObj; | 172 CGLContextObj m_contextObj; |
168 unsigned char* m_renderOutput; | 173 unsigned char* m_renderOutput; |
169 CGContextRef m_cgContext; | 174 CGContextRef m_cgContext; |
| 175 #elif PLATFORM(LINUX) |
| 176 Display* m_display; |
| 177 GLXContext m_contextObj; |
| 178 GLXPbuffer m_pbuffer; |
| 179 // In order to avoid problems caused by linking against libGL, we |
| 180 // dynamically look up all the symbols we need. |
| 181 // http://code.google.com/p/chromium/issues/detail?id=16800 |
| 182 void* m_libGL; |
| 183 PFNGLXCHOOSEFBCONFIGPROC m_glXChooseFBConfig; |
| 184 PFNGLXCREATENEWCONTEXTPROC m_glXCreateNewContext; |
| 185 PFNGLXCREATEPBUFFERPROC m_glXCreatePbuffer; |
| 186 PFNGLXDESTROYPBUFFERPROC m_glXDestroyPbuffer; |
| 187 typedef Bool (* PFNGLXMAKECURRENTPROC)(Display* dpy, GLXDrawable drawable, GLXContext ctx); |
| 188 PFNGLXMAKECURRENTPROC m_glXMakeCurrent; |
| 189 typedef void (* PFNGLXDESTROYCONTEXTPROC)(Display* dpy, GLXContext ctx); |
| 190 PFNGLXDESTROYCONTEXTPROC m_glXDestroyContext; |
| 191 typedef GLXContext (* PFNGLXGETCURRENTCONTEXTPROC)(void); |
| 192 PFNGLXGETCURRENTCONTEXTPROC m_glXGetCurrentContext; |
170 #else | 193 #else |
171 #error Must port GraphicsContext3D to your platform | 194 #error Must port GraphicsContext3D to your platform |
172 #endif | 195 #endif |
173 }; | 196 }; |
174 | 197 |
175 GraphicsContext3DInternal::VertexAttribPointerState::VertexAttribPointerState() | 198 GraphicsContext3DInternal::VertexAttribPointerState::VertexAttribPointerState() |
176 : enabled(false) | 199 : enabled(false) |
177 , buffer(0) | 200 , buffer(0) |
178 , indx(0) | 201 , indx(0) |
179 , size(0) | 202 , size(0) |
180 , type(0) | 203 , type(0) |
181 , normalized(false) | 204 , normalized(false) |
182 , stride(0) | 205 , stride(0) |
183 , offset(0) | 206 , offset(0) |
184 { | 207 { |
185 } | 208 } |
186 | 209 |
| 210 #if PLATFORM(LINUX) |
| 211 static void* tryLoad(const char* libName) { |
| 212 // We use RTLD_GLOBAL semantics so that GLEW initialization works; |
| 213 // GLEW expects to be able to open the current process's handle |
| 214 // and do dlsym's of GL entry points from there. |
| 215 return dlopen(libName, RTLD_LAZY | RTLD_GLOBAL); |
| 216 } |
| 217 #endif |
| 218 |
187 GraphicsContext3DInternal::GraphicsContext3DInternal() | 219 GraphicsContext3DInternal::GraphicsContext3DInternal() |
188 : m_texture(0) | 220 : m_texture(0) |
189 , m_fbo(0) | 221 , m_fbo(0) |
190 , m_depthBuffer(0) | 222 , m_depthBuffer(0) |
191 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 223 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
192 , m_scanline(NULL) | 224 , m_scanline(NULL) |
193 #endif | 225 #endif |
194 , m_boundArrayBuffer(0) | 226 , m_boundArrayBuffer(0) |
195 #if PLATFORM(WIN_OS) | 227 #if PLATFORM(WIN_OS) |
196 , m_canvasWindow(NULL) | 228 , m_canvasWindow(NULL) |
197 , m_canvasDC(NULL) | 229 , m_canvasDC(NULL) |
198 , m_contextObj(NULL) | 230 , m_contextObj(NULL) |
199 #elif PLATFORM(CG) | 231 #elif PLATFORM(CG) |
200 , m_pbuffer(NULL) | 232 , m_pbuffer(NULL) |
201 , m_contextObj(NULL) | 233 , m_contextObj(NULL) |
202 , m_renderOutput(NULL) | 234 , m_renderOutput(NULL) |
203 , m_cgContext(NULL) | 235 , m_cgContext(NULL) |
| 236 #elif PLATFORM(LINUX) |
| 237 , m_display(NULL) |
| 238 , m_contextObj(NULL) |
| 239 , m_pbuffer(NULL) |
| 240 , m_glXChooseFBConfig(NULL) |
| 241 , m_glXCreateNewContext(NULL) |
| 242 , m_glXCreatePbuffer(NULL) |
| 243 , m_glXDestroyPbuffer(NULL) |
| 244 , m_glXMakeCurrent(NULL) |
| 245 , m_glXDestroyContext(NULL) |
| 246 , m_glXGetCurrentContext(NULL) |
204 #else | 247 #else |
205 #error Must port to your platform | 248 #error Must port to your platform |
206 #endif | 249 #endif |
207 { | 250 { |
208 #if PLATFORM(WIN_OS) | 251 #if PLATFORM(WIN_OS) |
209 WNDCLASS wc; | 252 WNDCLASS wc; |
210 if (!GetClassInfo(GetModuleHandle(NULL), L"CANVASGL", &wc)) { | 253 if (!GetClassInfo(GetModuleHandle(NULL), L"CANVASGL", &wc)) { |
211 ZeroMemory(&wc, sizeof(WNDCLASS)); | 254 ZeroMemory(&wc, sizeof(WNDCLASS)); |
212 wc.style = CS_OWNDC; | 255 wc.style = CS_OWNDC; |
213 wc.hInstance = GetModuleHandle(NULL); | 256 wc.hInstance = GetModuleHandle(NULL); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 return; | 353 return; |
311 } | 354 } |
312 if (CGLSetCurrentContext(context) != kCGLNoError) { | 355 if (CGLSetCurrentContext(context) != kCGLNoError) { |
313 CGLDestroyContext(context); | 356 CGLDestroyContext(context); |
314 CGLDestroyPBuffer(pbuffer); | 357 CGLDestroyPBuffer(pbuffer); |
315 printf("GraphicsContext3D: error making context current\n"); | 358 printf("GraphicsContext3D: error making context current\n"); |
316 return; | 359 return; |
317 } | 360 } |
318 m_pbuffer = pbuffer; | 361 m_pbuffer = pbuffer; |
319 m_contextObj = context; | 362 m_contextObj = context; |
| 363 #elif PLATFORM(LINUX) |
| 364 m_display = XOpenDisplay(NULL); |
| 365 if (m_display == NULL) { |
| 366 printf("GraphicsContext3D: error opening X display\n"); |
| 367 return; |
| 368 } |
| 369 |
| 370 const char* libNames[] = { |
| 371 "/usr/lib/libGL.so.1", |
| 372 "/usr/lib32/libGL.so.1", |
| 373 "/usr/lib64/libGL.so.1", |
| 374 }; |
| 375 for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++) { |
| 376 m_libGL = tryLoad(libNames[i]); |
| 377 if (m_libGL != NULL) |
| 378 break; |
| 379 } |
| 380 if (m_libGL == NULL) { |
| 381 printf("GraphicsContext3D: error opening libGL.so.1\n"); |
| 382 printf("GraphicsContext3D: tried:"); |
| 383 for (int i = 0; i < sizeof(libNames) / sizeof(const char*); i++) { |
| 384 printf(" %s", libNames[i]); |
| 385 } |
| 386 return; |
| 387 } |
| 388 m_glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) dlsym(m_libGL, "glXChooseFBConfig"); |
| 389 m_glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC) dlsym(m_libGL, "glXCreateNewContext"); |
| 390 m_glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC) dlsym(m_libGL, "glXCreatePbuffer"); |
| 391 m_glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC) dlsym(m_libGL, "glXDestroyPbuffer"); |
| 392 m_glXMakeCurrent = (PFNGLXMAKECURRENTPROC) dlsym(m_libGL, "glXMakeCurrent"); |
| 393 m_glXDestroyContext = (PFNGLXDESTROYCONTEXTPROC) dlsym(m_libGL, "glXDestroyContext"); |
| 394 m_glXGetCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC) dlsym(m_libGL, "glXGetCurrentContext"); |
| 395 if (!m_glXChooseFBConfig || !m_glXCreateNewContext || !m_glXCreatePbuffer || |
| 396 !m_glXDestroyPbuffer || !m_glXMakeCurrent || !m_glXDestroyContext || |
| 397 !m_glXGetCurrentContext) { |
| 398 printf("GraphicsContext3D: error looking up bootstrapping entry points\n"); |
| 399 return; |
| 400 } |
| 401 int configAttrs[] = { |
| 402 GLX_DRAWABLE_TYPE, |
| 403 GLX_PBUFFER_BIT, |
| 404 GLX_RENDER_TYPE, |
| 405 GLX_RGBA_BIT, |
| 406 GLX_DOUBLEBUFFER, |
| 407 0, |
| 408 0 |
| 409 }; |
| 410 int nelements = 0; |
| 411 GLXFBConfig* config = m_glXChooseFBConfig(m_display, 0, configAttrs, &nelements); |
| 412 if (config == NULL) { |
| 413 printf("GraphicsContext3D: glXChooseFBConfig failed\n"); |
| 414 return; |
| 415 } |
| 416 if (nelements == 0) { |
| 417 printf("GraphicsContext3D: glXChooseFBConfig returned 0 elements\n"); |
| 418 XFree(config); |
| 419 return; |
| 420 } |
| 421 GLXContext context = m_glXCreateNewContext(m_display, config[0], GLX_RGBA_TYPE, NULL, True); |
| 422 if (context == NULL) { |
| 423 printf("GraphicsContext3D: glXCreateNewContext failed\n"); |
| 424 XFree(config); |
| 425 return; |
| 426 } |
| 427 int pbufferAttrs[] = { |
| 428 GLX_PBUFFER_WIDTH, |
| 429 1, |
| 430 GLX_PBUFFER_HEIGHT, |
| 431 1, |
| 432 0 |
| 433 }; |
| 434 GLXPbuffer pbuffer = m_glXCreatePbuffer(m_display, config[0], pbufferAttrs); |
| 435 XFree(config); |
| 436 if (!pbuffer) { |
| 437 printf("GraphicsContext3D: glxCreatePbuffer failed\n"); |
| 438 return; |
| 439 } |
| 440 if (!m_glXMakeCurrent(m_display, pbuffer, context)) { |
| 441 printf("GraphicsContext3D: glXMakeCurrent failed\n"); |
| 442 return; |
| 443 } |
| 444 m_contextObj = context; |
| 445 m_pbuffer = pbuffer; |
320 #else | 446 #else |
321 #error Must port to your platform | 447 #error Must port to your platform |
322 #endif | 448 #endif |
323 | 449 |
324 // Initialize GLEW and check for GL 2.0 support by the drivers. | 450 static bool initializedGLEW = false; |
325 GLenum glewInitResult = glewInit(); | 451 if (!initializedGLEW) { |
326 if (glewInitResult != GLEW_OK) { | 452 // Initialize GLEW and check for GL 2.0 support by the drivers. |
327 printf("GraphicsContext3D: GLEW initialization failed\n"); | 453 GLenum glewInitResult = glewInit(); |
328 return; | 454 if (glewInitResult != GLEW_OK) { |
329 } | 455 printf("GraphicsContext3D: GLEW initialization failed\n"); |
330 if (!glewIsSupported("GL_VERSION_2_0")) { | 456 return; |
331 printf("GraphicsContext3D: OpenGL 2.0 not supported\n"); | 457 } |
332 return; | 458 if (!glewIsSupported("GL_VERSION_2_0")) { |
| 459 printf("GraphicsContext3D: OpenGL 2.0 not supported\n"); |
| 460 return; |
| 461 } |
| 462 initializedGLEW = true; |
333 } | 463 } |
334 } | 464 } |
335 | 465 |
336 GraphicsContext3DInternal::~GraphicsContext3DInternal() | 466 GraphicsContext3DInternal::~GraphicsContext3DInternal() |
337 { | 467 { |
338 makeContextCurrent(); | 468 makeContextCurrent(); |
339 #ifndef RENDER_TO_DEBUGGING_WINDOW | 469 #ifndef RENDER_TO_DEBUGGING_WINDOW |
340 glDeleteRenderbuffersEXT(1, &m_depthBuffer); | 470 glDeleteRenderbuffersEXT(1, &m_depthBuffer); |
341 glDeleteTextures(1, &m_texture); | 471 glDeleteTextures(1, &m_texture); |
342 #ifdef FLIP_FRAMEBUFFER_VERTICALLY | 472 #ifdef FLIP_FRAMEBUFFER_VERTICALLY |
343 if (m_scanline != NULL) | 473 if (m_scanline != NULL) |
344 delete[] m_scanline; | 474 delete[] m_scanline; |
345 #endif | 475 #endif |
346 glDeleteFramebuffersEXT(1, &m_fbo); | 476 glDeleteFramebuffersEXT(1, &m_fbo); |
347 #endif // !RENDER_TO_DEBUGGING_WINDOW | 477 #endif // !RENDER_TO_DEBUGGING_WINDOW |
348 #if PLATFORM(WIN_OS) | 478 #if PLATFORM(WIN_OS) |
349 wglMakeCurrent(NULL, NULL); | 479 wglMakeCurrent(NULL, NULL); |
350 wglDeleteContext(m_contextObj); | 480 wglDeleteContext(m_contextObj); |
351 ReleaseDC(m_canvasWindow, m_canvasDC); | 481 ReleaseDC(m_canvasWindow, m_canvasDC); |
352 DestroyWindow(m_canvasWindow); | 482 DestroyWindow(m_canvasWindow); |
353 #elif PLATFORM(CG) | 483 #elif PLATFORM(CG) |
354 CGLSetCurrentContext(NULL); | 484 CGLSetCurrentContext(NULL); |
355 CGLDestroyContext(m_contextObj); | 485 CGLDestroyContext(m_contextObj); |
356 CGLDestroyPBuffer(m_pbuffer); | 486 CGLDestroyPBuffer(m_pbuffer); |
357 if (m_cgContext != NULL) | 487 if (m_cgContext != NULL) |
358 CGContextRelease(m_cgContext); | 488 CGContextRelease(m_cgContext); |
359 if (m_renderOutput != NULL) | 489 if (m_renderOutput != NULL) |
360 delete[] m_renderOutput; | 490 delete[] m_renderOutput; |
| 491 #elif PLATFORM(LINUX) |
| 492 m_glXMakeCurrent(m_display, NULL, NULL); |
| 493 m_glXDestroyContext(m_display, m_contextObj); |
| 494 m_glXDestroyPbuffer(m_display, m_pbuffer); |
| 495 XCloseDisplay(m_display); |
| 496 dlclose(m_libGL); |
361 #else | 497 #else |
362 #error Must port to your platform | 498 #error Must port to your platform |
363 #endif | 499 #endif |
364 m_contextObj = NULL; | 500 m_contextObj = NULL; |
365 } | 501 } |
366 | 502 |
367 void GraphicsContext3DInternal::checkError() const | 503 void GraphicsContext3DInternal::checkError() const |
368 { | 504 { |
369 // FIXME: This needs to only be done in the debug context. It | 505 // FIXME: This needs to only be done in the debug context. It |
370 // will need to throw an exception on error. | 506 // will need to throw an exception on error. |
371 GLenum error = glGetError(); | 507 GLenum error = glGetError(); |
372 if (error != GL_NO_ERROR) { | 508 if (error != GL_NO_ERROR) { |
373 printf("GraphicsContext3DInternal: GL Error : %x\n", error); | 509 printf("GraphicsContext3DInternal: GL Error : %x\n", error); |
374 notImplemented(); | 510 notImplemented(); |
375 } | 511 } |
376 } | 512 } |
377 | 513 |
378 bool GraphicsContext3DInternal::makeContextCurrent() | 514 bool GraphicsContext3DInternal::makeContextCurrent() |
379 { | 515 { |
380 #if PLATFORM(WIN_OS) | 516 #if PLATFORM(WIN_OS) |
381 if (wglGetCurrentContext() != m_contextObj) | 517 if (wglGetCurrentContext() != m_contextObj) |
382 if (wglMakeCurrent(m_canvasDC, m_contextObj)) | 518 if (wglMakeCurrent(m_canvasDC, m_contextObj)) |
383 return true; | 519 return true; |
384 #elif PLATFORM(CG) | 520 #elif PLATFORM(CG) |
385 if (CGLGetCurrentContext() != m_contextObj) | 521 if (CGLGetCurrentContext() != m_contextObj) |
386 if (CGLSetCurrentContext(m_contextObj) == kCGLNoError) | 522 if (CGLSetCurrentContext(m_contextObj) == kCGLNoError) |
387 return true; | 523 return true; |
| 524 #elif PLATFORM(LINUX) |
| 525 if (m_glXGetCurrentContext() != m_contextObj) |
| 526 if (m_glXMakeCurrent(m_display, m_pbuffer, m_contextObj)) |
| 527 return true; |
388 #else | 528 #else |
389 #error Must port to your platform | 529 #error Must port to your platform |
390 #endif | 530 #endif |
391 return false; | 531 return false; |
392 } | 532 } |
393 | 533 |
394 PlatformGraphicsContext3D GraphicsContext3DInternal::platformGraphicsContext3D() const | 534 PlatformGraphicsContext3D GraphicsContext3DInternal::platformGraphicsContext3D() const |
395 { | 535 { |
396 return m_contextObj; | 536 return m_contextObj; |
397 } | 537 } |
(...skipping 1629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2027 | 2167 |
2028 void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height) | 2168 void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height) |
2029 { | 2169 { |
2030 makeContextCurrent(); | 2170 makeContextCurrent(); |
2031 m_internal->viewportImpl(x, y, width, height); | 2171 m_internal->viewportImpl(x, y, width, height); |
2032 } | 2172 } |
2033 | 2173 |
2034 } | 2174 } |
2035 | 2175 |
2036 #endif // ENABLE(3D_CANVAS) | 2176 #endif // ENABLE(3D_CANVAS) |
OLD | NEW |