RenderEngine.cpp revision 3f84483382be2d528918cc1a6fbc6a7d68e0b181
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 for (size_t i=0 ; i<c ; i++, r++) { 153 mesh[i*6 + 0][0] = r->left; 154 mesh[i*6 + 0][1] = height - r->top; 155 mesh[i*6 + 1][0] = r->left; 156 mesh[i*6 + 1][1] = height - r->bottom; 157 mesh[i*6 + 2][0] = r->right; 158 mesh[i*6 + 2][1] = height - r->bottom; 159 mesh[i*6 + 3][0] = r->left; 160 mesh[i*6 + 3][1] = height - r->top; 161 mesh[i*6 + 4][0] = r->right; 162 mesh[i*6 + 4][1] = height - r->bottom; 163 mesh[i*6 + 5][0] = r->right; 164 mesh[i*6 + 5][1] = height - r->top; 165 } 166 fillWithColor(mesh, red, green, blue, alpha); 167} 168 169void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) { 170 glClearColor(red, green, blue, alpha); 171 glClear(GL_COLOR_BUFFER_BIT); 172} 173 174void RenderEngine::setScissor( 175 uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) { 176 glScissor(left, bottom, right, top); 177 glEnable(GL_SCISSOR_TEST); 178} 179 180void RenderEngine::disableScissor() { 181 glDisable(GL_SCISSOR_TEST); 182} 183 184void RenderEngine::genTextures(size_t count, uint32_t* names) { 185 glGenTextures(count, names); 186} 187 188void RenderEngine::deleteTextures(size_t count, uint32_t const* names) { 189 glDeleteTextures(count, names); 190} 191 192// --------------------------------------------------------------------------- 193 194RenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( 195 RenderEngine& engine, EGLImageKHR image) : mEngine(engine) 196{ 197 GLuint tname, name; 198 // turn our EGLImage into a texture 199 glGenTextures(1, &tname); 200 glBindTexture(GL_TEXTURE_2D, tname); 201 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image); 202 // create a Framebuffer Object to render into 203 glGenFramebuffersOES(1, &name); 204 glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); 205 glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, 206 GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); 207 mStatus = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); 208 ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, 209 "glCheckFramebufferStatusOES error %d", mStatus); 210 mTexName = tname; 211 mFbName = name; 212} 213 214RenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() { 215 // back to main framebuffer 216 glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); 217 glDeleteFramebuffersOES(1, &mFbName); 218 glDeleteTextures(1, &mTexName); 219 220} 221 222status_t RenderEngine::BindImageAsFramebuffer::getStatus() const { 223 return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; 224} 225 226// --------------------------------------------------------------------------- 227}; // namespace android 228// --------------------------------------------------------------------------- 229