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