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 |