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 (NULL != location) {
44            GrPrintf(" at\n\t%s", location);
45        }
46        if (NULL != call) {
47            GrPrintf("\n\t\t%s", call);
48        }
49        GrPrintf("\n");
50    }
51}
52
53namespace {
54// Mesa uses a non-standard version string of format: 1.4 Mesa <mesa_major>.<mesa_minor>.
55// The mapping of from mesa version to GL version came from here: http://www.mesa3d.org/intro.html
56bool get_gl_version_for_mesa(int mesaMajorVersion, int* major, int* minor) {
57    switch (mesaMajorVersion) {
58        case 2:
59        case 3:
60        case 4:
61        case 5:
62        case 6:
63            *major = 1;
64            *minor = mesaMajorVersion - 1;
65            return true;
66        case 7:
67            *major = 2;
68            *minor = 1;
69            return true;
70        case 8:
71            *major = 3;
72            *minor = 0;
73            return true;
74        case 9:
75            *major = 3;
76            *minor = 1;
77            return true;
78        case 10:
79            *major = 3;
80            *minor = 3;
81            return true;
82        default:
83            return false;
84    }
85}
86}
87
88///////////////////////////////////////////////////////////////////////////////
89
90#if GR_GL_LOG_CALLS
91    bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
92#endif
93
94#if GR_GL_CHECK_ERROR
95    bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);
96#endif
97
98///////////////////////////////////////////////////////////////////////////////
99
100GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) {
101    if (NULL == versionString) {
102        SkDebugf("NULL GL version string.");
103        return kNone_GrGLStandard;
104    }
105
106    int major, minor;
107
108    // check for desktop
109    int n = sscanf(versionString, "%d.%d", &major, &minor);
110    if (2 == n) {
111        return kGL_GrGLStandard;
112    }
113
114    // check for ES 1
115    char profile[2];
116    n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, &major, &minor);
117    if (4 == n) {
118        // we no longer support ES1.
119        return kNone_GrGLStandard;
120    }
121
122    // check for ES2
123    n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
124    if (2 == n) {
125        return kGLES_GrGLStandard;
126    }
127    return kNone_GrGLStandard;
128}
129
130bool GrGLIsMesaFromVersionString(const char* versionString) {
131    int major, minor, mesaMajor, mesaMinor;
132    int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
133    return 4 == n;
134}
135
136bool GrGLIsChromiumFromRendererString(const char* rendererString) {
137    return 0 == strcmp(rendererString, "Chromium");
138}
139
140GrGLVersion GrGLGetVersionFromString(const char* versionString) {
141    if (NULL == versionString) {
142        SkDebugf("NULL GL version string.");
143        return GR_GL_INVALID_VER;
144    }
145
146    int major, minor;
147
148    // check for mesa
149    int mesaMajor, mesaMinor;
150    int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
151    if (4 == n) {
152        if (get_gl_version_for_mesa(mesaMajor, &major, &minor)) {
153            return GR_GL_VER(major, minor);
154        } else {
155            return GR_GL_INVALID_VER;
156        }
157    }
158
159    n = sscanf(versionString, "%d.%d", &major, &minor);
160    if (2 == n) {
161        return GR_GL_VER(major, minor);
162    }
163
164    char profile[2];
165    n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
166               &major, &minor);
167    if (4 == n) {
168        return GR_GL_VER(major, minor);
169    }
170
171    n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
172    if (2 == n) {
173        return GR_GL_VER(major, minor);
174    }
175
176    return GR_GL_INVALID_VER;
177}
178
179GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
180    if (NULL == versionString) {
181        SkDebugf("NULL GLSL version string.");
182        return GR_GLSL_INVALID_VER;
183    }
184
185    int major, minor;
186
187    int n = sscanf(versionString, "%d.%d", &major, &minor);
188    if (2 == n) {
189        return GR_GLSL_VER(major, minor);
190    }
191
192    n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
193    if (2 == n) {
194        return GR_GLSL_VER(major, minor);
195    }
196
197#ifdef SK_BUILD_FOR_ANDROID
198    // android hack until the gpu vender updates their drivers
199    n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
200    if (2 == n) {
201        return GR_GLSL_VER(major, minor);
202    }
203#endif
204
205    return GR_GLSL_INVALID_VER;
206}
207
208GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
209    if (NULL != vendorString) {
210        if (0 == strcmp(vendorString, "ARM")) {
211            return kARM_GrGLVendor;
212        }
213        if (0 == strcmp(vendorString, "Imagination Technologies")) {
214            return kImagination_GrGLVendor;
215        }
216        if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
217            return kIntel_GrGLVendor;
218        }
219        if (0 == strcmp(vendorString, "Qualcomm")) {
220            return kQualcomm_GrGLVendor;
221        }
222    }
223    return kOther_GrGLVendor;
224}
225
226GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
227    if (NULL != rendererString) {
228        if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) {
229            return kTegra3_GrGLRenderer;
230        } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
231            return kTegra2_GrGLRenderer;
232        }
233    }
234    return kOther_GrGLRenderer;
235}
236
237GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
238    const GrGLubyte* v;
239    GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
240    return GrGLGetVersionFromString((const char*) v);
241}
242
243GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
244    const GrGLubyte* v;
245    GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
246    return GrGLGetGLSLVersionFromString((const char*) v);
247}
248
249GrGLVendor GrGLGetVendor(const GrGLInterface* gl) {
250    const GrGLubyte* v;
251    GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR));
252    return GrGLGetVendorFromString((const char*) v);
253}
254
255GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) {
256    const GrGLubyte* v;
257    GR_GL_CALL_RET(gl, v, GetString(GR_GL_RENDERER));
258    return GrGLGetRendererFromString((const char*) v);
259}
260
261template<> void GrGLGetMatrix<3>(GrGLfloat* dest, const SkMatrix& src) {
262    // Col 0
263    dest[0] = SkScalarToFloat(src[SkMatrix::kMScaleX]);
264    dest[1] = SkScalarToFloat(src[SkMatrix::kMSkewY]);
265    dest[2] = SkScalarToFloat(src[SkMatrix::kMPersp0]);
266
267    // Col 1
268    dest[3] = SkScalarToFloat(src[SkMatrix::kMSkewX]);
269    dest[4] = SkScalarToFloat(src[SkMatrix::kMScaleY]);
270    dest[5] = SkScalarToFloat(src[SkMatrix::kMPersp1]);
271
272    // Col 2
273    dest[6] = SkScalarToFloat(src[SkMatrix::kMTransX]);
274    dest[7] = SkScalarToFloat(src[SkMatrix::kMTransY]);
275    dest[8] = SkScalarToFloat(src[SkMatrix::kMPersp2]);
276}
277
278template<> void GrGLGetMatrix<4>(GrGLfloat* dest, const SkMatrix& src) {
279    // Col 0
280    dest[0]  = SkScalarToFloat(src[SkMatrix::kMScaleX]);
281    dest[1]  = SkScalarToFloat(src[SkMatrix::kMSkewY]);
282    dest[2]  = 0;
283    dest[3]  = SkScalarToFloat(src[SkMatrix::kMPersp0]);
284
285    // Col 1
286    dest[4]  = SkScalarToFloat(src[SkMatrix::kMSkewX]);
287    dest[5]  = SkScalarToFloat(src[SkMatrix::kMScaleY]);
288    dest[6]  = 0;
289    dest[7]  = SkScalarToFloat(src[SkMatrix::kMPersp1]);
290
291    // Col 2
292    dest[8]  = 0;
293    dest[9]  = 0;
294    dest[10] = 1;
295    dest[11] = 0;
296
297    // Col 3
298    dest[12] = SkScalarToFloat(src[SkMatrix::kMTransX]);
299    dest[13] = SkScalarToFloat(src[SkMatrix::kMTransY]);
300    dest[14] = 0;
301    dest[15] = SkScalarToFloat(src[SkMatrix::kMPersp2]);
302}
303