| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 #include "gl/SkGLContext.h" | 8 #include "gl/SkGLContext.h" |
| 9 | 9 |
| 10 #include <X11/Xlib.h> | 10 #include <X11/Xlib.h> |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #define NUM_GL_VERSIONS SK_ARRAY_COUNT(gl_versions) | 39 #define NUM_GL_VERSIONS SK_ARRAY_COUNT(gl_versions) |
| 40 | 40 |
| 41 static bool ctxErrorOccurred = false; | 41 static bool ctxErrorOccurred = false; |
| 42 static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) { | 42 static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) { |
| 43 ctxErrorOccurred = true; | 43 ctxErrorOccurred = true; |
| 44 return 0; | 44 return 0; |
| 45 } | 45 } |
| 46 | 46 |
| 47 class GLXGLContext : public SkGLContext { | 47 class GLXGLContext : public SkGLContext { |
| 48 public: | 48 public: |
| 49 GLXGLContext(); | 49 GLXGLContext(GrGLStandard forcedGpuAPI); |
| 50 | 50 virtual ~GLXGLContext() SK_OVERRIDE; |
| 51 virtual ~GLXGLContext(); | |
| 52 | |
| 53 virtual void makeCurrent() const SK_OVERRIDE; | 51 virtual void makeCurrent() const SK_OVERRIDE; |
| 54 virtual void swapBuffers() const SK_OVERRIDE; | 52 virtual void swapBuffers() const SK_OVERRIDE; |
| 55 protected: | |
| 56 virtual const GrGLInterface* createGLContext(GrGLStandard forcedGpuAPI) SK_O
VERRIDE; | |
| 57 virtual void destroyGLContext() SK_OVERRIDE; | |
| 58 | 53 |
| 59 private: | 54 private: |
| 55 void destroyGLContext(); |
| 56 |
| 60 GLXContext fContext; | 57 GLXContext fContext; |
| 61 Display* fDisplay; | 58 Display* fDisplay; |
| 62 Pixmap fPixmap; | 59 Pixmap fPixmap; |
| 63 GLXPixmap fGlxPixmap; | 60 GLXPixmap fGlxPixmap; |
| 64 }; | 61 }; |
| 65 | 62 |
| 66 GLXGLContext::GLXGLContext() | 63 GLXGLContext::GLXGLContext(GrGLStandard forcedGpuAPI) |
| 67 : fContext(NULL) | 64 : fContext(NULL) |
| 68 , fDisplay(NULL) | 65 , fDisplay(NULL) |
| 69 , fPixmap(0) | 66 , fPixmap(0) |
| 70 , fGlxPixmap(0) { | 67 , fGlxPixmap(0) { |
| 71 } | |
| 72 | 68 |
| 73 GLXGLContext::~GLXGLContext() { | |
| 74 this->destroyGLContext(); | |
| 75 } | |
| 76 | |
| 77 void GLXGLContext::destroyGLContext() { | |
| 78 if (fDisplay) { | |
| 79 glXMakeCurrent(fDisplay, 0, 0); | |
| 80 | |
| 81 if (fContext) { | |
| 82 glXDestroyContext(fDisplay, fContext); | |
| 83 fContext = NULL; | |
| 84 } | |
| 85 | |
| 86 if (fGlxPixmap) { | |
| 87 glXDestroyGLXPixmap(fDisplay, fGlxPixmap); | |
| 88 fGlxPixmap = 0; | |
| 89 } | |
| 90 | |
| 91 if (fPixmap) { | |
| 92 XFreePixmap(fDisplay, fPixmap); | |
| 93 fPixmap = 0; | |
| 94 } | |
| 95 | |
| 96 XCloseDisplay(fDisplay); | |
| 97 fDisplay = NULL; | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 const GrGLInterface* GLXGLContext::createGLContext(GrGLStandard forcedGpuAPI) { | |
| 102 fDisplay = XOpenDisplay(0); | 69 fDisplay = XOpenDisplay(0); |
| 103 | 70 |
| 104 if (!fDisplay) { | 71 if (!fDisplay) { |
| 105 SkDebugf("Failed to open X display.\n"); | 72 SkDebugf("Failed to open X display.\n"); |
| 106 this->destroyGLContext(); | 73 this->destroyGLContext(); |
| 107 return NULL; | 74 return; |
| 108 } | 75 } |
| 109 | 76 |
| 110 // Get a matching FB config | 77 // Get a matching FB config |
| 111 static int visual_attribs[] = { | 78 static int visual_attribs[] = { |
| 112 GLX_X_RENDERABLE , True, | 79 GLX_X_RENDERABLE , True, |
| 113 GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, | 80 GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, |
| 114 None | 81 None |
| 115 }; | 82 }; |
| 116 | 83 |
| 117 int glx_major, glx_minor; | 84 int glx_major, glx_minor; |
| 118 | 85 |
| 119 // FBConfigs were added in GLX version 1.3. | 86 // FBConfigs were added in GLX version 1.3. |
| 120 if (!glXQueryVersion(fDisplay, &glx_major, &glx_minor) || | 87 if (!glXQueryVersion(fDisplay, &glx_major, &glx_minor) || |
| 121 ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { | 88 ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { |
| 122 SkDebugf("GLX version 1.3 or higher required.\n"); | 89 SkDebugf("GLX version 1.3 or higher required.\n"); |
| 123 this->destroyGLContext(); | 90 this->destroyGLContext(); |
| 124 return NULL; | 91 return; |
| 125 } | 92 } |
| 126 | 93 |
| 127 //SkDebugf("Getting matching framebuffer configs.\n"); | 94 //SkDebugf("Getting matching framebuffer configs.\n"); |
| 128 int fbcount; | 95 int fbcount; |
| 129 GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay), | 96 GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay), |
| 130 visual_attribs, &fbcount); | 97 visual_attribs, &fbcount); |
| 131 if (!fbc) { | 98 if (!fbc) { |
| 132 SkDebugf("Failed to retrieve a framebuffer config.\n"); | 99 SkDebugf("Failed to retrieve a framebuffer config.\n"); |
| 133 this->destroyGLContext(); | 100 this->destroyGLContext(); |
| 134 return NULL; | 101 return; |
| 135 } | 102 } |
| 136 //SkDebugf("Found %d matching FB configs.\n", fbcount); | 103 //SkDebugf("Found %d matching FB configs.\n", fbcount); |
| 137 | 104 |
| 138 // Pick the FB config/visual with the most samples per pixel | 105 // Pick the FB config/visual with the most samples per pixel |
| 139 //SkDebugf("Getting XVisualInfos.\n"); | 106 //SkDebugf("Getting XVisualInfos.\n"); |
| 140 int best_fbc = -1, best_num_samp = -1; | 107 int best_fbc = -1, best_num_samp = -1; |
| 141 | 108 |
| 142 int i; | 109 int i; |
| 143 for (i = 0; i < fbcount; ++i) { | 110 for (i = 0; i < fbcount; ++i) { |
| 144 XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]); | 111 XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, fbc[i]); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 164 | 131 |
| 165 // Get a visual | 132 // Get a visual |
| 166 XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc); | 133 XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc); |
| 167 //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid); | 134 //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid); |
| 168 | 135 |
| 169 fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10,
vi->depth); | 136 fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10,
vi->depth); |
| 170 | 137 |
| 171 if (!fPixmap) { | 138 if (!fPixmap) { |
| 172 SkDebugf("Failed to create pixmap.\n"); | 139 SkDebugf("Failed to create pixmap.\n"); |
| 173 this->destroyGLContext(); | 140 this->destroyGLContext(); |
| 174 return NULL; | 141 return; |
| 175 } | 142 } |
| 176 | 143 |
| 177 fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap); | 144 fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap); |
| 178 | 145 |
| 179 // Done with the visual info data | 146 // Done with the visual info data |
| 180 XFree(vi); | 147 XFree(vi); |
| 181 | 148 |
| 182 // Create the context | 149 // Create the context |
| 183 | 150 |
| 184 // Install an X error handler so the application won't exit if GL 3.0 | 151 // Install an X error handler so the application won't exit if GL 3.0 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 | 243 |
| 277 // Sync to ensure any errors generated are processed. | 244 // Sync to ensure any errors generated are processed. |
| 278 XSync(fDisplay, False); | 245 XSync(fDisplay, False); |
| 279 | 246 |
| 280 // Restore the original error handler | 247 // Restore the original error handler |
| 281 XSetErrorHandler(oldHandler); | 248 XSetErrorHandler(oldHandler); |
| 282 | 249 |
| 283 if (ctxErrorOccurred || !fContext) { | 250 if (ctxErrorOccurred || !fContext) { |
| 284 SkDebugf("Failed to create an OpenGL context.\n"); | 251 SkDebugf("Failed to create an OpenGL context.\n"); |
| 285 this->destroyGLContext(); | 252 this->destroyGLContext(); |
| 286 return NULL; | 253 return; |
| 287 } | 254 } |
| 288 | 255 |
| 289 // Verify that context is a direct context | 256 // Verify that context is a direct context |
| 290 if (!glXIsDirect(fDisplay, fContext)) { | 257 if (!glXIsDirect(fDisplay, fContext)) { |
| 291 //SkDebugf("Indirect GLX rendering context obtained.\n"); | 258 //SkDebugf("Indirect GLX rendering context obtained.\n"); |
| 292 } else { | 259 } else { |
| 293 //SkDebugf("Direct GLX rendering context obtained.\n"); | 260 //SkDebugf("Direct GLX rendering context obtained.\n"); |
| 294 } | 261 } |
| 295 | 262 |
| 296 //SkDebugf("Making context current.\n"); | 263 //SkDebugf("Making context current.\n"); |
| 297 if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { | 264 if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { |
| 298 SkDebugf("Could not set the context.\n"); | 265 SkDebugf("Could not set the context.\n"); |
| 299 this->destroyGLContext(); | 266 this->destroyGLContext(); |
| 300 return NULL; | 267 return; |
| 301 } | 268 } |
| 302 | 269 |
| 303 const GrGLInterface* interface = GrGLCreateNativeInterface(); | 270 fGL.reset(GrGLCreateNativeInterface()); |
| 304 if (!interface) { | 271 if (NULL == fGL.get()) { |
| 305 SkDebugf("Failed to create gl interface"); | 272 SkDebugf("Failed to create gl interface"); |
| 306 this->destroyGLContext(); | 273 this->destroyGLContext(); |
| 307 return NULL; | 274 return; |
| 308 } | 275 } |
| 309 return interface; | 276 |
| 277 if (!fGL->validate()) { |
| 278 SkDebugf("Failed to validate gl interface"); |
| 279 this->destroyGLContext(); |
| 280 return; |
| 281 } |
| 282 } |
| 283 |
| 284 |
| 285 GLXGLContext::~GLXGLContext() { |
| 286 this->destroyGLContext(); |
| 287 } |
| 288 |
| 289 void GLXGLContext::destroyGLContext() { |
| 290 fGL.reset(NULL); |
| 291 if (fDisplay) { |
| 292 glXMakeCurrent(fDisplay, 0, 0); |
| 293 |
| 294 if (fContext) { |
| 295 glXDestroyContext(fDisplay, fContext); |
| 296 fContext = NULL; |
| 297 } |
| 298 |
| 299 if (fGlxPixmap) { |
| 300 glXDestroyGLXPixmap(fDisplay, fGlxPixmap); |
| 301 fGlxPixmap = 0; |
| 302 } |
| 303 |
| 304 if (fPixmap) { |
| 305 XFreePixmap(fDisplay, fPixmap); |
| 306 fPixmap = 0; |
| 307 } |
| 308 |
| 309 XCloseDisplay(fDisplay); |
| 310 fDisplay = NULL; |
| 311 } |
| 310 } | 312 } |
| 311 | 313 |
| 312 void GLXGLContext::makeCurrent() const { | 314 void GLXGLContext::makeCurrent() const { |
| 313 if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { | 315 if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { |
| 314 SkDebugf("Could not set the context.\n"); | 316 SkDebugf("Could not set the context.\n"); |
| 315 } | 317 } |
| 316 } | 318 } |
| 317 | 319 |
| 318 void GLXGLContext::swapBuffers() const { | 320 void GLXGLContext::swapBuffers() const { |
| 319 glXSwapBuffers(fDisplay, fGlxPixmap); | 321 glXSwapBuffers(fDisplay, fGlxPixmap); |
| 320 } | 322 } |
| 321 | 323 |
| 322 } // anonymous namespace | 324 } // anonymous namespace |
| 323 | 325 |
| 324 SkGLContext* SkCreatePlatformGLContext() { | 326 SkGLContext* SkCreatePlatformGLContext(GrGLStandard forcedGpuAPI) { |
| 325 return SkNEW(GLXGLContext); | 327 GLXGLContext* ctx = SkNEW_ARGS(GLXGLContext, (forcedGpuAPI)); |
| 328 if (!ctx->isValid()) { |
| 329 SkDELETE(ctx); |
| 330 return NULL; |
| 331 } |
| 332 return ctx; |
| 326 } | 333 } |
| OLD | NEW |