1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <system/window.h>
18 
19 #include <sys/types.h>
20 #include <sys/resource.h>
21 #include <sched.h>
22 
23 #define EGL_EGLEXT_PROTOTYPES
24 #include <EGL/egl.h>
25 #include <EGL/eglext.h>
26 #include <GLES/gl.h>
27 #include <GLES/glext.h>
28 #include <GLES2/gl2.h>
29 #include <GLES2/gl2ext.h>
30 
31 #include <string.h>
32 
33 #include "rsdCore.h"
34 #include "rsdGL.h"
35 
36 #include <malloc.h>
37 #include "rsContext.h"
38 #include "rsDevice.h"
39 #include "rsdShaderCache.h"
40 #include "rsdVertexArray.h"
41 #include "rsdFrameBufferObj.h"
42 
43 using android::renderscript::Context;
44 
45 static int32_t gGLContextCount = 0;
46 
checkEglError(const char * op,EGLBoolean returnVal=EGL_TRUE)47 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
48     struct EGLUtils {
49         static const char *strerror(EGLint err) {
50             switch (err){
51                 case EGL_SUCCESS:           return "EGL_SUCCESS";
52                 case EGL_NOT_INITIALIZED:   return "EGL_NOT_INITIALIZED";
53                 case EGL_BAD_ACCESS:        return "EGL_BAD_ACCESS";
54                 case EGL_BAD_ALLOC:         return "EGL_BAD_ALLOC";
55                 case EGL_BAD_ATTRIBUTE:     return "EGL_BAD_ATTRIBUTE";
56                 case EGL_BAD_CONFIG:        return "EGL_BAD_CONFIG";
57                 case EGL_BAD_CONTEXT:       return "EGL_BAD_CONTEXT";
58                 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE";
59                 case EGL_BAD_DISPLAY:       return "EGL_BAD_DISPLAY";
60                 case EGL_BAD_MATCH:         return "EGL_BAD_MATCH";
61                 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP";
62                 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW";
63                 case EGL_BAD_PARAMETER:     return "EGL_BAD_PARAMETER";
64                 case EGL_BAD_SURFACE:       return "EGL_BAD_SURFACE";
65                 case EGL_CONTEXT_LOST:      return "EGL_CONTEXT_LOST";
66                 default: return "UNKNOWN";
67             }
68         }
69     };
70 
71     if (returnVal != EGL_TRUE) {
72         fprintf(stderr, "%s() returned %d\n", op, returnVal);
73     }
74 
75     for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
76             = eglGetError()) {
77         fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
78                 error);
79     }
80 }
81 
printEGLConfiguration(EGLDisplay dpy,EGLConfig config)82 static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
83 
84 #define X(VAL) {VAL, #VAL}
85     struct {EGLint attribute; const char* name;} names[] = {
86     X(EGL_BUFFER_SIZE),
87     X(EGL_ALPHA_SIZE),
88     X(EGL_BLUE_SIZE),
89     X(EGL_GREEN_SIZE),
90     X(EGL_RED_SIZE),
91     X(EGL_DEPTH_SIZE),
92     X(EGL_STENCIL_SIZE),
93     X(EGL_CONFIG_CAVEAT),
94     X(EGL_CONFIG_ID),
95     X(EGL_LEVEL),
96     X(EGL_MAX_PBUFFER_HEIGHT),
97     X(EGL_MAX_PBUFFER_PIXELS),
98     X(EGL_MAX_PBUFFER_WIDTH),
99     X(EGL_NATIVE_RENDERABLE),
100     X(EGL_NATIVE_VISUAL_ID),
101     X(EGL_NATIVE_VISUAL_TYPE),
102     X(EGL_SAMPLES),
103     X(EGL_SAMPLE_BUFFERS),
104     X(EGL_SURFACE_TYPE),
105     X(EGL_TRANSPARENT_TYPE),
106     X(EGL_TRANSPARENT_RED_VALUE),
107     X(EGL_TRANSPARENT_GREEN_VALUE),
108     X(EGL_TRANSPARENT_BLUE_VALUE),
109     X(EGL_BIND_TO_TEXTURE_RGB),
110     X(EGL_BIND_TO_TEXTURE_RGBA),
111     X(EGL_MIN_SWAP_INTERVAL),
112     X(EGL_MAX_SWAP_INTERVAL),
113     X(EGL_LUMINANCE_SIZE),
114     X(EGL_ALPHA_MASK_SIZE),
115     X(EGL_COLOR_BUFFER_TYPE),
116     X(EGL_RENDERABLE_TYPE),
117     X(EGL_CONFORMANT),
118    };
119 #undef X
120 
121     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
122         EGLint value = -1;
123         EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
124         if (returnVal) {
125             ALOGV(" %s: %d (0x%x)", names[j].name, value, value);
126         }
127     }
128 }
129 
DumpDebug(RsdHal * dc)130 static void DumpDebug(RsdHal *dc) {
131     ALOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion);
132     ALOGE(" EGL context %p  surface %p,  Display=%p", dc->gl.egl.context, dc->gl.egl.surface,
133          dc->gl.egl.display);
134     ALOGE(" GL vendor: %s", dc->gl.gl.vendor);
135     ALOGE(" GL renderer: %s", dc->gl.gl.renderer);
136     ALOGE(" GL Version: %s", dc->gl.gl.version);
137     ALOGE(" GL Extensions: %s", dc->gl.gl.extensions);
138     ALOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion);
139 
140     ALOGV("MAX Textures %i, %i  %i", dc->gl.gl.maxVertexTextureUnits,
141          dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits);
142     ALOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs);
143     ALOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors,
144          dc->gl.gl.maxFragmentUniformVectors);
145     ALOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors);
146 }
147 
rsdGLShutdown(const Context * rsc)148 void rsdGLShutdown(const Context *rsc) {
149     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
150 
151     rsdGLSetSurface(rsc, 0, 0, nullptr);
152     dc->gl.shaderCache->cleanupAll();
153     delete dc->gl.shaderCache;
154     delete dc->gl.vertexArrayState;
155 
156     if (dc->gl.egl.context != EGL_NO_CONTEXT) {
157         RSD_CALL_GL(eglMakeCurrent, dc->gl.egl.display,
158                     EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
159         RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surfaceDefault);
160         if (dc->gl.egl.surface != EGL_NO_SURFACE) {
161             RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surface);
162         }
163         RSD_CALL_GL(eglDestroyContext, dc->gl.egl.display, dc->gl.egl.context);
164         checkEglError("eglDestroyContext");
165     }
166 
167     gGLContextCount--;
168     if (!gGLContextCount) {
169         RSD_CALL_GL(eglTerminate, dc->gl.egl.display);
170     }
171 }
172 
getConfigData(const Context * rsc,EGLint * configAttribs,size_t configAttribsLen,uint32_t numSamples)173 void getConfigData(const Context *rsc,
174                    EGLint *configAttribs, size_t configAttribsLen,
175                    uint32_t numSamples) {
176     memset(configAttribs, 0, configAttribsLen*sizeof(*configAttribs));
177 
178     EGLint *configAttribsPtr = configAttribs;
179 
180     configAttribsPtr[0] = EGL_SURFACE_TYPE;
181     configAttribsPtr[1] = EGL_PBUFFER_BIT;
182     configAttribsPtr += 2;
183 
184     configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
185     configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
186     configAttribsPtr += 2;
187 
188     configAttribsPtr[0] = EGL_RED_SIZE;
189     configAttribsPtr[1] = 8;
190     configAttribsPtr += 2;
191 
192     configAttribsPtr[0] = EGL_GREEN_SIZE;
193     configAttribsPtr[1] = 8;
194     configAttribsPtr += 2;
195 
196     configAttribsPtr[0] = EGL_BLUE_SIZE;
197     configAttribsPtr[1] = 8;
198     configAttribsPtr += 2;
199 
200     if (rsc->mUserSurfaceConfig.alphaMin > 0) {
201         configAttribsPtr[0] = EGL_ALPHA_SIZE;
202         configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin;
203         configAttribsPtr += 2;
204     }
205 
206     if (rsc->mUserSurfaceConfig.depthMin > 0) {
207         configAttribsPtr[0] = EGL_DEPTH_SIZE;
208         configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
209         configAttribsPtr += 2;
210     }
211 
212     if (numSamples > 1) {
213         configAttribsPtr[0] = EGL_SAMPLE_BUFFERS;
214         configAttribsPtr[1] = 1;
215         configAttribsPtr[2] = EGL_SAMPLES;
216         configAttribsPtr[3] = numSamples;
217         configAttribsPtr += 4;
218     }
219 
220     configAttribsPtr[0] = EGL_NONE;
221     rsAssert(configAttribsPtr < (configAttribs + configAttribsLen));
222 }
223 
rsdGLInit(const Context * rsc)224 int32_t rsdGLInit(const Context *rsc) {
225     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
226 
227     dc->gl.egl.numConfigs = -1;
228 
229     EGLint configAttribs[128];
230     EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
231 
232     ALOGV("%p initEGL start", rsc);
233     rsc->setWatchdogGL("eglGetDisplay", __LINE__, __FILE__);
234     dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
235     checkEglError("eglGetDisplay");
236 
237     RSD_CALL_GL(eglInitialize, dc->gl.egl.display,
238                 &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
239     checkEglError("eglInitialize");
240 
241     EGLBoolean ret;
242 
243     EGLint numConfigs = -1, n = 0;
244     rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
245 
246     // Try minding a multisample config that matches the user request
247     uint32_t minSample = rsc->mUserSurfaceConfig.samplesMin;
248     uint32_t prefSample = rsc->mUserSurfaceConfig.samplesPref;
249     for (uint32_t sampleCount = prefSample; sampleCount >= minSample; sampleCount--) {
250         getConfigData(rsc, configAttribs, (sizeof(configAttribs) / sizeof(EGLint)), sampleCount);
251         ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
252         checkEglError("eglGetConfigs", ret);
253         if (numConfigs > 0) {
254             break;
255         }
256     }
257 
258     if (numConfigs) {
259         EGLConfig* const configs = new EGLConfig[numConfigs];
260 
261         rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
262         ret = eglChooseConfig(dc->gl.egl.display,
263                 configAttribs, configs, numConfigs, &n);
264         if (!ret || !n) {
265             checkEglError("eglChooseConfig", ret);
266             ALOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
267         }
268 
269         // The first config is guaranteed to over-satisfy the constraints
270         dc->gl.egl.config = configs[0];
271 
272         // go through the list and skip configs that over-satisfy our needs
273         for (int i=0 ; i<n ; i++) {
274             if (rsc->mUserSurfaceConfig.alphaMin <= 0) {
275                 EGLint alphaSize;
276                 eglGetConfigAttrib(dc->gl.egl.display,
277                         configs[i], EGL_ALPHA_SIZE, &alphaSize);
278                 if (alphaSize > 0) {
279                     continue;
280                 }
281             }
282 
283             if (rsc->mUserSurfaceConfig.depthMin <= 0) {
284                 EGLint depthSize;
285                 eglGetConfigAttrib(dc->gl.egl.display,
286                         configs[i], EGL_DEPTH_SIZE, &depthSize);
287                 if (depthSize > 0) {
288                     continue;
289                 }
290             }
291 
292             // Found one!
293             dc->gl.egl.config = configs[i];
294             break;
295         }
296 
297         delete [] configs;
298     }
299 
300     //if (props.mLogVisual) {
301     if (0) {
302         printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
303     }
304     //}
305 
306     rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__);
307     dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config,
308                                           EGL_NO_CONTEXT, context_attribs2);
309     checkEglError("eglCreateContext");
310     if (dc->gl.egl.context == EGL_NO_CONTEXT) {
311         ALOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc);
312         rsc->setWatchdogGL(nullptr, 0, nullptr);
313         return -1;
314     }
315     gGLContextCount++;
316 
317     EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
318     rsc->setWatchdogGL("eglCreatePbufferSurface", __LINE__, __FILE__);
319     dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config,
320             pbuffer_attribs);
321     checkEglError("eglCreatePbufferSurface");
322     if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
323         ALOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE");
324         rsdGLShutdown(rsc);
325         rsc->setWatchdogGL(nullptr, 0, nullptr);
326         return -1;
327     }
328 
329     rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
330     ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
331                          dc->gl.egl.surfaceDefault, dc->gl.egl.context);
332     if (ret == EGL_FALSE) {
333         ALOGE("eglMakeCurrent returned EGL_FALSE");
334         checkEglError("eglMakeCurrent", ret);
335         rsdGLShutdown(rsc);
336         rsc->setWatchdogGL(nullptr, 0, nullptr);
337         return -1;
338     }
339 
340     dc->gl.gl.version = glGetString(GL_VERSION);
341     dc->gl.gl.vendor = glGetString(GL_VENDOR);
342     dc->gl.gl.renderer = glGetString(GL_RENDERER);
343     dc->gl.gl.extensions = glGetString(GL_EXTENSIONS);
344 
345     //ALOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
346     //ALOGV("GL Version %s", mGL.mVersion);
347     //ALOGV("GL Vendor %s", mGL.mVendor);
348     //ALOGV("GL Renderer %s", mGL.mRenderer);
349     //ALOGV("GL Extensions %s", mGL.mExtensions);
350 
351     const char *verptr = nullptr;
352     if (strlen((const char *)dc->gl.gl.version) > 9) {
353         if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) {
354             verptr = (const char *)dc->gl.gl.version + 12;
355         }
356         if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) {
357             verptr = (const char *)dc->gl.gl.version + 9;
358         }
359     }
360 
361     if (!verptr) {
362         ALOGE("Error, OpenGL ES Lite not supported");
363         rsdGLShutdown(rsc);
364         rsc->setWatchdogGL(nullptr, 0, nullptr);
365         return -1;
366     } else {
367         sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion);
368     }
369 
370     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs);
371     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors);
372     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits);
373 
374     glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors);
375     glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits);
376 
377     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits);
378     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors);
379 
380     dc->gl.gl.OES_texture_npot = nullptr != strstr((const char *)dc->gl.gl.extensions,
381                                                 "GL_OES_texture_npot");
382     dc->gl.gl.IMG_texture_npot = nullptr != strstr((const char *)dc->gl.gl.extensions,
383                                                    "GL_IMG_texture_npot");
384     dc->gl.gl.NV_texture_npot_2D_mipmap = nullptr != strstr((const char *)dc->gl.gl.extensions,
385                                                             "GL_NV_texture_npot_2D_mipmap");
386     dc->gl.gl.EXT_texture_max_aniso = 1.0f;
387     bool hasAniso = nullptr != strstr((const char *)dc->gl.gl.extensions,
388                                    "GL_EXT_texture_filter_anisotropic");
389     if (hasAniso) {
390         glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso);
391     }
392 
393     if (0) {
394         DumpDebug(dc);
395     }
396 
397     dc->gl.shaderCache = new RsdShaderCache();
398     dc->gl.vertexArrayState = new RsdVertexArrayState();
399     dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
400     dc->gl.currentFrameBuffer = nullptr;
401     dc->mHasGraphics = true;
402 
403     int syncFd = -1;
404     // Create a EGL sync object.
405     EGLSyncKHR sync = eglCreateSyncKHR(dc->gl.egl.display, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
406     if (sync != EGL_NO_SYNC_KHR) {
407         // native fence fd will not be populated until flush() is done.
408         glFlush();
409         // Convert the EGL sync object to a file descriptor.
410         syncFd = eglDupNativeFenceFDANDROID(dc->gl.egl.display, sync);
411         if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
412             ALOGW("Failed to dup sync khr object");
413             syncFd = -1;
414         }
415         // The sync object is no longer needed once we have the file descriptor.
416         eglDestroySyncKHR(dc->gl.egl.display, sync);
417     }
418 
419     ALOGV("%p initGLThread end", rsc);
420     rsc->setWatchdogGL(nullptr, 0, nullptr);
421     return syncFd;
422 }
423 
424 
rsdGLSetInternalSurface(const Context * rsc,RsNativeWindow sur)425 bool rsdGLSetInternalSurface(const Context *rsc, RsNativeWindow sur) {
426     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
427 
428     EGLBoolean ret;
429     if (dc->gl.egl.surface != nullptr) {
430         rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
431         ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
432                              dc->gl.egl.surfaceDefault, dc->gl.egl.context);
433         checkEglError("eglMakeCurrent", ret);
434 
435         rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__);
436         ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
437         checkEglError("eglDestroySurface", ret);
438 
439         dc->gl.egl.surface = nullptr;
440     }
441 
442     if (dc->gl.currentWndSurface != nullptr) {
443         dc->gl.currentWndSurface->decStrong(nullptr);
444     }
445 
446     dc->gl.currentWndSurface = (ANativeWindow *)sur;
447     if (dc->gl.currentWndSurface != nullptr) {
448         dc->gl.currentWndSurface->incStrong(nullptr);
449 
450         rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__);
451         dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
452                                                     dc->gl.currentWndSurface, nullptr);
453         checkEglError("eglCreateWindowSurface");
454         if (dc->gl.egl.surface == EGL_NO_SURFACE) {
455             ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
456         }
457 
458         rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
459         ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface,
460                              dc->gl.egl.surface, dc->gl.egl.context);
461         checkEglError("eglMakeCurrent", ret);
462     }
463     rsc->setWatchdogGL(nullptr, 0, nullptr);
464     return true;
465 }
466 
rsdGLSetSurface(const Context * rsc,uint32_t w,uint32_t h,RsNativeWindow sur)467 bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
468     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
469 
470     if (dc->gl.wndSurface != nullptr) {
471         dc->gl.wndSurface->decStrong(nullptr);
472         dc->gl.wndSurface = nullptr;
473     }
474     if(w && h) {
475         // WAR: Some drivers fail to handle 0 size surfaces correctly. Use the
476         // pbuffer to avoid this pitfall.
477         dc->gl.wndSurface = (ANativeWindow *)sur;
478         if (dc->gl.wndSurface != nullptr) {
479             dc->gl.wndSurface->incStrong(nullptr);
480         }
481     }
482 
483     return rsdGLSetInternalSurface(rsc, sur);
484 }
485 
rsdGLSwap(const android::renderscript::Context * rsc)486 void rsdGLSwap(const android::renderscript::Context *rsc) {
487     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
488     RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
489 }
490 
rsdGLSetPriority(const Context * rsc,int32_t priority)491 void rsdGLSetPriority(const Context *rsc, int32_t priority) {
492     if (priority > 0) {
493         // Mark context as low priority.
494         ALOGV("low pri");
495     } else {
496         ALOGV("normal pri");
497     }
498 }
499 
rsdGLCheckError(const android::renderscript::Context * rsc,const char * msg,bool isFatal)500 void rsdGLCheckError(const android::renderscript::Context *rsc,
501                      const char *msg, bool isFatal) {
502     GLenum err = glGetError();
503     if (err != GL_NO_ERROR) {
504         char buf[1024];
505         snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg);
506 
507         if (isFatal) {
508             rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
509         } else {
510             switch (err) {
511             case GL_OUT_OF_MEMORY:
512                 rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf);
513                 break;
514             default:
515                 rsc->setError(RS_ERROR_DRIVER, buf);
516                 break;
517             }
518         }
519 
520         ALOGE("%p, %s", rsc, buf);
521     }
522 
523 }
524 
rsdGLClearColor(const android::renderscript::Context * rsc,float r,float g,float b,float a)525 void rsdGLClearColor(const android::renderscript::Context *rsc,
526                      float r, float g, float b, float a) {
527     RSD_CALL_GL(glClearColor, r, g, b, a);
528     RSD_CALL_GL(glClear, GL_COLOR_BUFFER_BIT);
529 }
530 
rsdGLClearDepth(const android::renderscript::Context * rsc,float v)531 void rsdGLClearDepth(const android::renderscript::Context *rsc, float v) {
532     RSD_CALL_GL(glClearDepthf, v);
533     RSD_CALL_GL(glClear, GL_DEPTH_BUFFER_BIT);
534 }
535 
rsdGLFinish(const android::renderscript::Context * rsc)536 void rsdGLFinish(const android::renderscript::Context *rsc) {
537     RSD_CALL_GL(glFinish);
538 }
539 
rsdGLDrawQuadTexCoords(const android::renderscript::Context * rsc,float x1,float y1,float z1,float u1,float v1,float x2,float y2,float z2,float u2,float v2,float x3,float y3,float z3,float u3,float v3,float x4,float y4,float z4,float u4,float v4)540 void rsdGLDrawQuadTexCoords(const android::renderscript::Context *rsc,
541                             float x1, float y1, float z1, float u1, float v1,
542                             float x2, float y2, float z2, float u2, float v2,
543                             float x3, float y3, float z3, float u3, float v3,
544                             float x4, float y4, float z4, float u4, float v4) {
545 
546     float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
547     const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
548 
549     RsdVertexArray::Attrib attribs[2];
550 
551     attribs[0].set(GL_FLOAT, 3, 12, false, (size_t)vtx, "ATTRIB_position");
552     attribs[1].set(GL_FLOAT, 2, 8, false, (size_t)tex, "ATTRIB_texture0");
553 
554     RsdVertexArray va(attribs, 2);
555     va.setup(rsc);
556 
557     RSD_CALL_GL(glDrawArrays, GL_TRIANGLE_FAN, 0, 4);
558 }
559