Home | History | Annotate | Download | only in RenderEngine
      1 /*
      2  * Copyright 2013 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 <cutils/log.h>
     18 #include <ui/Rect.h>
     19 #include <ui/Region.h>
     20 
     21 #include "RenderEngine.h"
     22 #include "GLES10RenderEngine.h"
     23 #include "GLES11RenderEngine.h"
     24 #include "GLES20RenderEngine.h"
     25 #include "GLExtensions.h"
     26 #include "Mesh.h"
     27 
     28 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
     29 
     30 // ---------------------------------------------------------------------------
     31 namespace android {
     32 // ---------------------------------------------------------------------------
     33 
     34 static bool findExtension(const char* exts, const char* name) {
     35     if (!exts)
     36         return false;
     37     size_t len = strlen(name);
     38 
     39     const char* pos = exts;
     40     while ((pos = strstr(pos, name)) != NULL) {
     41         if (pos[len] == '\0' || pos[len] == ' ')
     42             return true;
     43         pos += len;
     44     }
     45 
     46     return false;
     47 }
     48 
     49 RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) {
     50     // EGL_ANDROIDX_no_config_context is an experimental extension with no
     51     // written specification. It will be replaced by something more formal.
     52     // SurfaceFlinger is using it to allow a single EGLContext to render to
     53     // both a 16-bit primary display framebuffer and a 32-bit virtual display
     54     // framebuffer.
     55     //
     56     // The code assumes that ES2 or later is available if this extension is
     57     // supported.
     58     EGLConfig config = EGL_NO_CONFIG;
     59     if (!findExtension(
     60             eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
     61             "EGL_ANDROIDX_no_config_context")) {
     62         config = chooseEglConfig(display, hwcFormat);
     63     }
     64 
     65     EGLint renderableType = 0;
     66     if (config == EGL_NO_CONFIG) {
     67         renderableType = EGL_OPENGL_ES2_BIT;
     68     } else if (!eglGetConfigAttrib(display, config,
     69             EGL_RENDERABLE_TYPE, &renderableType)) {
     70         LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
     71     }
     72     EGLint contextClientVersion = 0;
     73     if (renderableType & EGL_OPENGL_ES2_BIT) {
     74         contextClientVersion = 2;
     75     } else if (renderableType & EGL_OPENGL_ES_BIT) {
     76         contextClientVersion = 1;
     77     } else {
     78         LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
     79     }
     80 
     81     // Also create our EGLContext
     82     EGLint contextAttributes[] = {
     83             EGL_CONTEXT_CLIENT_VERSION, contextClientVersion,      // MUST be first
     84 #ifdef EGL_IMG_context_priority
     85 #ifdef HAS_CONTEXT_PRIORITY
     86 #warning "using EGL_IMG_context_priority"
     87             EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
     88 #endif
     89 #endif
     90             EGL_NONE, EGL_NONE
     91     };
     92     EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes);
     93 
     94     // if can't create a GL context, we can only abort.
     95     LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed");
     96 
     97 
     98     // now figure out what version of GL did we actually get
     99     // NOTE: a dummy surface is not needed if KHR_create_context is supported
    100 
    101     EGLConfig dummyConfig = config;
    102     if (dummyConfig == EGL_NO_CONFIG) {
    103         dummyConfig = chooseEglConfig(display, hwcFormat);
    104     }
    105     EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
    106     EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
    107     LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer");
    108     EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
    109     LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
    110 
    111     GLExtensions& extensions(GLExtensions::getInstance());
    112     extensions.initWithGLStrings(
    113             glGetString(GL_VENDOR),
    114             glGetString(GL_RENDERER),
    115             glGetString(GL_VERSION),
    116             glGetString(GL_EXTENSIONS));
    117 
    118     GlesVersion version = parseGlesVersion( extensions.getVersion() );
    119 
    120     // initialize the renderer while GL is current
    121 
    122     RenderEngine* engine = NULL;
    123     switch (version) {
    124     case GLES_VERSION_1_0:
    125         engine = new GLES10RenderEngine();
    126         break;
    127     case GLES_VERSION_1_1:
    128         engine = new GLES11RenderEngine();
    129         break;
    130     case GLES_VERSION_2_0:
    131     case GLES_VERSION_3_0:
    132         engine = new GLES20RenderEngine();
    133         break;
    134     }
    135     engine->setEGLHandles(config, ctxt);
    136 
    137     ALOGI("OpenGL ES informations:");
    138     ALOGI("vendor    : %s", extensions.getVendor());
    139     ALOGI("renderer  : %s", extensions.getRenderer());
    140     ALOGI("version   : %s", extensions.getVersion());
    141     ALOGI("extensions: %s", extensions.getExtension());
    142     ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
    143     ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
    144 
    145     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    146     eglDestroySurface(display, dummy);
    147 
    148     return engine;
    149 }
    150 
    151 RenderEngine::RenderEngine() : mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {
    152 }
    153 
    154 RenderEngine::~RenderEngine() {
    155 }
    156 
    157 void RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) {
    158     mEGLConfig = config;
    159     mEGLContext = ctxt;
    160 }
    161 
    162 EGLContext RenderEngine::getEGLConfig() const {
    163     return mEGLConfig;
    164 }
    165 
    166 EGLContext RenderEngine::getEGLContext() const {
    167     return mEGLContext;
    168 }
    169 
    170 void RenderEngine::checkErrors() const {
    171     do {
    172         // there could be more than one error flag
    173         GLenum error = glGetError();
    174         if (error == GL_NO_ERROR)
    175             break;
    176         ALOGE("GL error 0x%04x", int(error));
    177     } while (true);
    178 }
    179 
    180 RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) {
    181     int major, minor;
    182     if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
    183         if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
    184             ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
    185             return GLES_VERSION_1_0;
    186         }
    187     }
    188 
    189     if (major == 1 && minor == 0) return GLES_VERSION_1_0;
    190     if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
    191     if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
    192     if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
    193 
    194     ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
    195     return GLES_VERSION_1_0;
    196 }
    197 
    198 void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height,
    199         float red, float green, float blue, float alpha) {
    200     size_t c;
    201     Rect const* r = region.getArray(&c);
    202     Mesh mesh(Mesh::TRIANGLES, c*6, 2);
    203     Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
    204     for (size_t i=0 ; i<c ; i++, r++) {
    205         position[i*6 + 0].x = r->left;
    206         position[i*6 + 0].y = height - r->top;
    207         position[i*6 + 1].x = r->left;
    208         position[i*6 + 1].y = height - r->bottom;
    209         position[i*6 + 2].x = r->right;
    210         position[i*6 + 2].y = height - r->bottom;
    211         position[i*6 + 3].x = r->left;
    212         position[i*6 + 3].y = height - r->top;
    213         position[i*6 + 4].x = r->right;
    214         position[i*6 + 4].y = height - r->bottom;
    215         position[i*6 + 5].x = r->right;
    216         position[i*6 + 5].y = height - r->top;
    217     }
    218     setupFillWithColor(red, green, blue, alpha);
    219     drawMesh(mesh);
    220 }
    221 
    222 void RenderEngine::flush() {
    223     glFlush();
    224 }
    225 
    226 void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
    227     glClearColor(red, green, blue, alpha);
    228     glClear(GL_COLOR_BUFFER_BIT);
    229 }
    230 
    231 void RenderEngine::setScissor(
    232         uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
    233     glScissor(left, bottom, right, top);
    234     glEnable(GL_SCISSOR_TEST);
    235 }
    236 
    237 void RenderEngine::disableScissor() {
    238     glDisable(GL_SCISSOR_TEST);
    239 }
    240 
    241 void RenderEngine::genTextures(size_t count, uint32_t* names) {
    242     glGenTextures(count, names);
    243 }
    244 
    245 void RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
    246     glDeleteTextures(count, names);
    247 }
    248 
    249 void RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) {
    250     glReadPixels(l, b, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    251 }
    252 
    253 void RenderEngine::dump(String8& result) {
    254     const GLExtensions& extensions(GLExtensions::getInstance());
    255     result.appendFormat("GLES: %s, %s, %s\n",
    256             extensions.getVendor(),
    257             extensions.getRenderer(),
    258             extensions.getVersion());
    259     result.appendFormat("%s\n", extensions.getExtension());
    260 }
    261 
    262 // ---------------------------------------------------------------------------
    263 
    264 RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer(
    265         RenderEngine& engine, EGLImageKHR image) : mEngine(engine)
    266 {
    267     mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus);
    268 
    269     ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES,
    270             "glCheckFramebufferStatusOES error %d", mStatus);
    271 }
    272 
    273 RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() {
    274     // back to main framebuffer
    275     mEngine.unbindFramebuffer(mTexName, mFbName);
    276 }
    277 
    278 status_t RenderEngine::BindImageAsFramebuffer::getStatus() const {
    279     return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
    280 }
    281 
    282 // ---------------------------------------------------------------------------
    283 
    284 static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs,
    285         EGLint attribute, EGLint wanted, EGLConfig* outConfig) {
    286     EGLint numConfigs = -1, n = 0;
    287     eglGetConfigs(dpy, NULL, 0, &numConfigs);
    288     EGLConfig* const configs = new EGLConfig[numConfigs];
    289     eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
    290 
    291     if (n) {
    292         if (attribute != EGL_NONE) {
    293             for (int i=0 ; i<n ; i++) {
    294                 EGLint value = 0;
    295                 eglGetConfigAttrib(dpy, configs[i], attribute, &value);
    296                 if (wanted == value) {
    297                     *outConfig = configs[i];
    298                     delete [] configs;
    299                     return NO_ERROR;
    300                 }
    301             }
    302         } else {
    303             // just pick the first one
    304             *outConfig = configs[0];
    305             delete [] configs;
    306             return NO_ERROR;
    307         }
    308     }
    309     delete [] configs;
    310     return NAME_NOT_FOUND;
    311 }
    312 
    313 class EGLAttributeVector {
    314     struct Attribute;
    315     class Adder;
    316     friend class Adder;
    317     KeyedVector<Attribute, EGLint> mList;
    318     struct Attribute {
    319         Attribute() : v(0) {};
    320         Attribute(EGLint v) : v(v) { }
    321         EGLint v;
    322         bool operator < (const Attribute& other) const {
    323             // this places EGL_NONE at the end
    324             EGLint lhs(v);
    325             EGLint rhs(other.v);
    326             if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
    327             if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
    328             return lhs < rhs;
    329         }
    330     };
    331     class Adder {
    332         friend class EGLAttributeVector;
    333         EGLAttributeVector& v;
    334         EGLint attribute;
    335         Adder(EGLAttributeVector& v, EGLint attribute)
    336             : v(v), attribute(attribute) {
    337         }
    338     public:
    339         void operator = (EGLint value) {
    340             if (attribute != EGL_NONE) {
    341                 v.mList.add(attribute, value);
    342             }
    343         }
    344         operator EGLint () const { return v.mList[attribute]; }
    345     };
    346 public:
    347     EGLAttributeVector() {
    348         mList.add(EGL_NONE, EGL_NONE);
    349     }
    350     void remove(EGLint attribute) {
    351         if (attribute != EGL_NONE) {
    352             mList.removeItem(attribute);
    353         }
    354     }
    355     Adder operator [] (EGLint attribute) {
    356         return Adder(*this, attribute);
    357     }
    358     EGLint operator [] (EGLint attribute) const {
    359        return mList[attribute];
    360     }
    361     // cast-operator to (EGLint const*)
    362     operator EGLint const* () const { return &mList.keyAt(0).v; }
    363 };
    364 
    365 
    366 static status_t selectEGLConfig(EGLDisplay display, EGLint format,
    367     EGLint renderableType, EGLConfig* config) {
    368     // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
    369     // it is to be used with WIFI displays
    370     status_t err;
    371     EGLint wantedAttribute;
    372     EGLint wantedAttributeValue;
    373 
    374     EGLAttributeVector attribs;
    375     if (renderableType) {
    376         attribs[EGL_RENDERABLE_TYPE]            = renderableType;
    377         attribs[EGL_RECORDABLE_ANDROID]         = EGL_TRUE;
    378         attribs[EGL_SURFACE_TYPE]               = EGL_WINDOW_BIT|EGL_PBUFFER_BIT;
    379         attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
    380         attribs[EGL_RED_SIZE]                   = 8;
    381         attribs[EGL_GREEN_SIZE]                 = 8;
    382         attribs[EGL_BLUE_SIZE]                  = 8;
    383         wantedAttribute                         = EGL_NONE;
    384         wantedAttributeValue                    = EGL_NONE;
    385     } else {
    386         // if no renderable type specified, fallback to a simplified query
    387         wantedAttribute                         = EGL_NATIVE_VISUAL_ID;
    388         wantedAttributeValue                    = format;
    389     }
    390 
    391     err = selectConfigForAttribute(display, attribs,
    392             wantedAttribute, wantedAttributeValue, config);
    393     if (err == NO_ERROR) {
    394         EGLint caveat;
    395         if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
    396             ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
    397     }
    398 
    399     return err;
    400 }
    401 
    402 EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
    403     status_t err;
    404     EGLConfig config;
    405 
    406     // First try to get an ES2 config
    407     err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
    408     if (err != NO_ERROR) {
    409         // If ES2 fails, try ES1
    410         err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
    411         if (err != NO_ERROR) {
    412             // still didn't work, probably because we're on the emulator...
    413             // try a simplified query
    414             ALOGW("no suitable EGLConfig found, trying a simpler query");
    415             err = selectEGLConfig(display, format, 0, &config);
    416             if (err != NO_ERROR) {
    417                 // this EGL is too lame for android
    418                 LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
    419             }
    420         }
    421     }
    422 
    423     // print some debugging info
    424     EGLint r,g,b,a;
    425     eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
    426     eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
    427     eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
    428     eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
    429     ALOGI("EGL information:");
    430     ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
    431     ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
    432     ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
    433     ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
    434     ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
    435 
    436     return config;
    437 }
    438 
    439 
    440 void RenderEngine::primeCache() const {
    441     // Getting the ProgramCache instance causes it to prime its shader cache,
    442     // which is performed in its constructor
    443     ProgramCache::getInstance();
    444 }
    445 
    446 // ---------------------------------------------------------------------------
    447 }; // namespace android
    448 // ---------------------------------------------------------------------------
    449