Chromium Code Reviews| 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/SkNativeGLContext.h" | 8 #include "gl/SkNativeGLContext.h" |
| 9 | 9 |
| 10 #include <GL/glu.h> | 10 #include <GL/glu.h> |
| 11 | 11 |
| 12 #define GLX_1_3 1 | 12 /* Note: Skia requires glx 1.3 or newer */ |
| 13 | 13 |
| 14 SkNativeGLContext::AutoContextRestore::AutoContextRestore() { | 14 SkNativeGLContext::AutoContextRestore::AutoContextRestore() { |
| 15 fOldGLXContext = glXGetCurrentContext(); | 15 fOldGLXContext = glXGetCurrentContext(); |
| 16 fOldDisplay = glXGetCurrentDisplay(); | 16 fOldDisplay = glXGetCurrentDisplay(); |
| 17 fOldDrawable = glXGetCurrentDrawable(); | 17 fOldDrawable = glXGetCurrentDrawable(); |
| 18 } | 18 } |
| 19 | 19 |
| 20 SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { | 20 SkNativeGLContext::AutoContextRestore::~AutoContextRestore() { |
| 21 if (NULL != fOldDisplay) { | 21 if (NULL != fOldDisplay) { |
| 22 glXMakeCurrent(fOldDisplay, fOldDrawable, fOldGLXContext); | 22 glXMakeCurrent(fOldDisplay, fOldDrawable, fOldGLXContext); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 return NULL; | 75 return NULL; |
| 76 } | 76 } |
| 77 | 77 |
| 78 // Get a matching FB config | 78 // Get a matching FB config |
| 79 static int visual_attribs[] = { | 79 static int visual_attribs[] = { |
| 80 GLX_X_RENDERABLE , True, | 80 GLX_X_RENDERABLE , True, |
| 81 GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, | 81 GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT, |
| 82 None | 82 None |
| 83 }; | 83 }; |
| 84 | 84 |
| 85 #ifdef GLX_1_3 | 85 int glx_major, glx_minor; |
| 86 | |
| 87 // FBConfigs were added in GLX version 1.3. | |
| 88 if (!glXQueryVersion(fDisplay, &glx_major, &glx_minor) || | |
| 89 ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { | |
| 90 SkDebugf("GLX version 1.3 or higher required.\n"); | |
| 91 this->destroyGLContext(); | |
| 92 return NULL; | |
| 93 } | |
| 94 | |
| 86 //SkDebugf("Getting matching framebuffer configs.\n"); | 95 //SkDebugf("Getting matching framebuffer configs.\n"); |
| 87 int fbcount; | 96 int fbcount; |
| 88 GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay), | 97 GLXFBConfig *fbc = glXChooseFBConfig(fDisplay, DefaultScreen(fDisplay), |
| 89 visual_attribs, &fbcount); | 98 visual_attribs, &fbcount); |
| 90 if (!fbc) { | 99 if (!fbc) { |
| 91 SkDebugf("Failed to retrieve a framebuffer config.\n"); | 100 SkDebugf("Failed to retrieve a framebuffer config.\n"); |
| 92 this->destroyGLContext(); | 101 this->destroyGLContext(); |
| 93 return NULL; | 102 return NULL; |
| 94 } | 103 } |
| 95 //SkDebugf("Found %d matching FB configs.\n", fbcount); | 104 //SkDebugf("Found %d matching FB configs.\n", fbcount); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 117 } | 126 } |
| 118 | 127 |
| 119 GLXFBConfig bestFbc = fbc[best_fbc]; | 128 GLXFBConfig bestFbc = fbc[best_fbc]; |
| 120 | 129 |
| 121 // Be sure to free the FBConfig list allocated by glXChooseFBConfig() | 130 // Be sure to free the FBConfig list allocated by glXChooseFBConfig() |
| 122 XFree(fbc); | 131 XFree(fbc); |
| 123 | 132 |
| 124 // Get a visual | 133 // Get a visual |
| 125 XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc); | 134 XVisualInfo *vi = glXGetVisualFromFBConfig(fDisplay, bestFbc); |
| 126 //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid); | 135 //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid); |
| 127 #else | |
| 128 int numVisuals; | |
| 129 XVisualInfo visTemplate, *visReturn; | |
| 130 | |
| 131 visReturn = XGetVisualInfo(fDisplay, VisualNoMask, &visTemplate, &numVisuals ); | |
| 132 if (NULL == visReturn) | |
| 133 { | |
| 134 SkDebugf("Failed to get visual information.\n"); | |
| 135 this->destroyGLContext(); | |
| 136 return NULL; | |
| 137 } | |
| 138 | |
| 139 int best = -1, best_num_samp = -1; | |
| 140 | |
| 141 for (int i = 0; i < numVisuals; ++i) | |
| 142 { | |
| 143 int samp_buf, samples; | |
| 144 | |
| 145 glXGetConfig(fDisplay, &visReturn[i], GLX_SAMPLE_BUFFERS, &samp_buf); | |
| 146 glXGetConfig(fDisplay, &visReturn[i], GLX_SAMPLES, &samples); | |
| 147 | |
| 148 if (best < 0 || (samp_buf && samples > best_num_samp)) | |
| 149 best = i, best_num_samp = samples; | |
| 150 } | |
| 151 | |
| 152 XVisualInfo temp = visReturn[best]; | |
| 153 XVisualInfo *vi = &temp; | |
| 154 | |
| 155 XFree(visReturn); | |
| 156 #endif | |
| 157 | 136 |
| 158 fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth); | 137 fPixmap = XCreatePixmap(fDisplay, RootWindow(fDisplay, vi->screen), 10, 10, vi->depth); |
| 159 | 138 |
| 160 if (!fPixmap) { | 139 if (!fPixmap) { |
| 161 SkDebugf("Failed to create pixmap.\n"); | 140 SkDebugf("Failed to create pixmap.\n"); |
| 162 this->destroyGLContext(); | 141 this->destroyGLContext(); |
| 163 return NULL; | 142 return NULL; |
| 164 } | 143 } |
| 165 | 144 |
| 166 fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap); | 145 fGlxPixmap = glXCreateGLXPixmap(fDisplay, vi, fPixmap); |
| 167 | 146 |
| 168 #ifdef GLX_1_3 | |
| 169 // Done with the visual info data | 147 // Done with the visual info data |
| 170 XFree(vi); | 148 XFree(vi); |
| 171 #endif | |
| 172 | 149 |
| 173 // Create the context | 150 // Create the context |
| 174 | 151 |
| 175 // Install an X error handler so the application won't exit if GL 3.0 | 152 // Install an X error handler so the application won't exit if GL 3.0 |
| 176 // context allocation fails. | 153 // context allocation fails. |
| 177 // | 154 // |
| 178 // Note this error handler is global. | 155 // Note this error handler is global. |
| 179 // All display connections in all threads of a process use the same | 156 // All display connections in all threads of a process use the same |
| 180 // error handler, so be sure to guard against other threads issuing | 157 // error handler, so be sure to guard against other threads issuing |
| 181 // X commands while this code is running. | 158 // X commands while this code is running. |
| 182 ctxErrorOccurred = false; | 159 ctxErrorOccurred = false; |
| 183 int (*oldHandler)(Display*, XErrorEvent*) = | 160 int (*oldHandler)(Display*, XErrorEvent*) = |
| 184 XSetErrorHandler(&ctxErrorHandler); | 161 XSetErrorHandler(&ctxErrorHandler); |
| 185 | 162 |
| 186 // Get the default screen's GLX extension list | 163 // Get the default screen's GLX extension list |
| 187 const char *glxExts = glXQueryExtensionsString( | 164 const char *glxExts = glXQueryExtensionsString( |
| 188 fDisplay, DefaultScreen(fDisplay) | 165 fDisplay, DefaultScreen(fDisplay) |
| 189 ); | 166 ); |
| 190 | 167 |
| 191 | 168 |
| 192 // Check for the GLX_ARB_create_context extension string and the function. | 169 // Check for the GLX_ARB_create_context extension string and the function. |
| 193 // If either is not present, use GLX 1.3 context creation method. | 170 // If either is not present, use GLX 1.3 context creation method. |
| 194 | |
| 195 if (!gluCheckExtension(reinterpret_cast<const GLubyte*>("GLX_ARB_create_cont ext"), | 171 if (!gluCheckExtension(reinterpret_cast<const GLubyte*>("GLX_ARB_create_cont ext"), |
| 196 reinterpret_cast<const GLubyte*>(glxExts))) { | 172 reinterpret_cast<const GLubyte*>(glxExts))) { |
| 197 if (kGLES_GrGLStandard != forcedGpuAPI) { | 173 if (kGLES_GrGLStandard != forcedGpuAPI) { |
| 198 #ifdef GLX_1_3 | |
| 199 fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True); | 174 fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True); |
| 200 #else | |
| 201 fContext = glXCreateContext(fDisplay, vi, 0, True); | |
| 202 #endif | |
| 203 } | 175 } |
| 204 } | 176 } else { |
| 205 #ifdef GLX_1_3 | |
| 206 else { | |
| 207 //SkDebugf("Creating context.\n"); | 177 //SkDebugf("Creating context.\n"); |
| 208 PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = | 178 PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = |
| 209 (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte* )"glXCreateContextAttribsARB"); | 179 (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte* )"glXCreateContextAttribsARB"); |
| 210 | 180 |
| 211 static const int context_attribs_gl[] = { | |
| 212 GLX_CONTEXT_MAJOR_VERSION_ARB, 3, | |
| 213 GLX_CONTEXT_MINOR_VERSION_ARB, 0, | |
| 214 None | |
| 215 }; | |
| 216 static const int context_attribs_gl_fallback[] = { | |
| 217 GLX_CONTEXT_MAJOR_VERSION_ARB, 1, | |
| 218 GLX_CONTEXT_MINOR_VERSION_ARB, 0, | |
| 219 None | |
| 220 }; | |
| 221 static const int context_attribs_gles[] = { | |
| 222 GLX_CONTEXT_MAJOR_VERSION_ARB, 3, | |
| 223 GLX_CONTEXT_MINOR_VERSION_ARB, 0, | |
| 224 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, | |
| 225 None | |
| 226 }; | |
| 227 | |
| 228 if (kGLES_GrGLStandard == forcedGpuAPI) { | 181 if (kGLES_GrGLStandard == forcedGpuAPI) { |
| 229 if (gluCheckExtension( | 182 if (gluCheckExtension( |
| 230 reinterpret_cast<const GLubyte*>("GLX_EXT_create_context_es2 _profile"), | 183 reinterpret_cast<const GLubyte*>("GLX_EXT_create_context_es2 _profile"), |
| 231 reinterpret_cast<const GLubyte*>(glxExts))) { | 184 reinterpret_cast<const GLubyte*>(glxExts))) { |
| 185 static const int context_attribs_gles[] = { | |
| 186 GLX_CONTEXT_MAJOR_VERSION_ARB, 3, | |
| 187 GLX_CONTEXT_MINOR_VERSION_ARB, 0, | |
| 188 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EX T, | |
| 189 None | |
| 190 }; | |
| 232 fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True , | 191 fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True , |
| 233 context_attribs_gles); | 192 context_attribs_gles); |
| 234 } | 193 } |
| 235 } else { | 194 } else { |
| 236 fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, co ntext_attribs_gl); | 195 // Well, unfortunately GLX will not just give us the highest context so instead we have |
| 196 // to do this nastiness | |
| 197 for (i = NUM_GL_VERSIONS - 2; i > 0 ; i--) { | |
| 198 /* don't bother below GL 3.0 */ | |
| 199 if (gl_versions[i].major == 3 && gl_versions[i].minor == 0) { | |
| 200 break; | |
| 201 } | |
| 202 static const int context_attribs_gl[] = { | |
| 203 GLX_CONTEXT_MAJOR_VERSION_ARB, gl_versions[i].major, | |
| 204 GLX_CONTEXT_MINOR_VERSION_ARB, gl_versions[i].minor, | |
| 205 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT _ARB, | |
|
bsalomon
2014/08/07 20:39:15
We weren't setting this before, but now we are. Do
| |
| 206 None | |
| 207 }; | |
| 208 fContext = | |
| 209 glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, c ontext_attribs_gl); | |
| 237 | 210 |
| 238 // Sync to ensure any errors generated are processed. | 211 // Sync to ensure any errors generated are processed. |
| 239 XSync(fDisplay, False); | 212 XSync(fDisplay, False); |
| 213 | |
| 214 if (!ctxErrorOccurred && fContext) { | |
| 215 break; | |
| 216 } | |
| 217 // try again | |
| 218 ctxErrorOccurred = false; | |
| 219 } | |
| 220 | |
| 221 // Couldn't create GL 3.0 context. | |
|
bsalomon
2014/08/07 20:39:15
Maybe change this to "Couldn't create a Core profi
| |
| 222 // Fall back to old-style 2.x context. | |
| 223 // When a context version below 3.0 is requested, | |
| 224 // implementations will return the newest context version | |
| 225 // compatible with OpenGL versions less than version 3.0. | |
| 240 if (ctxErrorOccurred || !fContext) { | 226 if (ctxErrorOccurred || !fContext) { |
| 241 // Couldn't create GL 3.0 context. | 227 static const int context_attribs_gl_fallback[] = { |
| 242 // Fall back to old-style 2.x context. | 228 GLX_CONTEXT_MAJOR_VERSION_ARB, 1, |
| 243 // When a context version below 3.0 is requested, | 229 GLX_CONTEXT_MINOR_VERSION_ARB, 0, |
| 244 // implementations will return the newest context version | 230 None |
| 245 // compatible with OpenGL versions less than version 3.0. | 231 }; |
| 246 | 232 |
| 247 ctxErrorOccurred = false; | 233 ctxErrorOccurred = false; |
| 248 | 234 |
| 249 fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True , | 235 fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True , |
| 250 context_attribs_gl_fallbac k); | 236 context_attribs_gl_fallbac k); |
| 251 } | 237 } |
| 252 } | 238 } |
| 253 } | 239 } |
| 254 #endif | |
| 255 | 240 |
| 256 // Sync to ensure any errors generated are processed. | 241 // Sync to ensure any errors generated are processed. |
| 257 XSync(fDisplay, False); | 242 XSync(fDisplay, False); |
| 258 | 243 |
| 259 // Restore the original error handler | 244 // Restore the original error handler |
| 260 XSetErrorHandler(oldHandler); | 245 XSetErrorHandler(oldHandler); |
| 261 | 246 |
| 262 if (ctxErrorOccurred || !fContext) { | 247 if (ctxErrorOccurred || !fContext) { |
| 263 SkDebugf("Failed to create an OpenGL context.\n"); | 248 SkDebugf("Failed to create an OpenGL context.\n"); |
| 264 this->destroyGLContext(); | 249 this->destroyGLContext(); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 290 | 275 |
| 291 void SkNativeGLContext::makeCurrent() const { | 276 void SkNativeGLContext::makeCurrent() const { |
| 292 if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { | 277 if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { |
| 293 SkDebugf("Could not set the context.\n"); | 278 SkDebugf("Could not set the context.\n"); |
| 294 } | 279 } |
| 295 } | 280 } |
| 296 | 281 |
| 297 void SkNativeGLContext::swapBuffers() const { | 282 void SkNativeGLContext::swapBuffers() const { |
| 298 glXSwapBuffers(fDisplay, fGlxPixmap); | 283 glXSwapBuffers(fDisplay, fGlxPixmap); |
| 299 } | 284 } |
| OLD | NEW |