| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 | 8 |
| 9 #include "gl/GrGLInterface.h" | 9 #include "gl/GrGLInterface.h" |
| 10 #include "GrGLUtil.h" | 10 #include "gl/GrGLExtensions.h" |
| 11 #include "gl/GrGLUtil.h" |
| 11 | 12 |
| 12 #include <stdio.h> | 13 #include <stdio.h> |
| 13 | 14 |
| 14 SK_DEFINE_INST_COUNT(GrGLInterface) | 15 SK_DEFINE_INST_COUNT(GrGLInterface) |
| 15 | 16 |
| 16 #if GR_GL_PER_GL_FUNC_CALLBACK | 17 #if GR_GL_PER_GL_FUNC_CALLBACK |
| 17 namespace { | 18 namespace { |
| 18 void GrGLDefaultInterfaceCallback(const GrGLInterface*) {} | 19 void GrGLDefaultInterfaceCallback(const GrGLInterface*) {} |
| 19 } | 20 } |
| 20 #endif | 21 #endif |
| 21 | 22 |
| 22 GrGLInterface::GrGLInterface() { | 23 GrGLInterface::GrGLInterface() { |
| 23 fBindingsExported = kNone_GrGLBinding; | 24 fBindingsExported = kNone_GrGLBinding; |
| 24 | 25 |
| 25 #if GR_GL_PER_GL_FUNC_CALLBACK | 26 #if GR_GL_PER_GL_FUNC_CALLBACK |
| 26 fCallback = GrGLDefaultInterfaceCallback; | 27 fCallback = GrGLDefaultInterfaceCallback; |
| 27 fCallbackData = 0; | 28 fCallbackData = 0; |
| 28 #endif | 29 #endif |
| 29 } | 30 } |
| 30 | 31 |
| 31 bool GrGLInterface::validate(GrGLBinding binding) const { | 32 bool GrGLInterface::validate(GrGLBinding binding) const { |
| 32 | 33 |
| 33 // kNone must be 0 so that the check we're about to do can never succeed if | 34 // kNone must be 0 so that the check we're about to do can never succeed if |
| 34 // binding == kNone. | 35 // binding == kNone. |
| 35 GR_STATIC_ASSERT(kNone_GrGLBinding == 0); | 36 GR_STATIC_ASSERT(kNone_GrGLBinding == 0); |
| 36 | 37 |
| 37 if (0 == (binding & fBindingsExported)) { | 38 if (0 == (binding & fBindingsExported)) { |
| 38 return false; | 39 return false; |
| 39 } | 40 } |
| 41 |
| 42 GrGLExtensions extensions; |
| 43 if (!extensions.init(binding, this)) { |
| 44 return false; |
| 45 } |
| 40 | 46 |
| 41 // functions that are always required | 47 // functions that are always required |
| 42 if (NULL == fActiveTexture || | 48 if (NULL == fActiveTexture || |
| 43 NULL == fAttachShader || | 49 NULL == fAttachShader || |
| 44 NULL == fBindAttribLocation || | 50 NULL == fBindAttribLocation || |
| 45 NULL == fBindBuffer || | 51 NULL == fBindBuffer || |
| 46 NULL == fBindTexture || | 52 NULL == fBindTexture || |
| 47 NULL == fBlendFunc || | 53 NULL == fBlendFunc || |
| 48 NULL == fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension | 54 NULL == fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension |
| 49 NULL == fBufferData || | 55 NULL == fBufferData || |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 NULL == fFramebufferRenderbuffer || | 130 NULL == fFramebufferRenderbuffer || |
| 125 NULL == fFramebufferTexture2D || | 131 NULL == fFramebufferTexture2D || |
| 126 NULL == fGetFramebufferAttachmentParameteriv || | 132 NULL == fGetFramebufferAttachmentParameteriv || |
| 127 NULL == fGetRenderbufferParameteriv || | 133 NULL == fGetRenderbufferParameteriv || |
| 128 NULL == fGenFramebuffers || | 134 NULL == fGenFramebuffers || |
| 129 NULL == fGenRenderbuffers || | 135 NULL == fGenRenderbuffers || |
| 130 NULL == fRenderbufferStorage) { | 136 NULL == fRenderbufferStorage) { |
| 131 return false; | 137 return false; |
| 132 } | 138 } |
| 133 | 139 |
| 134 const char* ext; | |
| 135 GrGLVersion glVer = GrGLGetVersion(this); | 140 GrGLVersion glVer = GrGLGetVersion(this); |
| 136 ext = (const char*)fGetString(GR_GL_EXTENSIONS); | |
| 137 | 141 |
| 138 // Now check that baseline ES/Desktop fns not covered above are present | 142 // Now check that baseline ES/Desktop fns not covered above are present |
| 139 // and that we have fn pointers for any advertised extensions that we will | 143 // and that we have fn pointers for any advertised extensions that we will |
| 140 // try to use. | 144 // try to use. |
| 141 | 145 |
| 142 // these functions are part of ES2, we assume they are available | 146 // these functions are part of ES2, we assume they are available |
| 143 // On the desktop we assume they are available if the extension | 147 // On the desktop we assume they are available if the extension |
| 144 // is present or GL version is high enough. | 148 // is present or GL version is high enough. |
| 145 if (kES2_GrGLBinding == binding) { | 149 if (kES2_GrGLBinding == binding) { |
| 146 if (NULL == fStencilFuncSeparate || | 150 if (NULL == fStencilFuncSeparate || |
| 147 NULL == fStencilMaskSeparate || | 151 NULL == fStencilMaskSeparate || |
| 148 NULL == fStencilOpSeparate) { | 152 NULL == fStencilOpSeparate) { |
| 149 return false; | 153 return false; |
| 150 } | 154 } |
| 151 } else if (kDesktop_GrGLBinding == binding) { | 155 } else if (kDesktop_GrGLBinding == binding) { |
| 152 | 156 |
| 153 if (glVer >= GR_GL_VER(2,0)) { | 157 if (glVer >= GR_GL_VER(2,0)) { |
| 154 if (NULL == fStencilFuncSeparate || | 158 if (NULL == fStencilFuncSeparate || |
| 155 NULL == fStencilMaskSeparate || | 159 NULL == fStencilMaskSeparate || |
| 156 NULL == fStencilOpSeparate) { | 160 NULL == fStencilOpSeparate) { |
| 157 return false; | 161 return false; |
| 158 } | 162 } |
| 159 } | 163 } |
| 160 if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) { | 164 if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) { |
| 161 return false; | 165 return false; |
| 162 } | 166 } |
| 163 if (glVer >= GR_GL_VER(2,0) || | 167 if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) { |
| 164 GrGLHasExtensionFromString("GL_ARB_draw_buffers", ext)) { | |
| 165 if (NULL == fDrawBuffers) { | 168 if (NULL == fDrawBuffers) { |
| 166 return false; | 169 return false; |
| 167 } | 170 } |
| 168 } | 171 } |
| 169 | 172 |
| 170 if (glVer >= GR_GL_VER(1,5) || | 173 if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query"))
{ |
| 171 GrGLHasExtensionFromString("GL_ARB_occlusion_query", ext)) { | |
| 172 if (NULL == fGenQueries || | 174 if (NULL == fGenQueries || |
| 173 NULL == fDeleteQueries || | 175 NULL == fDeleteQueries || |
| 174 NULL == fBeginQuery || | 176 NULL == fBeginQuery || |
| 175 NULL == fEndQuery || | 177 NULL == fEndQuery || |
| 176 NULL == fGetQueryiv || | 178 NULL == fGetQueryiv || |
| 177 NULL == fGetQueryObjectiv || | 179 NULL == fGetQueryObjectiv || |
| 178 NULL == fGetQueryObjectuiv) { | 180 NULL == fGetQueryObjectuiv) { |
| 179 return false; | 181 return false; |
| 180 } | 182 } |
| 181 } | 183 } |
| 182 if (glVer >= GR_GL_VER(3,3) || | 184 if (glVer >= GR_GL_VER(3,3) || |
| 183 GrGLHasExtensionFromString("GL_ARB_timer_query", ext) || | 185 extensions.has("GL_ARB_timer_query") || |
| 184 GrGLHasExtensionFromString("GL_EXT_timer_query", ext)) { | 186 extensions.has("GL_EXT_timer_query")) { |
| 185 if (NULL == fGetQueryObjecti64v || | 187 if (NULL == fGetQueryObjecti64v || |
| 186 NULL == fGetQueryObjectui64v) { | 188 NULL == fGetQueryObjectui64v) { |
| 187 return false; | 189 return false; |
| 188 } | 190 } |
| 189 } | 191 } |
| 190 if (glVer >= GR_GL_VER(3,3) || | 192 if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) { |
| 191 GrGLHasExtensionFromString("GL_ARB_timer_query", ext)) { | |
| 192 if (NULL == fQueryCounter) { | 193 if (NULL == fQueryCounter) { |
| 193 return false; | 194 return false; |
| 194 } | 195 } |
| 195 } | 196 } |
| 196 // The below two blocks are checks for functions used with | 197 // The below two blocks are checks for functions used with |
| 197 // GL_NV_path_rendering. We're not enforcing that they be non-NULL | 198 // GL_NV_path_rendering. We're not enforcing that they be non-NULL |
| 198 // because they aren't actually called at this time. | 199 // because they aren't actually called at this time. |
| 199 if (false && | 200 if (false && |
| 200 (NULL == fMatrixMode || | 201 (NULL == fMatrixMode || |
| 201 NULL == fLoadIdentity || | 202 NULL == fLoadIdentity || |
| 202 NULL == fLoadMatrixf)) { | 203 NULL == fLoadMatrixf)) { |
| 203 return false; | 204 return false; |
| 204 } | 205 } |
| 205 if (false && GrGLHasExtensionFromString("GL_NV_path_rendering", ext)) { | 206 if (false && extensions.has("GL_NV_path_rendering")) { |
| 206 if (NULL == fPathCommands || | 207 if (NULL == fPathCommands || |
| 207 NULL == fPathCoords || | 208 NULL == fPathCoords || |
| 208 NULL == fPathSubCommands || | 209 NULL == fPathSubCommands || |
| 209 NULL == fPathSubCoords || | 210 NULL == fPathSubCoords || |
| 210 NULL == fPathString || | 211 NULL == fPathString || |
| 211 NULL == fPathGlyphs || | 212 NULL == fPathGlyphs || |
| 212 NULL == fPathGlyphRange || | 213 NULL == fPathGlyphRange || |
| 213 NULL == fWeightPaths || | 214 NULL == fWeightPaths || |
| 214 NULL == fCopyPath || | 215 NULL == fCopyPath || |
| 215 NULL == fInterpolatePaths || | 216 NULL == fInterpolatePaths || |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 NULL == fIsPointInStrokePath || | 253 NULL == fIsPointInStrokePath || |
| 253 NULL == fGetPathLength || | 254 NULL == fGetPathLength || |
| 254 NULL == fPointAlongPath) { | 255 NULL == fPointAlongPath) { |
| 255 return false; | 256 return false; |
| 256 } | 257 } |
| 257 } | 258 } |
| 258 } | 259 } |
| 259 | 260 |
| 260 // optional function on desktop before 1.3 | 261 // optional function on desktop before 1.3 |
| 261 if (kDesktop_GrGLBinding != binding || | 262 if (kDesktop_GrGLBinding != binding || |
| 262 (glVer >= GR_GL_VER(1,3) || | 263 (glVer >= GR_GL_VER(1,3)) || |
| 263 GrGLHasExtensionFromString("GL_ARB_texture_compression", ext))) { | 264 extensions.has("GL_ARB_texture_compression")) { |
| 264 if (NULL == fCompressedTexImage2D) { | 265 if (NULL == fCompressedTexImage2D) { |
| 265 return false; | 266 return false; |
| 266 } | 267 } |
| 267 } | 268 } |
| 268 | 269 |
| 269 // part of desktop GL, but not ES | 270 // part of desktop GL, but not ES |
| 270 if (kDesktop_GrGLBinding == binding && | 271 if (kDesktop_GrGLBinding == binding && |
| 271 (NULL == fLineWidth || | 272 (NULL == fLineWidth || |
| 272 NULL == fGetTexLevelParameteriv || | 273 NULL == fGetTexLevelParameteriv || |
| 273 NULL == fDrawBuffer || | 274 NULL == fDrawBuffer || |
| 274 NULL == fReadBuffer)) { | 275 NULL == fReadBuffer)) { |
| 275 return false; | 276 return false; |
| 276 } | 277 } |
| 277 | 278 |
| 278 // GL_EXT_texture_storage is part of desktop 4.2 | 279 // GL_EXT_texture_storage is part of desktop 4.2 |
| 279 // There is a desktop ARB extension and an ES+desktop EXT extension | 280 // There is a desktop ARB extension and an ES+desktop EXT extension |
| 280 if (kDesktop_GrGLBinding == binding) { | 281 if (kDesktop_GrGLBinding == binding) { |
| 281 if (glVer >= GR_GL_VER(4,2) || | 282 if (glVer >= GR_GL_VER(4,2) || |
| 282 GrGLHasExtensionFromString("GL_ARB_texture_storage", ext) || | 283 extensions.has("GL_ARB_texture_storage") || |
| 283 GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) { | 284 extensions.has("GL_EXT_texture_storage")) { |
| 284 if (NULL == fTexStorage2D) { | 285 if (NULL == fTexStorage2D) { |
| 285 return false; | 286 return false; |
| 286 } | 287 } |
| 287 } | 288 } |
| 288 } else if (GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) { | 289 } else if (extensions.has("GL_EXT_texture_storage")) { |
| 289 if (NULL == fTexStorage2D) { | 290 if (NULL == fTexStorage2D) { |
| 290 return false; | 291 return false; |
| 291 } | 292 } |
| 292 } | 293 } |
| 293 | 294 |
| 294 // FBO MSAA | 295 // FBO MSAA |
| 295 if (kDesktop_GrGLBinding == binding) { | 296 if (kDesktop_GrGLBinding == binding) { |
| 296 // GL 3.0 and the ARB extension have multisample + blit | 297 // GL 3.0 and the ARB extension have multisample + blit |
| 297 if (glVer >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_frameb
uffer_object", ext)) { | 298 if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object
")) { |
| 298 if (NULL == fRenderbufferStorageMultisample || | 299 if (NULL == fRenderbufferStorageMultisample || |
| 299 NULL == fBlitFramebuffer) { | 300 NULL == fBlitFramebuffer) { |
| 300 return false; | 301 return false; |
| 301 } | 302 } |
| 302 } else { | 303 } else { |
| 303 if (GrGLHasExtensionFromString("GL_EXT_framebuffer_blit", ext) && | 304 if (extensions.has("GL_EXT_framebuffer_blit") && |
| 304 NULL == fBlitFramebuffer) { | 305 NULL == fBlitFramebuffer) { |
| 305 return false; | 306 return false; |
| 306 } | 307 } |
| 307 if (GrGLHasExtensionFromString("GL_EXT_framebuffer_multisample", ext
) && | 308 if (extensions.has("GL_EXT_framebuffer_multisample") && |
| 308 NULL == fRenderbufferStorageMultisample) { | 309 NULL == fRenderbufferStorageMultisample) { |
| 309 return false; | 310 return false; |
| 310 } | 311 } |
| 311 } | 312 } |
| 312 } else { | 313 } else { |
| 313 if (GrGLHasExtensionFromString("GL_CHROMIUM_framebuffer_multisample", ex
t)) { | 314 if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) { |
| 314 if (NULL == fRenderbufferStorageMultisample || | 315 if (NULL == fRenderbufferStorageMultisample || |
| 315 NULL == fBlitFramebuffer) { | 316 NULL == fBlitFramebuffer) { |
| 316 return false; | 317 return false; |
| 317 } | 318 } |
| 318 } | 319 } |
| 319 if (GrGLHasExtensionFromString("GL_APPLE_framebuffer_multisample", ext))
{ | 320 if (extensions.has("GL_APPLE_framebuffer_multisample")) { |
| 320 if (NULL == fRenderbufferStorageMultisample || | 321 if (NULL == fRenderbufferStorageMultisample || |
| 321 NULL == fResolveMultisampleFramebuffer) { | 322 NULL == fResolveMultisampleFramebuffer) { |
| 322 return false; | 323 return false; |
| 323 } | 324 } |
| 324 } | 325 } |
| 325 } | 326 } |
| 326 | 327 |
| 327 // On ES buffer mapping is an extension. On Desktop | 328 // On ES buffer mapping is an extension. On Desktop |
| 328 // buffer mapping was part of original VBO extension | 329 // buffer mapping was part of original VBO extension |
| 329 // which we require. | 330 // which we require. |
| 330 if (kDesktop_GrGLBinding == binding || | 331 if (kDesktop_GrGLBinding == binding || extensions.has("GL_OES_mapbuffer")) { |
| 331 GrGLHasExtensionFromString("GL_OES_mapbuffer", ext)) { | |
| 332 if (NULL == fMapBuffer || | 332 if (NULL == fMapBuffer || |
| 333 NULL == fUnmapBuffer) { | 333 NULL == fUnmapBuffer) { |
| 334 return false; | 334 return false; |
| 335 } | 335 } |
| 336 } | 336 } |
| 337 | 337 |
| 338 // Dual source blending | 338 // Dual source blending |
| 339 if (kDesktop_GrGLBinding == binding && | 339 if (kDesktop_GrGLBinding == binding && |
| 340 (glVer >= GR_GL_VER(3,3) || | 340 (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended")
)) { |
| 341 GrGLHasExtensionFromString("GL_ARB_blend_func_extended", ext))) { | |
| 342 if (NULL == fBindFragDataLocationIndexed) { | 341 if (NULL == fBindFragDataLocationIndexed) { |
| 343 return false; | 342 return false; |
| 344 } | 343 } |
| 345 } | 344 } |
| 345 |
| 346 if (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3, 0)) { |
| 347 if (NULL == fGetStringi) { |
| 348 return false; |
| 349 } |
| 350 } |
| 346 | 351 |
| 347 return true; | 352 return true; |
| 348 } | 353 } |
| OLD | NEW |