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 // On Nvidia GPUs, to use Nv Path rendering we need a compatibil
ity profile for the |
| 203 // time being. |
| 204 // TODO when Nvidia implements NVPR on Core profiles, we should
start requesting |
| 205 // core here |
| 206 static const int context_attribs_gl[] = { |
| 207 GLX_CONTEXT_MAJOR_VERSION_ARB, gl_versions[i].major, |
| 208 GLX_CONTEXT_MINOR_VERSION_ARB, gl_versions[i].minor, |
| 209 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PR
OFILE_BIT_ARB, |
| 210 None |
| 211 }; |
| 212 fContext = |
| 213 glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, c
ontext_attribs_gl); |
237 | 214 |
238 // Sync to ensure any errors generated are processed. | 215 // Sync to ensure any errors generated are processed. |
239 XSync(fDisplay, False); | 216 XSync(fDisplay, False); |
| 217 |
| 218 if (!ctxErrorOccurred && fContext) { |
| 219 break; |
| 220 } |
| 221 // try again |
| 222 ctxErrorOccurred = false; |
| 223 } |
| 224 |
| 225 // Couldn't create GL 3.0 context. |
| 226 // Fall back to old-style 2.x context. |
| 227 // When a context version below 3.0 is requested, |
| 228 // implementations will return the newest context version |
| 229 // compatible with OpenGL versions less than version 3.0. |
240 if (ctxErrorOccurred || !fContext) { | 230 if (ctxErrorOccurred || !fContext) { |
241 // Couldn't create GL 3.0 context. | 231 static const int context_attribs_gl_fallback[] = { |
242 // Fall back to old-style 2.x context. | 232 GLX_CONTEXT_MAJOR_VERSION_ARB, 1, |
243 // When a context version below 3.0 is requested, | 233 GLX_CONTEXT_MINOR_VERSION_ARB, 0, |
244 // implementations will return the newest context version | 234 None |
245 // compatible with OpenGL versions less than version 3.0. | 235 }; |
246 | 236 |
247 ctxErrorOccurred = false; | 237 ctxErrorOccurred = false; |
248 | 238 |
249 fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True
, | 239 fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True
, |
250 context_attribs_gl_fallbac
k); | 240 context_attribs_gl_fallbac
k); |
251 } | 241 } |
252 } | 242 } |
253 } | 243 } |
254 #endif | |
255 | 244 |
256 // Sync to ensure any errors generated are processed. | 245 // Sync to ensure any errors generated are processed. |
257 XSync(fDisplay, False); | 246 XSync(fDisplay, False); |
258 | 247 |
259 // Restore the original error handler | 248 // Restore the original error handler |
260 XSetErrorHandler(oldHandler); | 249 XSetErrorHandler(oldHandler); |
261 | 250 |
262 if (ctxErrorOccurred || !fContext) { | 251 if (ctxErrorOccurred || !fContext) { |
263 SkDebugf("Failed to create an OpenGL context.\n"); | 252 SkDebugf("Failed to create an OpenGL context.\n"); |
264 this->destroyGLContext(); | 253 this->destroyGLContext(); |
(...skipping 25 matching lines...) Expand all Loading... |
290 | 279 |
291 void SkNativeGLContext::makeCurrent() const { | 280 void SkNativeGLContext::makeCurrent() const { |
292 if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { | 281 if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) { |
293 SkDebugf("Could not set the context.\n"); | 282 SkDebugf("Could not set the context.\n"); |
294 } | 283 } |
295 } | 284 } |
296 | 285 |
297 void SkNativeGLContext::swapBuffers() const { | 286 void SkNativeGLContext::swapBuffers() const { |
298 glXSwapBuffers(fDisplay, fGlxPixmap); | 287 glXSwapBuffers(fDisplay, fGlxPixmap); |
299 } | 288 } |
OLD | NEW |