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 
GrGLClearErr(const GrGLInterface * gl)13 void GrGLClearErr(const GrGLInterface* gl) {
14     while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {}
15 }
16 
17 namespace {
get_error_string(uint32_t err)18 const 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 
GrGLCheckErr(const GrGLInterface * gl,const char * location,const char * call)37 void 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         SkDebugf("---- glGetError 0x%x(%s)", err, get_error_string(err));
43         if (location) {
44             SkDebugf(" at\n\t%s", location);
45         }
46         if (call) {
47             SkDebugf("\n\t\t%s", call);
48         }
49         SkDebugf("\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 
GrGLGetStandardInUseFromString(const char * versionString)65 GrGLStandard 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 
GrGLIsMesaFromVersionString(const char * versionString)95 bool GrGLIsMesaFromVersionString(const char* versionString) {
96     int major, minor, mesaMajor, mesaMinor;
97 
98     GrGLStandard standard = GrGLGetStandardInUseFromString(versionString);
99 
100     if (standard == kGL_GrGLStandard) {
101         int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
102         return 4 == n;
103     }
104     else {
105         int n = sscanf(versionString, "OpenGL ES %d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
106         return 4 == n;
107     }
108     return false;
109 }
110 
GrGLIsChromiumFromRendererString(const char * rendererString)111 bool GrGLIsChromiumFromRendererString(const char* rendererString) {
112     return 0 == strcmp(rendererString, "Chromium");
113 }
114 
GrGLGetVersionFromString(const char * versionString)115 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
116     if (NULL == versionString) {
117         SkDebugf("NULL GL version string.");
118         return GR_GL_INVALID_VER;
119     }
120 
121     int major, minor;
122 
123     // check for mesa
124     int mesaMajor, mesaMinor;
125     int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
126     if (4 == n) {
127         return GR_GL_VER(major, minor);
128     }
129 
130     n = sscanf(versionString, "%d.%d", &major, &minor);
131     if (2 == n) {
132         return GR_GL_VER(major, minor);
133     }
134 
135     char profile[2];
136     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
137                &major, &minor);
138     if (4 == n) {
139         return GR_GL_VER(major, minor);
140     }
141 
142     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
143     if (2 == n) {
144         return GR_GL_VER(major, minor);
145     }
146 
147     return GR_GL_INVALID_VER;
148 }
149 
GrGLGetGLSLVersionFromString(const char * versionString)150 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
151     if (NULL == versionString) {
152         SkDebugf("NULL GLSL version string.");
153         return GR_GLSL_INVALID_VER;
154     }
155 
156     int major, minor;
157 
158     int n = sscanf(versionString, "%d.%d", &major, &minor);
159     if (2 == n) {
160         return GR_GLSL_VER(major, minor);
161     }
162 
163     n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
164     if (2 == n) {
165         return GR_GLSL_VER(major, minor);
166     }
167 
168 #ifdef SK_BUILD_FOR_ANDROID
169     // android hack until the gpu vender updates their drivers
170     n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
171     if (2 == n) {
172         return GR_GLSL_VER(major, minor);
173     }
174 #endif
175 
176     return GR_GLSL_INVALID_VER;
177 }
178 
GrGLGetVendorFromString(const char * vendorString)179 GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
180     if (vendorString) {
181         if (0 == strcmp(vendorString, "ARM")) {
182             return kARM_GrGLVendor;
183         }
184         if (0 == strcmp(vendorString, "Imagination Technologies")) {
185             return kImagination_GrGLVendor;
186         }
187         if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
188             return kIntel_GrGLVendor;
189         }
190         if (0 == strcmp(vendorString, "Qualcomm")) {
191             return kQualcomm_GrGLVendor;
192         }
193         if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
194             return kNVIDIA_GrGLVendor;
195         }
196     }
197     return kOther_GrGLVendor;
198 }
199 
GrGLGetRendererFromString(const char * rendererString)200 GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
201     if (rendererString) {
202         if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) {
203             return kTegra3_GrGLRenderer;
204         } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
205             return kTegra2_GrGLRenderer;
206         }
207         int lastDigit;
208         int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
209         if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
210             return kPowerVR54x_GrGLRenderer;
211         }
212         static const char kPowerVRRogueStr[] = "PowerVR Rogue";
213         if (0 == strncmp(rendererString, kPowerVRRogueStr,
214                          SK_ARRAY_COUNT(kPowerVRRogueStr)-1)) {
215             return kPowerVRRogue_GrGLRenderer;
216         }
217         int adrenoNumber;
218         n = sscanf(rendererString, "Adreno (TM) %d", &adrenoNumber);
219         if (1 == n) {
220             if (adrenoNumber >= 300) {
221                 if (adrenoNumber < 400) {
222                     return kAdreno3xx_GrGLRenderer;
223                 }
224                 if (adrenoNumber < 500) {
225                     return kAdreno4xx_GrGLRenderer;
226                 }
227             }
228         }
229     }
230     return kOther_GrGLRenderer;
231 }
232 
GrGLGetVersion(const GrGLInterface * gl)233 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
234     const GrGLubyte* v;
235     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
236     return GrGLGetVersionFromString((const char*) v);
237 }
238 
GrGLGetGLSLVersion(const GrGLInterface * gl)239 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
240     const GrGLubyte* v;
241     GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
242     return GrGLGetGLSLVersionFromString((const char*) v);
243 }
244 
GrGLGetVendor(const GrGLInterface * gl)245 GrGLVendor GrGLGetVendor(const GrGLInterface* gl) {
246     const GrGLubyte* v;
247     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR));
248     return GrGLGetVendorFromString((const char*) v);
249 }
250 
GrGLGetRenderer(const GrGLInterface * gl)251 GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) {
252     const GrGLubyte* v;
253     GR_GL_CALL_RET(gl, v, GetString(GR_GL_RENDERER));
254     return GrGLGetRendererFromString((const char*) v);
255 }
256 
GrGLGetMatrix(GrGLfloat * dest,const SkMatrix & src)257 template<> void GrGLGetMatrix<3>(GrGLfloat* dest, const SkMatrix& src) {
258     // Col 0
259     dest[0] = SkScalarToFloat(src[SkMatrix::kMScaleX]);
260     dest[1] = SkScalarToFloat(src[SkMatrix::kMSkewY]);
261     dest[2] = SkScalarToFloat(src[SkMatrix::kMPersp0]);
262 
263     // Col 1
264     dest[3] = SkScalarToFloat(src[SkMatrix::kMSkewX]);
265     dest[4] = SkScalarToFloat(src[SkMatrix::kMScaleY]);
266     dest[5] = SkScalarToFloat(src[SkMatrix::kMPersp1]);
267 
268     // Col 2
269     dest[6] = SkScalarToFloat(src[SkMatrix::kMTransX]);
270     dest[7] = SkScalarToFloat(src[SkMatrix::kMTransY]);
271     dest[8] = SkScalarToFloat(src[SkMatrix::kMPersp2]);
272 }
273 
GrGLGetMatrix(GrGLfloat * dest,const SkMatrix & src)274 template<> void GrGLGetMatrix<4>(GrGLfloat* dest, const SkMatrix& src) {
275     // Col 0
276     dest[0]  = SkScalarToFloat(src[SkMatrix::kMScaleX]);
277     dest[1]  = SkScalarToFloat(src[SkMatrix::kMSkewY]);
278     dest[2]  = 0;
279     dest[3]  = SkScalarToFloat(src[SkMatrix::kMPersp0]);
280 
281     // Col 1
282     dest[4]  = SkScalarToFloat(src[SkMatrix::kMSkewX]);
283     dest[5]  = SkScalarToFloat(src[SkMatrix::kMScaleY]);
284     dest[6]  = 0;
285     dest[7]  = SkScalarToFloat(src[SkMatrix::kMPersp1]);
286 
287     // Col 2
288     dest[8]  = 0;
289     dest[9]  = 0;
290     dest[10] = 1;
291     dest[11] = 0;
292 
293     // Col 3
294     dest[12] = SkScalarToFloat(src[SkMatrix::kMTransX]);
295     dest[13] = SkScalarToFloat(src[SkMatrix::kMTransY]);
296     dest[14] = 0;
297     dest[15] = SkScalarToFloat(src[SkMatrix::kMPersp2]);
298 }
299 
GrToGLStencilFunc(GrStencilFunc basicFunc)300 GrGLenum GrToGLStencilFunc(GrStencilFunc basicFunc) {
301     static const GrGLenum gTable[] = {
302         GR_GL_ALWAYS,           // kAlways_StencilFunc
303         GR_GL_NEVER,            // kNever_StencilFunc
304         GR_GL_GREATER,          // kGreater_StencilFunc
305         GR_GL_GEQUAL,           // kGEqual_StencilFunc
306         GR_GL_LESS,             // kLess_StencilFunc
307         GR_GL_LEQUAL,           // kLEqual_StencilFunc,
308         GR_GL_EQUAL,            // kEqual_StencilFunc,
309         GR_GL_NOTEQUAL,         // kNotEqual_StencilFunc,
310     };
311     GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
312     GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
313     GR_STATIC_ASSERT(1 == kNever_StencilFunc);
314     GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
315     GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
316     GR_STATIC_ASSERT(4 == kLess_StencilFunc);
317     GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
318     GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
319     GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
320     SkASSERT((unsigned) basicFunc < kBasicStencilFuncCount);
321 
322     return gTable[basicFunc];
323 }
324