1/* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9#include "gl/GrGLInterface.h" 10#include "gl/GrGLExtensions.h" 11#include "gl/GrGLUtil.h" 12 13#include <stdio.h> 14 15#if GR_GL_PER_GL_FUNC_CALLBACK 16namespace { 17void GrGLDefaultInterfaceCallback(const GrGLInterface*) {} 18} 19#endif 20 21GrGLInterface::GrGLInterface() { 22 fBindingsExported = kNone_GrGLBinding; 23 24#if GR_GL_PER_GL_FUNC_CALLBACK 25 fCallback = GrGLDefaultInterfaceCallback; 26 fCallbackData = 0; 27#endif 28} 29 30bool GrGLInterface::validate(GrGLBinding binding) const { 31 32 // kNone must be 0 so that the check we're about to do can never succeed if 33 // binding == kNone. 34 GR_STATIC_ASSERT(kNone_GrGLBinding == 0); 35 36 if (0 == (binding & fBindingsExported)) { 37 return false; 38 } 39 40 GrGLExtensions extensions; 41 if (!extensions.init(binding, this)) { 42 return false; 43 } 44 45 // functions that are always required 46 if (NULL == fActiveTexture || 47 NULL == fAttachShader || 48 NULL == fBindAttribLocation || 49 NULL == fBindBuffer || 50 NULL == fBindTexture || 51 NULL == fBlendFunc || 52 NULL == fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension 53 NULL == fBufferData || 54 NULL == fBufferSubData || 55 NULL == fClear || 56 NULL == fClearColor || 57 NULL == fClearStencil || 58 NULL == fColorMask || 59 NULL == fCompileShader || 60 NULL == fCopyTexSubImage2D || 61 NULL == fCreateProgram || 62 NULL == fCreateShader || 63 NULL == fCullFace || 64 NULL == fDeleteBuffers || 65 NULL == fDeleteProgram || 66 NULL == fDeleteShader || 67 NULL == fDeleteTextures || 68 NULL == fDepthMask || 69 NULL == fDisable || 70 NULL == fDisableVertexAttribArray || 71 NULL == fDrawArrays || 72 NULL == fDrawElements || 73 NULL == fEnable || 74 NULL == fEnableVertexAttribArray || 75 NULL == fFrontFace || 76 NULL == fGenBuffers || 77 NULL == fGenTextures || 78 NULL == fGetBufferParameteriv || 79 NULL == fGenerateMipmap || 80 NULL == fGetError || 81 NULL == fGetIntegerv || 82 NULL == fGetProgramInfoLog || 83 NULL == fGetProgramiv || 84 NULL == fGetShaderInfoLog || 85 NULL == fGetShaderiv || 86 NULL == fGetString || 87 NULL == fGetUniformLocation || 88 NULL == fLinkProgram || 89 NULL == fLineWidth || 90 NULL == fPixelStorei || 91 NULL == fReadPixels || 92 NULL == fScissor || 93 NULL == fShaderSource || 94 NULL == fStencilFunc || 95 NULL == fStencilMask || 96 NULL == fStencilOp || 97 NULL == fTexImage2D || 98 NULL == fTexParameteri || 99 NULL == fTexParameteriv || 100 NULL == fTexSubImage2D || 101 NULL == fUniform1f || 102 NULL == fUniform1i || 103 NULL == fUniform1fv || 104 NULL == fUniform1iv || 105 NULL == fUniform2f || 106 NULL == fUniform2i || 107 NULL == fUniform2fv || 108 NULL == fUniform2iv || 109 NULL == fUniform3f || 110 NULL == fUniform3i || 111 NULL == fUniform3fv || 112 NULL == fUniform3iv || 113 NULL == fUniform4f || 114 NULL == fUniform4i || 115 NULL == fUniform4fv || 116 NULL == fUniform4iv || 117 NULL == fUniformMatrix2fv || 118 NULL == fUniformMatrix3fv || 119 NULL == fUniformMatrix4fv || 120 NULL == fUseProgram || 121 NULL == fVertexAttrib4fv || 122 NULL == fVertexAttribPointer || 123 NULL == fViewport || 124 NULL == fBindFramebuffer || 125 NULL == fBindRenderbuffer || 126 NULL == fCheckFramebufferStatus || 127 NULL == fDeleteFramebuffers || 128 NULL == fDeleteRenderbuffers || 129 NULL == fFinish || 130 NULL == fFlush || 131 NULL == fFramebufferRenderbuffer || 132 NULL == fFramebufferTexture2D || 133 NULL == fGetFramebufferAttachmentParameteriv || 134 NULL == fGetRenderbufferParameteriv || 135 NULL == fGenFramebuffers || 136 NULL == fGenRenderbuffers || 137 NULL == fRenderbufferStorage) { 138 return false; 139 } 140 141 GrGLVersion glVer = GrGLGetVersion(this); 142 143 bool isCoreProfile = false; 144 if (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3,2)) { 145 GrGLint profileMask; 146 GR_GL_GetIntegerv(this, GR_GL_CONTEXT_PROFILE_MASK, &profileMask); 147 isCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT); 148 } 149 150 // Now check that baseline ES/Desktop fns not covered above are present 151 // and that we have fn pointers for any advertised extensions that we will 152 // try to use. 153 154 // these functions are part of ES2, we assume they are available 155 // On the desktop we assume they are available if the extension 156 // is present or GL version is high enough. 157 if (kES_GrGLBinding == binding) { 158 if (NULL == fStencilFuncSeparate || 159 NULL == fStencilMaskSeparate || 160 NULL == fStencilOpSeparate) { 161 return false; 162 } 163 } else if (kDesktop_GrGLBinding == binding) { 164 165 if (glVer >= GR_GL_VER(2,0)) { 166 if (NULL == fStencilFuncSeparate || 167 NULL == fStencilMaskSeparate || 168 NULL == fStencilOpSeparate) { 169 return false; 170 } 171 } 172 if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) { 173 return false; 174 } 175 if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) { 176 if (NULL == fDrawBuffers) { 177 return false; 178 } 179 } 180 181 if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) { 182 if (NULL == fGenQueries || 183 NULL == fDeleteQueries || 184 NULL == fBeginQuery || 185 NULL == fEndQuery || 186 NULL == fGetQueryiv || 187 NULL == fGetQueryObjectiv || 188 NULL == fGetQueryObjectuiv) { 189 return false; 190 } 191 } 192 if (glVer >= GR_GL_VER(3,3) || 193 extensions.has("GL_ARB_timer_query") || 194 extensions.has("GL_EXT_timer_query")) { 195 if (NULL == fGetQueryObjecti64v || 196 NULL == fGetQueryObjectui64v) { 197 return false; 198 } 199 } 200 if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) { 201 if (NULL == fQueryCounter) { 202 return false; 203 } 204 } 205 if (!isCoreProfile) { 206 if (NULL == fClientActiveTexture || 207 NULL == fDisableClientState || 208 NULL == fEnableClientState || 209 NULL == fLoadIdentity || 210 NULL == fLoadMatrixf || 211 NULL == fMatrixMode || 212 NULL == fTexGenf || 213 NULL == fTexGenfv || 214 NULL == fTexGeni || 215 NULL == fVertexPointer) { 216 return false; 217 } 218 } 219 if (false && extensions.has("GL_NV_path_rendering")) { 220 if (NULL == fPathCommands || 221 NULL == fPathCoords || 222 NULL == fPathSubCommands || 223 NULL == fPathSubCoords || 224 NULL == fPathString || 225 NULL == fPathGlyphs || 226 NULL == fPathGlyphRange || 227 NULL == fWeightPaths || 228 NULL == fCopyPath || 229 NULL == fInterpolatePaths || 230 NULL == fTransformPath || 231 NULL == fPathParameteriv || 232 NULL == fPathParameteri || 233 NULL == fPathParameterfv || 234 NULL == fPathParameterf || 235 NULL == fPathDashArray || 236 NULL == fGenPaths || 237 NULL == fDeletePaths || 238 NULL == fIsPath || 239 NULL == fPathStencilFunc || 240 NULL == fPathStencilDepthOffset || 241 NULL == fStencilFillPath || 242 NULL == fStencilStrokePath || 243 NULL == fStencilFillPathInstanced || 244 NULL == fStencilStrokePathInstanced || 245 NULL == fPathCoverDepthFunc || 246 NULL == fPathColorGen || 247 NULL == fPathTexGen || 248 NULL == fPathFogGen || 249 NULL == fCoverFillPath || 250 NULL == fCoverStrokePath || 251 NULL == fCoverFillPathInstanced || 252 NULL == fCoverStrokePathInstanced || 253 NULL == fGetPathParameteriv || 254 NULL == fGetPathParameterfv || 255 NULL == fGetPathCommands || 256 NULL == fGetPathCoords || 257 NULL == fGetPathDashArray || 258 NULL == fGetPathMetrics || 259 NULL == fGetPathMetricRange || 260 NULL == fGetPathSpacing || 261 NULL == fGetPathColorGeniv || 262 NULL == fGetPathColorGenfv || 263 NULL == fGetPathTexGeniv || 264 NULL == fGetPathTexGenfv || 265 NULL == fIsPointInFillPath || 266 NULL == fIsPointInStrokePath || 267 NULL == fGetPathLength || 268 NULL == fPointAlongPath) { 269 return false; 270 } 271 } 272 } 273 274 // optional function on desktop before 1.3 275 if (kDesktop_GrGLBinding != binding || 276 (glVer >= GR_GL_VER(1,3)) || 277 extensions.has("GL_ARB_texture_compression")) { 278 if (NULL == fCompressedTexImage2D) { 279 return false; 280 } 281 } 282 283 // part of desktop GL, but not ES 284 if (kDesktop_GrGLBinding == binding && 285 (NULL == fGetTexLevelParameteriv || 286 NULL == fDrawBuffer || 287 NULL == fReadBuffer)) { 288 return false; 289 } 290 291 // GL_EXT_texture_storage is part of desktop 4.2 292 // There is a desktop ARB extension and an ES+desktop EXT extension 293 if (kDesktop_GrGLBinding == binding) { 294 if (glVer >= GR_GL_VER(4,2) || 295 extensions.has("GL_ARB_texture_storage") || 296 extensions.has("GL_EXT_texture_storage")) { 297 if (NULL == fTexStorage2D) { 298 return false; 299 } 300 } 301 } else if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_EXT_texture_storage")) { 302 if (NULL == fTexStorage2D) { 303 return false; 304 } 305 } 306 307 if (extensions.has("GL_EXT_discard_framebuffer")) { 308// FIXME: Remove this once Chromium is updated to provide this function 309#if 0 310 if (NULL == fDiscardFramebuffer) { 311 return false; 312 } 313#endif 314 } 315 316 // FBO MSAA 317 if (kDesktop_GrGLBinding == binding) { 318 // GL 3.0 and the ARB extension have multisample + blit 319 if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) { 320 if (NULL == fRenderbufferStorageMultisample || 321 NULL == fBlitFramebuffer) { 322 return false; 323 } 324 } else { 325 if (extensions.has("GL_EXT_framebuffer_blit") && 326 NULL == fBlitFramebuffer) { 327 return false; 328 } 329 if (extensions.has("GL_EXT_framebuffer_multisample") && 330 NULL == fRenderbufferStorageMultisample) { 331 return false; 332 } 333 } 334 } else { 335#if GR_GL_IGNORE_ES3_MSAA 336 if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) { 337 if (NULL == fRenderbufferStorageMultisample || 338 NULL == fBlitFramebuffer) { 339 return false; 340 } 341 } else if (extensions.has("GL_APPLE_framebuffer_multisample")) { 342 if (NULL == fRenderbufferStorageMultisample || 343 NULL == fResolveMultisampleFramebuffer) { 344 return false; 345 } 346 } else if (extensions.has("GL_IMG_multisampled_render_to_texture") || 347 extensions.has("GL_EXT_multisampled_render_to_texture")) { 348 if (NULL == fRenderbufferStorageMultisample || 349 NULL == fFramebufferTexture2DMultisample) { 350 return false; 351 } 352 } 353#else 354 if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_CHROMIUM_framebuffer_multisample")) { 355 if (NULL == fRenderbufferStorageMultisample || 356 NULL == fBlitFramebuffer) { 357 return false; 358 } 359 } 360 if (extensions.has("GL_APPLE_framebuffer_multisample")) { 361 if (NULL == fRenderbufferStorageMultisampleES2APPLE || 362 NULL == fResolveMultisampleFramebuffer) { 363 return false; 364 } 365 } 366 if (extensions.has("GL_IMG_multisampled_render_to_texture") || 367 extensions.has("GL_EXT_multisampled_render_to_texture")) { 368 if (NULL == fRenderbufferStorageMultisampleES2EXT || 369 NULL == fFramebufferTexture2DMultisample) { 370 return false; 371 } 372 } 373#endif 374 } 375 376 // On ES buffer mapping is an extension. On Desktop 377 // buffer mapping was part of original VBO extension 378 // which we require. 379 if (kDesktop_GrGLBinding == binding || extensions.has("GL_OES_mapbuffer")) { 380 if (NULL == fMapBuffer || 381 NULL == fUnmapBuffer) { 382 return false; 383 } 384 } 385 386 // Dual source blending 387 if (kDesktop_GrGLBinding == binding && 388 (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) { 389 if (NULL == fBindFragDataLocationIndexed) { 390 return false; 391 } 392 } 393 394 // glGetStringi was added in version 3.0 of both desktop and ES. 395 if (glVer >= GR_GL_VER(3, 0)) { 396 if (NULL == fGetStringi) { 397 return false; 398 } 399 } 400 401 if (kDesktop_GrGLBinding == binding) { 402 if (glVer >= GR_GL_VER(3, 0) || extensions.has("GL_ARB_vertex_array_object")) { 403 if (NULL == fBindVertexArray || 404 NULL == fDeleteVertexArrays || 405 NULL == fGenVertexArrays) { 406 return false; 407 } 408 } 409 } else { 410 if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_OES_vertex_array_object")) { 411 if (NULL == fBindVertexArray || 412 NULL == fDeleteVertexArrays || 413 NULL == fGenVertexArrays) { 414 return false; 415 } 416 } 417 } 418 419 return true; 420} 421