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