RenderEngine.cpp revision 19733a32799f792125913e746e8644d16f8dc223
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// --------------------------------------------------------------------------- 29namespace android { 30// --------------------------------------------------------------------------- 31 32RenderEngine* RenderEngine::create(EGLDisplay display, EGLConfig config) { 33 // Also create our EGLContext 34 EGLint contextAttributes[] = { 35 EGL_CONTEXT_CLIENT_VERSION, 2, // MUST be first 36#ifdef EGL_IMG_context_priority 37#ifdef HAS_CONTEXT_PRIORITY 38#warning "using EGL_IMG_context_priority" 39 EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG, 40#endif 41#endif 42 EGL_NONE, EGL_NONE 43 }; 44 45 EGLContext ctxt = eglCreateContext(display, config, NULL, contextAttributes); 46 if (ctxt == EGL_NO_CONTEXT) { 47 // maybe ES 2.x is not supported 48 ALOGW("can't create an ES 2.x context, trying 1.x"); 49 ctxt = eglCreateContext(display, config, NULL, contextAttributes + 2); 50 } 51 52 // if can't create a GL context, we can only abort. 53 LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed"); 54 55 56 // now figure out what version of GL did we actually get 57 // NOTE: a dummy surface is not needed if KHR_create_context is supported 58 59 EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE }; 60 EGLSurface dummy = eglCreatePbufferSurface(display, config, attribs); 61 LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer"); 62 EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt); 63 LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current"); 64 65 GLExtensions& extensions(GLExtensions::getInstance()); 66 extensions.initWithGLStrings( 67 glGetString(GL_VENDOR), 68 glGetString(GL_RENDERER), 69 glGetString(GL_VERSION), 70 glGetString(GL_EXTENSIONS)); 71 72 GlesVersion version = parseGlesVersion( extensions.getVersion() ); 73 74 // initialize the renderer while GL is current 75 76 RenderEngine* engine = NULL; 77 switch (version) { 78 case GLES_VERSION_1_0: 79 engine = new GLES10RenderEngine(); 80 break; 81 case GLES_VERSION_1_1: 82 engine = new GLES11RenderEngine(); 83 break; 84 case GLES_VERSION_2_0: 85 case GLES_VERSION_3_0: 86 engine = new GLES20RenderEngine(); 87 break; 88 } 89 engine->setEGLContext(ctxt); 90 91 ALOGI("OpenGL ES informations:"); 92 ALOGI("vendor : %s", extensions.getVendor()); 93 ALOGI("renderer : %s", extensions.getRenderer()); 94 ALOGI("version : %s", extensions.getVersion()); 95 ALOGI("extensions: %s", extensions.getExtension()); 96 ALOGI("GL_MAX_TEXTURE_SIZE = %d", engine->getMaxTextureSize()); 97 ALOGI("GL_MAX_VIEWPORT_DIMS = %d", engine->getMaxViewportDims()); 98 99 eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 100 eglDestroySurface(display, dummy); 101 102 return engine; 103} 104 105RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) { 106} 107 108RenderEngine::~RenderEngine() { 109} 110 111void RenderEngine::setEGLContext(EGLContext ctxt) { 112 mEGLContext = ctxt; 113} 114 115EGLContext RenderEngine::getEGLContext() const { 116 return mEGLContext; 117} 118 119void RenderEngine::checkErrors() const { 120 do { 121 // there could be more than one error flag 122 GLenum error = glGetError(); 123 if (error == GL_NO_ERROR) 124 break; 125 ALOGE("GL error 0x%04x", int(error)); 126 } while (true); 127} 128 129RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) { 130 int major, minor; 131 if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) { 132 if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) { 133 ALOGW("Unable to parse GL_VERSION string: \"%s\"", str); 134 return GLES_VERSION_1_0; 135 } 136 } 137 138 if (major == 1 && minor == 0) return GLES_VERSION_1_0; 139 if (major == 1 && minor >= 1) return GLES_VERSION_1_1; 140 if (major == 2 && minor >= 0) return GLES_VERSION_2_0; 141 if (major == 3 && minor >= 0) return GLES_VERSION_3_0; 142 143 ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor); 144 return GLES_VERSION_1_0; 145} 146 147void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, 148 float red, float green, float blue, float alpha) { 149 size_t c; 150 Rect const* r = region.getArray(&c); 151 Mesh mesh(Mesh::TRIANGLES, c*6, 2); 152 Mesh::VertexArray position(mesh.getPositionArray()); 153 for (size_t i=0 ; i<c ; i++, r++) { 154 position[i*6 + 0].x = r->left; 155 position[i*6 + 0].y = height - r->top; 156 position[i*6 + 1].x = r->left; 157 position[i*6 + 1].y = height - r->bottom; 158 position[i*6 + 2].x = r->right; 159 position[i*6 + 2].y = height - r->bottom; 160 position[i*6 + 3].x = r->left; 161 position[i*6 + 3].y = height - r->top; 162 position[i*6 + 4].x = r->right; 163 position[i*6 + 4].y = height - r->bottom; 164 position[i*6 + 5].x = r->right; 165 position[i*6 + 5].y = height - r->top; 166 } 167 setupFillWithColor(red, green, blue, alpha); 168 drawMesh(mesh); 169} 170 171void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) { 172 glClearColor(red, green, blue, alpha); 173 glClear(GL_COLOR_BUFFER_BIT); 174} 175 176void RenderEngine::setScissor( 177 uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) { 178 glScissor(left, bottom, right, top); 179 glEnable(GL_SCISSOR_TEST); 180} 181 182void RenderEngine::disableScissor() { 183 glDisable(GL_SCISSOR_TEST); 184} 185 186void RenderEngine::genTextures(size_t count, uint32_t* names) { 187 glGenTextures(count, names); 188} 189 190void RenderEngine::deleteTextures(size_t count, uint32_t const* names) { 191 glDeleteTextures(count, names); 192} 193 194void RenderEngine::dump(String8& result) { 195 const GLExtensions& extensions(GLExtensions::getInstance()); 196 result.appendFormat("GLES: %s, %s, %s\n", 197 extensions.getVendor(), 198 extensions.getRenderer(), 199 extensions.getVersion()); 200 result.appendFormat("%s\n", extensions.getExtension()); 201} 202 203// --------------------------------------------------------------------------- 204 205RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( 206 RenderEngine& engine, EGLImageKHR image) : mEngine(engine) 207{ 208 mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus); 209 210 ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, 211 "glCheckFramebufferStatusOES error %d", mStatus); 212} 213 214RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() { 215 // back to main framebuffer 216 mEngine.unbindFramebuffer(mTexName, mFbName); 217} 218 219status_t RenderEngine::BindImageAsFramebuffer::getStatus() const { 220 return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; 221} 222 223// --------------------------------------------------------------------------- 224}; // namespace android 225// --------------------------------------------------------------------------- 226