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