| /* | 
 |  * Copyright 2011 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 |  | 
 | #include "GrGLUtil.h" | 
 | #include "SkMatrix.h" | 
 | #include <stdio.h> | 
 |  | 
 | void GrGLClearErr(const GrGLInterface* gl) { | 
 |     while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {} | 
 | } | 
 |  | 
 | namespace { | 
 | const char *get_error_string(uint32_t err) { | 
 |     switch (err) { | 
 |     case GR_GL_NO_ERROR: | 
 |         return ""; | 
 |     case GR_GL_INVALID_ENUM: | 
 |         return "Invalid Enum"; | 
 |     case GR_GL_INVALID_VALUE: | 
 |         return "Invalid Value"; | 
 |     case GR_GL_INVALID_OPERATION: | 
 |         return "Invalid Operation"; | 
 |     case GR_GL_OUT_OF_MEMORY: | 
 |         return "Out of Memory"; | 
 |     case GR_GL_CONTEXT_LOST: | 
 |         return "Context Lost"; | 
 |     } | 
 |     return "Unknown"; | 
 | } | 
 | } | 
 |  | 
 | void GrGLCheckErr(const GrGLInterface* gl, | 
 |                   const char* location, | 
 |                   const char* call) { | 
 |     uint32_t err = GR_GL_GET_ERROR(gl); | 
 |     if (GR_GL_NO_ERROR != err) { | 
 |         GrPrintf("---- glGetError 0x%x(%s)", err, get_error_string(err)); | 
 |         if (NULL != location) { | 
 |             GrPrintf(" at\n\t%s", location); | 
 |         } | 
 |         if (NULL != call) { | 
 |             GrPrintf("\n\t\t%s", call); | 
 |         } | 
 |         GrPrintf("\n"); | 
 |     } | 
 | } | 
 |  | 
 | namespace { | 
 | // Mesa uses a non-standard version string of format: 1.4 Mesa <mesa_major>.<mesa_minor>. | 
 | // The mapping of from mesa version to GL version came from here: http://www.mesa3d.org/intro.html | 
 | bool get_gl_version_for_mesa(int mesaMajorVersion, int* major, int* minor) { | 
 |     switch (mesaMajorVersion) { | 
 |         case 2: | 
 |         case 3: | 
 |         case 4: | 
 |         case 5: | 
 |         case 6: | 
 |             *major = 1; | 
 |             *minor = mesaMajorVersion - 1; | 
 |             return true; | 
 |         case 7: | 
 |             *major = 2; | 
 |             *minor = 1; | 
 |             return true; | 
 |         case 8: | 
 |             *major = 3; | 
 |             *minor = 0; | 
 |             return true; | 
 |         case 9: | 
 |             *major = 3; | 
 |             *minor = 1; | 
 |             return true; | 
 |         case 10: | 
 |             *major = 3; | 
 |             *minor = 3; | 
 |             return true; | 
 |         default: | 
 |             return false; | 
 |     } | 
 | } | 
 | } | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | #if GR_GL_LOG_CALLS | 
 |     bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START); | 
 | #endif | 
 |  | 
 | #if GR_GL_CHECK_ERROR | 
 |     bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START); | 
 | #endif | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) { | 
 |     if (NULL == versionString) { | 
 |         SkDebugf("NULL GL version string."); | 
 |         return kNone_GrGLStandard; | 
 |     } | 
 |  | 
 |     int major, minor; | 
 |  | 
 |     // check for desktop | 
 |     int n = sscanf(versionString, "%d.%d", &major, &minor); | 
 |     if (2 == n) { | 
 |         return kGL_GrGLStandard; | 
 |     } | 
 |  | 
 |     // check for ES 1 | 
 |     char profile[2]; | 
 |     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, &major, &minor); | 
 |     if (4 == n) { | 
 |         // we no longer support ES1. | 
 |         return kNone_GrGLStandard; | 
 |     } | 
 |  | 
 |     // check for ES2 | 
 |     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor); | 
 |     if (2 == n) { | 
 |         return kGLES_GrGLStandard; | 
 |     } | 
 |     return kNone_GrGLStandard; | 
 | } | 
 |  | 
 | bool GrGLIsMesaFromVersionString(const char* versionString) { | 
 |     int major, minor, mesaMajor, mesaMinor; | 
 |     int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor); | 
 |     return 4 == n; | 
 | } | 
 |  | 
 | bool GrGLIsChromiumFromRendererString(const char* rendererString) { | 
 |     return 0 == strcmp(rendererString, "Chromium"); | 
 | } | 
 |  | 
 | GrGLVersion GrGLGetVersionFromString(const char* versionString) { | 
 |     if (NULL == versionString) { | 
 |         SkDebugf("NULL GL version string."); | 
 |         return GR_GL_INVALID_VER; | 
 |     } | 
 |  | 
 |     int major, minor; | 
 |  | 
 |     // check for mesa | 
 |     int mesaMajor, mesaMinor; | 
 |     int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor); | 
 |     if (4 == n) { | 
 |         if (get_gl_version_for_mesa(mesaMajor, &major, &minor)) { | 
 |             return GR_GL_VER(major, minor); | 
 |         } else { | 
 |             return GR_GL_INVALID_VER; | 
 |         } | 
 |     } | 
 |  | 
 |     n = sscanf(versionString, "%d.%d", &major, &minor); | 
 |     if (2 == n) { | 
 |         return GR_GL_VER(major, minor); | 
 |     } | 
 |  | 
 |     char profile[2]; | 
 |     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, | 
 |                &major, &minor); | 
 |     if (4 == n) { | 
 |         return GR_GL_VER(major, minor); | 
 |     } | 
 |  | 
 |     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor); | 
 |     if (2 == n) { | 
 |         return GR_GL_VER(major, minor); | 
 |     } | 
 |  | 
 |     return GR_GL_INVALID_VER; | 
 | } | 
 |  | 
 | GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) { | 
 |     if (NULL == versionString) { | 
 |         SkDebugf("NULL GLSL version string."); | 
 |         return GR_GLSL_INVALID_VER; | 
 |     } | 
 |  | 
 |     int major, minor; | 
 |  | 
 |     int n = sscanf(versionString, "%d.%d", &major, &minor); | 
 |     if (2 == n) { | 
 |         return GR_GLSL_VER(major, minor); | 
 |     } | 
 |  | 
 |     n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor); | 
 |     if (2 == n) { | 
 |         return GR_GLSL_VER(major, minor); | 
 |     } | 
 |  | 
 | #ifdef SK_BUILD_FOR_ANDROID | 
 |     // android hack until the gpu vender updates their drivers | 
 |     n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor); | 
 |     if (2 == n) { | 
 |         return GR_GLSL_VER(major, minor); | 
 |     } | 
 | #endif | 
 |  | 
 |     return GR_GLSL_INVALID_VER; | 
 | } | 
 |  | 
 | GrGLVendor GrGLGetVendorFromString(const char* vendorString) { | 
 |     if (NULL != vendorString) { | 
 |         if (0 == strcmp(vendorString, "ARM")) { | 
 |             return kARM_GrGLVendor; | 
 |         } | 
 |         if (0 == strcmp(vendorString, "Imagination Technologies")) { | 
 |             return kImagination_GrGLVendor; | 
 |         } | 
 |         if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) { | 
 |             return kIntel_GrGLVendor; | 
 |         } | 
 |         if (0 == strcmp(vendorString, "Qualcomm")) { | 
 |             return kQualcomm_GrGLVendor; | 
 |         } | 
 |     } | 
 |     return kOther_GrGLVendor; | 
 | } | 
 |  | 
 | GrGLRenderer GrGLGetRendererFromString(const char* rendererString) { | 
 |     if (NULL != rendererString) { | 
 |         if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) { | 
 |             return kTegra3_GrGLRenderer; | 
 |         } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) { | 
 |             return kTegra2_GrGLRenderer; | 
 |         } | 
 |     } | 
 |     return kOther_GrGLRenderer; | 
 | } | 
 |  | 
 | GrGLVersion GrGLGetVersion(const GrGLInterface* gl) { | 
 |     const GrGLubyte* v; | 
 |     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION)); | 
 |     return GrGLGetVersionFromString((const char*) v); | 
 | } | 
 |  | 
 | GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) { | 
 |     const GrGLubyte* v; | 
 |     GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); | 
 |     return GrGLGetGLSLVersionFromString((const char*) v); | 
 | } | 
 |  | 
 | GrGLVendor GrGLGetVendor(const GrGLInterface* gl) { | 
 |     const GrGLubyte* v; | 
 |     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR)); | 
 |     return GrGLGetVendorFromString((const char*) v); | 
 | } | 
 |  | 
 | GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) { | 
 |     const GrGLubyte* v; | 
 |     GR_GL_CALL_RET(gl, v, GetString(GR_GL_RENDERER)); | 
 |     return GrGLGetRendererFromString((const char*) v); | 
 | } | 
 |  | 
 | template<> void GrGLGetMatrix<3>(GrGLfloat* dest, const SkMatrix& src) { | 
 |     // Col 0 | 
 |     dest[0] = SkScalarToFloat(src[SkMatrix::kMScaleX]); | 
 |     dest[1] = SkScalarToFloat(src[SkMatrix::kMSkewY]); | 
 |     dest[2] = SkScalarToFloat(src[SkMatrix::kMPersp0]); | 
 |  | 
 |     // Col 1 | 
 |     dest[3] = SkScalarToFloat(src[SkMatrix::kMSkewX]); | 
 |     dest[4] = SkScalarToFloat(src[SkMatrix::kMScaleY]); | 
 |     dest[5] = SkScalarToFloat(src[SkMatrix::kMPersp1]); | 
 |  | 
 |     // Col 2 | 
 |     dest[6] = SkScalarToFloat(src[SkMatrix::kMTransX]); | 
 |     dest[7] = SkScalarToFloat(src[SkMatrix::kMTransY]); | 
 |     dest[8] = SkScalarToFloat(src[SkMatrix::kMPersp2]); | 
 | } | 
 |  | 
 | template<> void GrGLGetMatrix<4>(GrGLfloat* dest, const SkMatrix& src) { | 
 |     // Col 0 | 
 |     dest[0]  = SkScalarToFloat(src[SkMatrix::kMScaleX]); | 
 |     dest[1]  = SkScalarToFloat(src[SkMatrix::kMSkewY]); | 
 |     dest[2]  = 0; | 
 |     dest[3]  = SkScalarToFloat(src[SkMatrix::kMPersp0]); | 
 |  | 
 |     // Col 1 | 
 |     dest[4]  = SkScalarToFloat(src[SkMatrix::kMSkewX]); | 
 |     dest[5]  = SkScalarToFloat(src[SkMatrix::kMScaleY]); | 
 |     dest[6]  = 0; | 
 |     dest[7]  = SkScalarToFloat(src[SkMatrix::kMPersp1]); | 
 |  | 
 |     // Col 2 | 
 |     dest[8]  = 0; | 
 |     dest[9]  = 0; | 
 |     dest[10] = 1; | 
 |     dest[11] = 0; | 
 |  | 
 |     // Col 3 | 
 |     dest[12] = SkScalarToFloat(src[SkMatrix::kMTransX]); | 
 |     dest[13] = SkScalarToFloat(src[SkMatrix::kMTransY]); | 
 |     dest[14] = 0; | 
 |     dest[15] = SkScalarToFloat(src[SkMatrix::kMPersp2]); | 
 | } |