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 <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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    536 void rsdGLFinish(const android::renderscript::Context *rsc) {
    537     RSD_CALL_GL(glFinish);
    538 }
    539 
    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