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 "GrGLUtil.h"
10#include "SkMatrix.h"
11#include <stdio.h>
12
13void GrGLClearErr(const GrGLInterface* gl) {
14    while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {}
15}
16
17namespace {
18const char *get_error_string(uint32_t err) {
19    switch (err) {
20    case GR_GL_NO_ERROR:
21        return "";
22    case GR_GL_INVALID_ENUM:
23        return "Invalid Enum";
24    case GR_GL_INVALID_VALUE:
25        return "Invalid Value";
26    case GR_GL_INVALID_OPERATION:
27        return "Invalid Operation";
28    case GR_GL_OUT_OF_MEMORY:
29        return "Out of Memory";
30    case GR_GL_CONTEXT_LOST:
31        return "Context Lost";
32    }
33    return "Unknown";
34}
35}
36
37void GrGLCheckErr(const GrGLInterface* gl,
38                  const char* location,
39                  const char* call) {
40    uint32_t err = GR_GL_GET_ERROR(gl);
41    if (GR_GL_NO_ERROR != err) {
42        GrPrintf("---- glGetError 0x%x(%s)", err, get_error_string(err));
43        if (location) {
44            GrPrintf(" at\n\t%s", location);
45        }
46        if (call) {
47            GrPrintf("\n\t\t%s", call);
48        }
49        GrPrintf("\n");
50    }
51}
52
53///////////////////////////////////////////////////////////////////////////////
54
55#if GR_GL_LOG_CALLS
56    bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
57#endif
58
59#if GR_GL_CHECK_ERROR
60    bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);
61#endif
62
63///////////////////////////////////////////////////////////////////////////////
64
65GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) {
66    if (NULL == versionString) {
67        SkDebugf("NULL GL version string.");
68        return kNone_GrGLStandard;
69    }
70
71    int major, minor;
72
73    // check for desktop
74    int n = sscanf(versionString, "%d.%d", &major, &minor);
75    if (2 == n) {
76        return kGL_GrGLStandard;
77    }
78
79    // check for ES 1
80    char profile[2];
81    n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, &major, &minor);
82    if (4 == n) {
83        // we no longer support ES1.
84        return kNone_GrGLStandard;
85    }
86
87    // check for ES2
88    n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
89    if (2 == n) {
90        return kGLES_GrGLStandard;
91    }
92    return kNone_GrGLStandard;
93}
94
95bool GrGLIsMesaFromVersionString(const char* versionString) {
96    int major, minor, mesaMajor, mesaMinor;
97    int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
98    return 4 == n;
99}
100
101bool GrGLIsChromiumFromRendererString(const char* rendererString) {
102    return 0 == strcmp(rendererString, "Chromium");
103}
104
105GrGLVersion GrGLGetVersionFromString(const char* versionString) {
106    if (NULL == versionString) {
107        SkDebugf("NULL GL version string.");
108        return GR_GL_INVALID_VER;
109    }
110
111    int major, minor;
112
113    // check for mesa
114    int mesaMajor, mesaMinor;
115    int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
116    if (4 == n) {
117        return GR_GL_VER(major, minor);
118    }
119
120    n = sscanf(versionString, "%d.%d", &major, &minor);
121    if (2 == n) {
122        return GR_GL_VER(major, minor);
123    }
124
125    char profile[2];
126    n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
127               &major, &minor);
128    if (4 == n) {
129        return GR_GL_VER(major, minor);
130    }
131
132    n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
133    if (2 == n) {
134        return GR_GL_VER(major, minor);
135    }
136
137    return GR_GL_INVALID_VER;
138}
139
140GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
141    if (NULL == versionString) {
142        SkDebugf("NULL GLSL version string.");
143        return GR_GLSL_INVALID_VER;
144    }
145
146    int major, minor;
147
148    int n = sscanf(versionString, "%d.%d", &major, &minor);
149    if (2 == n) {
150        return GR_GLSL_VER(major, minor);
151    }
152
153    n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
154    if (2 == n) {
155        return GR_GLSL_VER(major, minor);
156    }
157
158#ifdef SK_BUILD_FOR_ANDROID
159    // android hack until the gpu vender updates their drivers
160    n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
161    if (2 == n) {
162        return GR_GLSL_VER(major, minor);
163    }
164#endif
165
166    return GR_GLSL_INVALID_VER;
167}
168
169GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
170    if (vendorString) {
171        if (0 == strcmp(vendorString, "ARM")) {
172            return kARM_GrGLVendor;
173        }
174        if (0 == strcmp(vendorString, "Imagination Technologies")) {
175            return kImagination_GrGLVendor;
176        }
177        if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
178            return kIntel_GrGLVendor;
179        }
180        if (0 == strcmp(vendorString, "Qualcomm")) {
181            return kQualcomm_GrGLVendor;
182        }
183        if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
184                return kNVIDIA_GrGLVendor;
185        }
186    }
187    return kOther_GrGLVendor;
188}
189
190GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
191    if (rendererString) {
192        if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) {
193            return kTegra3_GrGLRenderer;
194        } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
195            return kTegra2_GrGLRenderer;
196        }
197    }
198    return kOther_GrGLRenderer;
199}
200
201GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
202    const GrGLubyte* v;
203    GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
204    return GrGLGetVersionFromString((const char*) v);
205}
206
207GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
208    const GrGLubyte* v;
209    GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
210    return GrGLGetGLSLVersionFromString((const char*) v);
211}
212
213GrGLVendor GrGLGetVendor(const GrGLInterface* gl) {
214    const GrGLubyte* v;
215    GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR));
216    return GrGLGetVendorFromString((const char*) v);
217}
218
219GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) {
220    const GrGLubyte* v;
221    GR_GL_CALL_RET(gl, v, GetString(GR_GL_RENDERER));
222    return GrGLGetRendererFromString((const char*) v);
223}
224
225template<> void GrGLGetMatrix<3>(GrGLfloat* dest, const SkMatrix& src) {
226    // Col 0
227    dest[0] = SkScalarToFloat(src[SkMatrix::kMScaleX]);
228    dest[1] = SkScalarToFloat(src[SkMatrix::kMSkewY]);
229    dest[2] = SkScalarToFloat(src[SkMatrix::kMPersp0]);
230
231    // Col 1
232    dest[3] = SkScalarToFloat(src[SkMatrix::kMSkewX]);
233    dest[4] = SkScalarToFloat(src[SkMatrix::kMScaleY]);
234    dest[5] = SkScalarToFloat(src[SkMatrix::kMPersp1]);
235
236    // Col 2
237    dest[6] = SkScalarToFloat(src[SkMatrix::kMTransX]);
238    dest[7] = SkScalarToFloat(src[SkMatrix::kMTransY]);
239    dest[8] = SkScalarToFloat(src[SkMatrix::kMPersp2]);
240}
241
242template<> void GrGLGetMatrix<4>(GrGLfloat* dest, const SkMatrix& src) {
243    // Col 0
244    dest[0]  = SkScalarToFloat(src[SkMatrix::kMScaleX]);
245    dest[1]  = SkScalarToFloat(src[SkMatrix::kMSkewY]);
246    dest[2]  = 0;
247    dest[3]  = SkScalarToFloat(src[SkMatrix::kMPersp0]);
248
249    // Col 1
250    dest[4]  = SkScalarToFloat(src[SkMatrix::kMSkewX]);
251    dest[5]  = SkScalarToFloat(src[SkMatrix::kMScaleY]);
252    dest[6]  = 0;
253    dest[7]  = SkScalarToFloat(src[SkMatrix::kMPersp1]);
254
255    // Col 2
256    dest[8]  = 0;
257    dest[9]  = 0;
258    dest[10] = 1;
259    dest[11] = 0;
260
261    // Col 3
262    dest[12] = SkScalarToFloat(src[SkMatrix::kMTransX]);
263    dest[13] = SkScalarToFloat(src[SkMatrix::kMTransY]);
264    dest[14] = 0;
265    dest[15] = SkScalarToFloat(src[SkMatrix::kMPersp2]);
266}
267
268GrGLenum GrToGLStencilFunc(GrStencilFunc basicFunc) {
269    static const GrGLenum gTable[] = {
270        GR_GL_ALWAYS,           // kAlways_StencilFunc
271        GR_GL_NEVER,            // kNever_StencilFunc
272        GR_GL_GREATER,          // kGreater_StencilFunc
273        GR_GL_GEQUAL,           // kGEqual_StencilFunc
274        GR_GL_LESS,             // kLess_StencilFunc
275        GR_GL_LEQUAL,           // kLEqual_StencilFunc,
276        GR_GL_EQUAL,            // kEqual_StencilFunc,
277        GR_GL_NOTEQUAL,         // kNotEqual_StencilFunc,
278    };
279    GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
280    GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
281    GR_STATIC_ASSERT(1 == kNever_StencilFunc);
282    GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
283    GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
284    GR_STATIC_ASSERT(4 == kLess_StencilFunc);
285    GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
286    GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
287    GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
288    SkASSERT((unsigned) basicFunc < kBasicStencilFuncCount);
289
290    return gTable[basicFunc];
291}
292