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