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