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 #include <ui/EGLUtils.h>
     20 #include <ui/egl/android_natives.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 "rsdShaderCache.h"
     41 #include "rsdVertexArray.h"
     42 #include "rsdFrameBufferObj.h"
     43 
     44 using namespace android;
     45 using namespace android::renderscript;
     46 
     47 static int32_t gGLContextCount = 0;
     48 
     49 static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
     50     if (returnVal != EGL_TRUE) {
     51         fprintf(stderr, "%s() returned %d\n", op, returnVal);
     52     }
     53 
     54     for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
     55             = eglGetError()) {
     56         fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
     57                 error);
     58     }
     59 }
     60 
     61 static void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
     62 
     63 #define X(VAL) {VAL, #VAL}
     64     struct {EGLint attribute; const char* name;} names[] = {
     65     X(EGL_BUFFER_SIZE),
     66     X(EGL_ALPHA_SIZE),
     67     X(EGL_BLUE_SIZE),
     68     X(EGL_GREEN_SIZE),
     69     X(EGL_RED_SIZE),
     70     X(EGL_DEPTH_SIZE),
     71     X(EGL_STENCIL_SIZE),
     72     X(EGL_CONFIG_CAVEAT),
     73     X(EGL_CONFIG_ID),
     74     X(EGL_LEVEL),
     75     X(EGL_MAX_PBUFFER_HEIGHT),
     76     X(EGL_MAX_PBUFFER_PIXELS),
     77     X(EGL_MAX_PBUFFER_WIDTH),
     78     X(EGL_NATIVE_RENDERABLE),
     79     X(EGL_NATIVE_VISUAL_ID),
     80     X(EGL_NATIVE_VISUAL_TYPE),
     81     X(EGL_SAMPLES),
     82     X(EGL_SAMPLE_BUFFERS),
     83     X(EGL_SURFACE_TYPE),
     84     X(EGL_TRANSPARENT_TYPE),
     85     X(EGL_TRANSPARENT_RED_VALUE),
     86     X(EGL_TRANSPARENT_GREEN_VALUE),
     87     X(EGL_TRANSPARENT_BLUE_VALUE),
     88     X(EGL_BIND_TO_TEXTURE_RGB),
     89     X(EGL_BIND_TO_TEXTURE_RGBA),
     90     X(EGL_MIN_SWAP_INTERVAL),
     91     X(EGL_MAX_SWAP_INTERVAL),
     92     X(EGL_LUMINANCE_SIZE),
     93     X(EGL_ALPHA_MASK_SIZE),
     94     X(EGL_COLOR_BUFFER_TYPE),
     95     X(EGL_RENDERABLE_TYPE),
     96     X(EGL_CONFORMANT),
     97    };
     98 #undef X
     99 
    100     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
    101         EGLint value = -1;
    102         EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
    103         if (returnVal) {
    104             LOGV(" %s: %d (0x%x)", names[j].name, value, value);
    105         }
    106     }
    107 }
    108 
    109 static void DumpDebug(RsdHal *dc) {
    110     LOGE(" EGL ver %i %i", dc->gl.egl.majorVersion, dc->gl.egl.minorVersion);
    111     LOGE(" EGL context %p  surface %p,  Display=%p", dc->gl.egl.context, dc->gl.egl.surface,
    112          dc->gl.egl.display);
    113     LOGE(" GL vendor: %s", dc->gl.gl.vendor);
    114     LOGE(" GL renderer: %s", dc->gl.gl.renderer);
    115     LOGE(" GL Version: %s", dc->gl.gl.version);
    116     LOGE(" GL Extensions: %s", dc->gl.gl.extensions);
    117     LOGE(" GL int Versions %i %i", dc->gl.gl.majorVersion, dc->gl.gl.minorVersion);
    118 
    119     LOGV("MAX Textures %i, %i  %i", dc->gl.gl.maxVertexTextureUnits,
    120          dc->gl.gl.maxFragmentTextureImageUnits, dc->gl.gl.maxTextureImageUnits);
    121     LOGV("MAX Attribs %i", dc->gl.gl.maxVertexAttribs);
    122     LOGV("MAX Uniforms %i, %i", dc->gl.gl.maxVertexUniformVectors,
    123          dc->gl.gl.maxFragmentUniformVectors);
    124     LOGV("MAX Varyings %i", dc->gl.gl.maxVaryingVectors);
    125 }
    126 
    127 void rsdGLShutdown(const Context *rsc) {
    128     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    129 
    130     dc->gl.shaderCache->cleanupAll();
    131     delete dc->gl.shaderCache;
    132     delete dc->gl.vertexArrayState;
    133 
    134     if (dc->gl.egl.context != EGL_NO_CONTEXT) {
    135         RSD_CALL_GL(eglMakeCurrent, dc->gl.egl.display,
    136                     EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    137         RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surfaceDefault);
    138         if (dc->gl.egl.surface != EGL_NO_SURFACE) {
    139             RSD_CALL_GL(eglDestroySurface, dc->gl.egl.display, dc->gl.egl.surface);
    140         }
    141         RSD_CALL_GL(eglDestroyContext, dc->gl.egl.display, dc->gl.egl.context);
    142         checkEglError("eglDestroyContext");
    143     }
    144 
    145     gGLContextCount--;
    146     if (!gGLContextCount) {
    147         RSD_CALL_GL(eglTerminate, dc->gl.egl.display);
    148     }
    149 }
    150 
    151 bool rsdGLInit(const Context *rsc) {
    152     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    153 
    154     dc->gl.egl.numConfigs = -1;
    155     EGLint configAttribs[128];
    156     EGLint *configAttribsPtr = configAttribs;
    157     EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
    158 
    159     memset(configAttribs, 0, sizeof(configAttribs));
    160 
    161     configAttribsPtr[0] = EGL_SURFACE_TYPE;
    162     configAttribsPtr[1] = EGL_WINDOW_BIT;
    163     configAttribsPtr += 2;
    164 
    165     configAttribsPtr[0] = EGL_RENDERABLE_TYPE;
    166     configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
    167     configAttribsPtr += 2;
    168 
    169     configAttribsPtr[0] = EGL_RED_SIZE;
    170     configAttribsPtr[1] = 8;
    171     configAttribsPtr += 2;
    172 
    173     configAttribsPtr[0] = EGL_GREEN_SIZE;
    174     configAttribsPtr[1] = 8;
    175     configAttribsPtr += 2;
    176 
    177     configAttribsPtr[0] = EGL_BLUE_SIZE;
    178     configAttribsPtr[1] = 8;
    179     configAttribsPtr += 2;
    180 
    181     if (rsc->mUserSurfaceConfig.alphaMin > 0) {
    182         configAttribsPtr[0] = EGL_ALPHA_SIZE;
    183         configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin;
    184         configAttribsPtr += 2;
    185     }
    186 
    187     if (rsc->mUserSurfaceConfig.depthMin > 0) {
    188         configAttribsPtr[0] = EGL_DEPTH_SIZE;
    189         configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
    190         configAttribsPtr += 2;
    191     }
    192 
    193     if (rsc->mDev->mForceSW) {
    194         configAttribsPtr[0] = EGL_CONFIG_CAVEAT;
    195         configAttribsPtr[1] = EGL_SLOW_CONFIG;
    196         configAttribsPtr += 2;
    197     }
    198 
    199     configAttribsPtr[0] = EGL_NONE;
    200     rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
    201 
    202     LOGV("%p initEGL start", rsc);
    203     rsc->setWatchdogGL("eglGetDisplay", __LINE__, __FILE__);
    204     dc->gl.egl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    205     checkEglError("eglGetDisplay");
    206 
    207     RSD_CALL_GL(eglInitialize, dc->gl.egl.display,
    208                 &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
    209     checkEglError("eglInitialize");
    210 
    211     EGLBoolean ret;
    212 
    213     EGLint numConfigs = -1, n = 0;
    214     rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
    215     ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
    216     checkEglError("eglGetConfigs", ret);
    217 
    218     if (numConfigs) {
    219         EGLConfig* const configs = new EGLConfig[numConfigs];
    220 
    221         rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
    222         ret = eglChooseConfig(dc->gl.egl.display,
    223                 configAttribs, configs, numConfigs, &n);
    224         if (!ret || !n) {
    225             checkEglError("eglChooseConfig", ret);
    226             LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
    227         }
    228 
    229         // The first config is guaranteed to over-satisfy the constraints
    230         dc->gl.egl.config = configs[0];
    231 
    232         // go through the list and skip configs that over-satisfy our needs
    233         for (int i=0 ; i<n ; i++) {
    234             if (rsc->mUserSurfaceConfig.alphaMin <= 0) {
    235                 EGLint alphaSize;
    236                 eglGetConfigAttrib(dc->gl.egl.display,
    237                         configs[i], EGL_ALPHA_SIZE, &alphaSize);
    238                 if (alphaSize > 0) {
    239                     continue;
    240                 }
    241             }
    242 
    243             if (rsc->mUserSurfaceConfig.depthMin <= 0) {
    244                 EGLint depthSize;
    245                 eglGetConfigAttrib(dc->gl.egl.display,
    246                         configs[i], EGL_DEPTH_SIZE, &depthSize);
    247                 if (depthSize > 0) {
    248                     continue;
    249                 }
    250             }
    251 
    252             // Found one!
    253             dc->gl.egl.config = configs[i];
    254             break;
    255         }
    256 
    257         delete [] configs;
    258     }
    259 
    260     //if (props.mLogVisual) {
    261     if (0) {
    262         printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
    263     }
    264     //}
    265 
    266     rsc->setWatchdogGL("eglCreateContext", __LINE__, __FILE__);
    267     dc->gl.egl.context = eglCreateContext(dc->gl.egl.display, dc->gl.egl.config,
    268                                           EGL_NO_CONTEXT, context_attribs2);
    269     checkEglError("eglCreateContext");
    270     if (dc->gl.egl.context == EGL_NO_CONTEXT) {
    271         LOGE("%p, eglCreateContext returned EGL_NO_CONTEXT", rsc);
    272         rsc->setWatchdogGL(NULL, 0, NULL);
    273         return false;
    274     }
    275     gGLContextCount++;
    276 
    277 
    278     EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
    279     rsc->setWatchdogGL("eglCreatePbufferSurface", __LINE__, __FILE__);
    280     dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config,
    281                                                         pbuffer_attribs);
    282     checkEglError("eglCreatePbufferSurface");
    283     if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
    284         LOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE");
    285         rsdGLShutdown(rsc);
    286         rsc->setWatchdogGL(NULL, 0, NULL);
    287         return false;
    288     }
    289 
    290     rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
    291     ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
    292                          dc->gl.egl.surfaceDefault, dc->gl.egl.context);
    293     if (ret == EGL_FALSE) {
    294         LOGE("eglMakeCurrent returned EGL_FALSE");
    295         checkEglError("eglMakeCurrent", ret);
    296         rsdGLShutdown(rsc);
    297         rsc->setWatchdogGL(NULL, 0, NULL);
    298         return false;
    299     }
    300 
    301     dc->gl.gl.version = glGetString(GL_VERSION);
    302     dc->gl.gl.vendor = glGetString(GL_VENDOR);
    303     dc->gl.gl.renderer = glGetString(GL_RENDERER);
    304     dc->gl.gl.extensions = glGetString(GL_EXTENSIONS);
    305 
    306     //LOGV("EGL Version %i %i", mEGL.mMajorVersion, mEGL.mMinorVersion);
    307     //LOGV("GL Version %s", mGL.mVersion);
    308     //LOGV("GL Vendor %s", mGL.mVendor);
    309     //LOGV("GL Renderer %s", mGL.mRenderer);
    310     //LOGV("GL Extensions %s", mGL.mExtensions);
    311 
    312     const char *verptr = NULL;
    313     if (strlen((const char *)dc->gl.gl.version) > 9) {
    314         if (!memcmp(dc->gl.gl.version, "OpenGL ES-CM", 12)) {
    315             verptr = (const char *)dc->gl.gl.version + 12;
    316         }
    317         if (!memcmp(dc->gl.gl.version, "OpenGL ES ", 10)) {
    318             verptr = (const char *)dc->gl.gl.version + 9;
    319         }
    320     }
    321 
    322     if (!verptr) {
    323         LOGE("Error, OpenGL ES Lite not supported");
    324         rsdGLShutdown(rsc);
    325         rsc->setWatchdogGL(NULL, 0, NULL);
    326         return false;
    327     } else {
    328         sscanf(verptr, " %i.%i", &dc->gl.gl.majorVersion, &dc->gl.gl.minorVersion);
    329     }
    330 
    331     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &dc->gl.gl.maxVertexAttribs);
    332     glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &dc->gl.gl.maxVertexUniformVectors);
    333     glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxVertexTextureUnits);
    334 
    335     glGetIntegerv(GL_MAX_VARYING_VECTORS, &dc->gl.gl.maxVaryingVectors);
    336     glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxTextureImageUnits);
    337 
    338     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &dc->gl.gl.maxFragmentTextureImageUnits);
    339     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &dc->gl.gl.maxFragmentUniformVectors);
    340 
    341     dc->gl.gl.OES_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
    342                                                 "GL_OES_texture_npot");
    343     dc->gl.gl.GL_IMG_texture_npot = NULL != strstr((const char *)dc->gl.gl.extensions,
    344                                                    "GL_IMG_texture_npot");
    345     dc->gl.gl.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)dc->gl.gl.extensions,
    346                                                             "GL_NV_texture_npot_2D_mipmap");
    347     dc->gl.gl.EXT_texture_max_aniso = 1.0f;
    348     bool hasAniso = NULL != strstr((const char *)dc->gl.gl.extensions,
    349                                    "GL_EXT_texture_filter_anisotropic");
    350     if (hasAniso) {
    351         glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dc->gl.gl.EXT_texture_max_aniso);
    352     }
    353 
    354     if (0) {
    355         DumpDebug(dc);
    356     }
    357 
    358     dc->gl.shaderCache = new RsdShaderCache();
    359     dc->gl.vertexArrayState = new RsdVertexArrayState();
    360     dc->gl.vertexArrayState->init(dc->gl.gl.maxVertexAttribs);
    361     dc->gl.currentFrameBuffer = NULL;
    362 
    363     LOGV("%p initGLThread end", rsc);
    364     rsc->setWatchdogGL(NULL, 0, NULL);
    365     return true;
    366 }
    367 
    368 
    369 bool rsdGLSetSurface(const Context *rsc, uint32_t w, uint32_t h, RsNativeWindow sur) {
    370     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    371 
    372     EGLBoolean ret;
    373     // WAR: Some drivers fail to handle 0 size surfaces correcntly.
    374     // Use the pbuffer to avoid this pitfall.
    375     if ((dc->gl.egl.surface != NULL) || (w == 0) || (h == 0)) {
    376         rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
    377         ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
    378                              dc->gl.egl.surfaceDefault, dc->gl.egl.context);
    379         checkEglError("eglMakeCurrent", ret);
    380 
    381         rsc->setWatchdogGL("eglDestroySurface", __LINE__, __FILE__);
    382         ret = eglDestroySurface(dc->gl.egl.display, dc->gl.egl.surface);
    383         checkEglError("eglDestroySurface", ret);
    384 
    385         dc->gl.egl.surface = NULL;
    386         dc->gl.width = 1;
    387         dc->gl.height = 1;
    388     }
    389 
    390     if (dc->gl.wndSurface != NULL) {
    391         dc->gl.wndSurface->decStrong(NULL);
    392     }
    393 
    394     dc->gl.wndSurface = (ANativeWindow *)sur;
    395     if (dc->gl.wndSurface != NULL) {
    396         dc->gl.wndSurface->incStrong(NULL);
    397         dc->gl.width = w;
    398         dc->gl.height = h;
    399 
    400         rsc->setWatchdogGL("eglCreateWindowSurface", __LINE__, __FILE__);
    401         dc->gl.egl.surface = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
    402                                                     dc->gl.wndSurface, NULL);
    403         checkEglError("eglCreateWindowSurface");
    404         if (dc->gl.egl.surface == EGL_NO_SURFACE) {
    405             LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
    406         }
    407 
    408         rsc->setWatchdogGL("eglMakeCurrent", __LINE__, __FILE__);
    409         ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surface,
    410                              dc->gl.egl.surface, dc->gl.egl.context);
    411         checkEglError("eglMakeCurrent", ret);
    412     }
    413     rsc->setWatchdogGL(NULL, 0, NULL);
    414     return true;
    415 }
    416 
    417 void rsdGLSwap(const android::renderscript::Context *rsc) {
    418     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    419     RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
    420 }
    421 
    422 void rsdGLCheckError(const android::renderscript::Context *rsc,
    423                      const char *msg, bool isFatal) {
    424     GLenum err = glGetError();
    425     if (err != GL_NO_ERROR) {
    426         char buf[1024];
    427         snprintf(buf, sizeof(buf), "GL Error = 0x%08x, from: %s", err, msg);
    428 
    429         if (isFatal) {
    430             rsc->setError(RS_ERROR_FATAL_DRIVER, buf);
    431         } else {
    432             switch (err) {
    433             case GL_OUT_OF_MEMORY:
    434                 rsc->setError(RS_ERROR_OUT_OF_MEMORY, buf);
    435                 break;
    436             default:
    437                 rsc->setError(RS_ERROR_DRIVER, buf);
    438                 break;
    439             }
    440         }
    441 
    442         LOGE("%p, %s", rsc, buf);
    443     }
    444 
    445 }
    446