RenderEngine.cpp revision c93afd54a05497c4ae42db99ea0310ee69cca492
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* 2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright 2013 The Android Open Source Project 3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License. 6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at 7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * http://www.apache.org/licenses/LICENSE-2.0 9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software 11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and 14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License. 15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <log/log.h> 18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <ui/Rect.h> 19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <ui/Region.h> 20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RenderEngine.h" 229fded232a9548a304e0145011df8849fba0dcda7Chris Craik#include "GLES20RenderEngine.h" 23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "GLExtensions.h" 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "Mesh.h" 259fded232a9548a304e0145011df8849fba0dcda7Chris Craik 26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <vector> 27a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik#include <SurfaceFlinger.h> 28a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikEGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// --------------------------------------------------------------------------- 32d3daa3198e2212c985c634821682d5819346b653Chris Craiknamespace android { 339fded232a9548a304e0145011df8849fba0dcda7Chris Craik// --------------------------------------------------------------------------- 349fded232a9548a304e0145011df8849fba0dcda7Chris Craik 359fded232a9548a304e0145011df8849fba0dcda7Chris Craikstatic bool findExtension(const char* exts, const char* name) { 3698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik if (!exts) 370b7e8245db728d127ada698be63d78b33fc6e4daChris Craik return false; 380b7e8245db728d127ada698be63d78b33fc6e4daChris Craik size_t len = strlen(name); 390b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 4098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik const char* pos = exts; 41d3daa3198e2212c985c634821682d5819346b653Chris Craik while ((pos = strstr(pos, name)) != NULL) { 42d3daa3198e2212c985c634821682d5819346b653Chris Craik if (pos[len] == '\0' || pos[len] == ' ') 430b7e8245db728d127ada698be63d78b33fc6e4daChris Craik return true; 44818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik pos += len; 455854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik } 465854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 475854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik return false; 48818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik} 49818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 50818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris CraikRenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat) { 510b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // EGL_ANDROIDX_no_config_context is an experimental extension with no 52818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // written specification. It will be replaced by something more formal. 53818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // SurfaceFlinger is using it to allow a single EGLContext to render to 54818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // both a 16-bit primary display framebuffer and a 32-bit virtual display 55818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // framebuffer. 56818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik // 570b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // The code assumes that ES2 or later is available if this extension is 5898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // supported. 5998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EGLConfig config = EGL_NO_CONFIG; 60818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik if (!findExtension( 61818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS), 625854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik "EGL_ANDROIDX_no_config_context")) { 63e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik config = chooseEglConfig(display, hwcFormat); 64e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik } 65e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik 66e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik EGLint renderableType = 0; 67e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik if (config == EGL_NO_CONFIG) { 68e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik renderableType = EGL_OPENGL_ES2_BIT; 69e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik } else if (!eglGetConfigAttrib(display, config, 70e4db79de127cfe961195f52907af8451026eaa20Chris Craik EGL_RENDERABLE_TYPE, &renderableType)) { 71818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE"); 72e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik } 73e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik EGLint contextClientVersion = 0; 74e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik if (renderableType & EGL_OPENGL_ES2_BIT) { 75818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik contextClientVersion = 2; 76818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik } else if (renderableType & EGL_OPENGL_ES_BIT) { 77818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik contextClientVersion = 1; 785854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik } else { 79e4db79de127cfe961195f52907af8451026eaa20Chris Craik LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs"); 80818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik } 81818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 827435eb148e72382126e9073183e881357bb38a8bChris Craik std::vector<EGLint> contextAttributes; 837435eb148e72382126e9073183e881357bb38a8bChris Craik contextAttributes.reserve(6); 847435eb148e72382126e9073183e881357bb38a8bChris Craik contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION); 857435eb148e72382126e9073183e881357bb38a8bChris Craik contextAttributes.push_back(contextClientVersion); 867435eb148e72382126e9073183e881357bb38a8bChris Craik#ifdef EGL_IMG_context_priority 877435eb148e72382126e9073183e881357bb38a8bChris Craik if (SurfaceFlinger::useContextPriority) { 887435eb148e72382126e9073183e881357bb38a8bChris Craik contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG); 897435eb148e72382126e9073183e881357bb38a8bChris Craik contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG); 907435eb148e72382126e9073183e881357bb38a8bChris Craik } 917435eb148e72382126e9073183e881357bb38a8bChris Craik#endif 927435eb148e72382126e9073183e881357bb38a8bChris Craik contextAttributes.push_back(EGL_NONE); 937435eb148e72382126e9073183e881357bb38a8bChris Craik contextAttributes.push_back(EGL_NONE); 947435eb148e72382126e9073183e881357bb38a8bChris Craik 957435eb148e72382126e9073183e881357bb38a8bChris Craik EGLContext ctxt = eglCreateContext(display, config, NULL, 9698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik contextAttributes.data()); 97e4db79de127cfe961195f52907af8451026eaa20Chris Craik 985854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik // if can't create a GL context, we can only abort. 995854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik LOG_ALWAYS_FATAL_IF(ctxt==EGL_NO_CONTEXT, "EGLContext creation failed"); 100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1015854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 10298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // now figure out what version of GL did we actually get 103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // NOTE: a dummy surface is not needed if KHR_create_context is supported 104e4db79de127cfe961195f52907af8451026eaa20Chris Craik 105e4db79de127cfe961195f52907af8451026eaa20Chris Craik EGLConfig dummyConfig = config; 106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (dummyConfig == EGL_NO_CONFIG) { 1075854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik dummyConfig = chooseEglConfig(display, hwcFormat); 108e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 109e4db79de127cfe961195f52907af8451026eaa20Chris Craik EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE }; 110e4db79de127cfe961195f52907af8451026eaa20Chris Craik EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs); 111e4db79de127cfe961195f52907af8451026eaa20Chris Craik LOG_ALWAYS_FATAL_IF(dummy==EGL_NO_SURFACE, "can't create dummy pbuffer"); 112e4db79de127cfe961195f52907af8451026eaa20Chris Craik EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt); 113e4db79de127cfe961195f52907af8451026eaa20Chris Craik LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current"); 114e4db79de127cfe961195f52907af8451026eaa20Chris Craik 115e4db79de127cfe961195f52907af8451026eaa20Chris Craik GLExtensions& extensions(GLExtensions::getInstance()); 116e4db79de127cfe961195f52907af8451026eaa20Chris Craik extensions.initWithGLStrings( 117e4db79de127cfe961195f52907af8451026eaa20Chris Craik glGetString(GL_VENDOR), 118e4db79de127cfe961195f52907af8451026eaa20Chris Craik glGetString(GL_RENDERER), 119e4db79de127cfe961195f52907af8451026eaa20Chris Craik glGetString(GL_VERSION), 120e4db79de127cfe961195f52907af8451026eaa20Chris Craik glGetString(GL_EXTENSIONS)); 121e4db79de127cfe961195f52907af8451026eaa20Chris Craik 122e4db79de127cfe961195f52907af8451026eaa20Chris Craik GlesVersion version = parseGlesVersion( extensions.getVersion() ); 123e4db79de127cfe961195f52907af8451026eaa20Chris Craik 124e4db79de127cfe961195f52907af8451026eaa20Chris Craik // initialize the renderer while GL is current 125e4db79de127cfe961195f52907af8451026eaa20Chris Craik 126e4db79de127cfe961195f52907af8451026eaa20Chris Craik RenderEngine* engine = NULL; 127e4db79de127cfe961195f52907af8451026eaa20Chris Craik switch (version) { 128e4db79de127cfe961195f52907af8451026eaa20Chris Craik case GLES_VERSION_1_0: 129e4db79de127cfe961195f52907af8451026eaa20Chris Craik case GLES_VERSION_1_1: 130e4db79de127cfe961195f52907af8451026eaa20Chris Craik LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run."); 131e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 132e4db79de127cfe961195f52907af8451026eaa20Chris Craik case GLES_VERSION_2_0: 133e4db79de127cfe961195f52907af8451026eaa20Chris Craik case GLES_VERSION_3_0: 134e4db79de127cfe961195f52907af8451026eaa20Chris Craik engine = new GLES20RenderEngine(); 135e4db79de127cfe961195f52907af8451026eaa20Chris Craik break; 136e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 137e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik engine->setEGLHandles(config, ctxt); 1385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ALOGI("OpenGL ES informations:"); 140b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGI("vendor : %s", extensions.getVendor()); 141b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGI("renderer : %s", extensions.getRenderer()); 142b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGI("version : %s", extensions.getVersion()); 143b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGI("extensions: %s", extensions.getExtension()); 144b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize()); 145b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims()); 1465854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 147b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 148b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik eglDestroySurface(display, dummy); 1495854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 150b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return engine; 151b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 152b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 153b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikRenderEngine::RenderEngine() : mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) { 1545854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik} 1555854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1565854b34881b1a747ac80b5077869ef270a92b1f4Chris CraikRenderEngine::~RenderEngine() { 1575854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik} 1585854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1595854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid RenderEngine::setEGLHandles(EGLConfig config, EGLContext ctxt) { 1605854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mEGLConfig = config; 1615854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik mEGLContext = ctxt; 1625854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik} 16398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 16484ad6149db0e1dc98ed3778ee4fc2ab685765d9aChris CraikEGLContext RenderEngine::getEGLConfig() const { 16598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return mEGLConfig; 16698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 16798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 16898787e6c9b2c10b1ab7820bdac168686025b924aChris CraikEGLContext RenderEngine::getEGLContext() const { 16998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return mEGLContext; 17098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 17198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 17298787e6c9b2c10b1ab7820bdac168686025b924aChris Craikvoid RenderEngine::checkErrors() const { 17398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik do { 17498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // there could be more than one error flag 17598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik GLenum error = glGetError(); 17698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik if (error == GL_NO_ERROR) 1775854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik break; 17815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ALOGE("GL error 0x%04x", int(error)); 1795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik } while (true); 1805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik} 1815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 1825854b34881b1a747ac80b5077869ef270a92b1f4Chris CraikRenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) { 1835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int major, minor; 1845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) { 185e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) { 186e4db79de127cfe961195f52907af8451026eaa20Chris Craik ALOGW("Unable to parse GL_VERSION string: \"%s\"", str); 187e4db79de127cfe961195f52907af8451026eaa20Chris Craik return GLES_VERSION_1_0; 188e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 189e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 190e4db79de127cfe961195f52907af8451026eaa20Chris Craik 191e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (major == 1 && minor == 0) return GLES_VERSION_1_0; 192e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (major == 1 && minor >= 1) return GLES_VERSION_1_1; 193e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (major == 2 && minor >= 0) return GLES_VERSION_2_0; 194e4db79de127cfe961195f52907af8451026eaa20Chris Craik if (major == 3 && minor >= 0) return GLES_VERSION_3_0; 195e4db79de127cfe961195f52907af8451026eaa20Chris Craik 196e4db79de127cfe961195f52907af8451026eaa20Chris Craik ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor); 197e4db79de127cfe961195f52907af8451026eaa20Chris Craik return GLES_VERSION_1_0; 198e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 199e4db79de127cfe961195f52907af8451026eaa20Chris Craik 200e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, 201e4db79de127cfe961195f52907af8451026eaa20Chris Craik float red, float green, float blue, float alpha) { 202e4db79de127cfe961195f52907af8451026eaa20Chris Craik size_t c; 203e4db79de127cfe961195f52907af8451026eaa20Chris Craik Rect const* r = region.getArray(&c); 20415f046866cb650d78f55d03327cfa4a474fc9471Chris Craik Mesh mesh(Mesh::TRIANGLES, c*6, 2); 205e4db79de127cfe961195f52907af8451026eaa20Chris Craik Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); 206e4db79de127cfe961195f52907af8451026eaa20Chris Craik for (size_t i=0 ; i<c ; i++, r++) { 207e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 0].x = r->left; 208e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 0].y = height - r->top; 209e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 1].x = r->left; 210e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 1].y = height - r->bottom; 211e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 2].x = r->right; 212e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 2].y = height - r->bottom; 213e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 3].x = r->left; 214e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 3].y = height - r->top; 215e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 4].x = r->right; 216e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 4].y = height - r->bottom; 217e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 5].x = r->right; 218e4db79de127cfe961195f52907af8451026eaa20Chris Craik position[i*6 + 5].y = height - r->top; 219e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 220e4db79de127cfe961195f52907af8451026eaa20Chris Craik setupFillWithColor(red, green, blue, alpha); 221e4db79de127cfe961195f52907af8451026eaa20Chris Craik drawMesh(mesh); 222e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 223e4db79de127cfe961195f52907af8451026eaa20Chris Craik 224e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RenderEngine::flush() { 225e4db79de127cfe961195f52907af8451026eaa20Chris Craik glFlush(); 226e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 227e4db79de127cfe961195f52907af8451026eaa20Chris Craik 228e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RenderEngine::clearWithColor(float red, float green, float blue, float alpha) { 229e4db79de127cfe961195f52907af8451026eaa20Chris Craik glClearColor(red, green, blue, alpha); 230e4db79de127cfe961195f52907af8451026eaa20Chris Craik glClear(GL_COLOR_BUFFER_BIT); 231e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 232e4db79de127cfe961195f52907af8451026eaa20Chris Craik 233e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RenderEngine::setScissor( 234e4db79de127cfe961195f52907af8451026eaa20Chris Craik uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) { 235e4db79de127cfe961195f52907af8451026eaa20Chris Craik glScissor(left, bottom, right, top); 236e4db79de127cfe961195f52907af8451026eaa20Chris Craik glEnable(GL_SCISSOR_TEST); 237e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 23815f046866cb650d78f55d03327cfa4a474fc9471Chris Craik 239e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RenderEngine::disableScissor() { 240e4db79de127cfe961195f52907af8451026eaa20Chris Craik glDisable(GL_SCISSOR_TEST); 241e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 242e4db79de127cfe961195f52907af8451026eaa20Chris Craik 243e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RenderEngine::genTextures(size_t count, uint32_t* names) { 244e4db79de127cfe961195f52907af8451026eaa20Chris Craik glGenTextures(count, names); 245e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 246e4db79de127cfe961195f52907af8451026eaa20Chris Craik 247e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RenderEngine::deleteTextures(size_t count, uint32_t const* names) { 248e4db79de127cfe961195f52907af8451026eaa20Chris Craik glDeleteTextures(count, names); 249e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 250e4db79de127cfe961195f52907af8451026eaa20Chris Craik 251e4db79de127cfe961195f52907af8451026eaa20Chris Craikvoid RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) { 252e4db79de127cfe961195f52907af8451026eaa20Chris Craik glReadPixels(l, b, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 253e4db79de127cfe961195f52907af8451026eaa20Chris Craik} 254e4db79de127cfe961195f52907af8451026eaa20Chris Craik 255b87eadda1818034ce03d85f30388384d1ac65916Chris Craikvoid RenderEngine::dump(String8& result) { 25615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik const GLExtensions& extensions(GLExtensions::getInstance()); 25715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik result.appendFormat("GLES: %s, %s, %s\n", 258e4db79de127cfe961195f52907af8451026eaa20Chris Craik extensions.getVendor(), 259e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik extensions.getRenderer(), 260e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik extensions.getVersion()); 261b87eadda1818034ce03d85f30388384d1ac65916Chris Craik result.appendFormat("%s\n", extensions.getExtension()); 262e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik} 263e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik 264e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik// --------------------------------------------------------------------------- 265e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik 266e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris CraikRenderEngine::BindImageAsFramebuffer::BindImageAsFramebuffer( 267e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik RenderEngine& engine, EGLImageKHR image) : mEngine(engine) 268e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik{ 269e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik mEngine.bindImageAsFramebuffer(image, &mTexName, &mFbName, &mStatus); 270e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik 271e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, 272e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik "glCheckFramebufferStatusOES error %d", mStatus); 273e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik} 274e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik 275e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris CraikRenderEngine::BindImageAsFramebuffer::~BindImageAsFramebuffer() { 276e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik // back to main framebuffer 277e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik mEngine.unbindFramebuffer(mTexName, mFbName); 278e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik} 279e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik 280e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craikstatus_t RenderEngine::BindImageAsFramebuffer::getStatus() const { 281e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE; 282e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik} 283e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik 284e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik// --------------------------------------------------------------------------- 285e4db79de127cfe961195f52907af8451026eaa20Chris Craik 286e4db79de127cfe961195f52907af8451026eaa20Chris Craikstatic status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, 287e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik EGLint attribute, EGLint wanted, EGLConfig* outConfig) { 288e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik EGLint numConfigs = -1, n = 0; 289e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik eglGetConfigs(dpy, NULL, 0, &numConfigs); 290e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik EGLConfig* const configs = new EGLConfig[numConfigs]; 291e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik eglChooseConfig(dpy, attrs, configs, numConfigs, &n); 292e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik 293e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik if (n) { 294e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik if (attribute != EGL_NONE) { 295e4db79de127cfe961195f52907af8451026eaa20Chris Craik for (int i=0 ; i<n ; i++) { 296e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik EGLint value = 0; 297e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik eglGetConfigAttrib(dpy, configs[i], attribute, &value); 298e5b50197e870aa6d22c3893f5d25f4279f06e5c3Chris Craik if (wanted == value) { 299e4db79de127cfe961195f52907af8451026eaa20Chris Craik *outConfig = configs[i]; 3005854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik delete [] configs; 301e4db79de127cfe961195f52907af8451026eaa20Chris Craik return NO_ERROR; 302e4db79de127cfe961195f52907af8451026eaa20Chris Craik } 30315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 3048d2cf943d9c7292e54726399faefdec4a01c084bChris Craik } else { 30515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // just pick the first one 30615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik *outConfig = configs[0]; 3078d2cf943d9c7292e54726399faefdec4a01c084bChris Craik delete [] configs; 3088d2cf943d9c7292e54726399faefdec4a01c084bChris Craik return NO_ERROR; 309e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik } 310e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik } 311e4db79de127cfe961195f52907af8451026eaa20Chris Craik delete [] configs; 312e4db79de127cfe961195f52907af8451026eaa20Chris Craik return NAME_NOT_FOUND; 313e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik} 3145854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 31598787e6c9b2c10b1ab7820bdac168686025b924aChris Craikclass EGLAttributeVector { 3165854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik struct Attribute; 3175854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik class Adder; 318e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik friend class Adder; 319e4db79de127cfe961195f52907af8451026eaa20Chris Craik KeyedVector<Attribute, EGLint> mList; 320e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik struct Attribute { 321e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik Attribute() : v(0) {}; 322e4db79de127cfe961195f52907af8451026eaa20Chris Craik explicit Attribute(EGLint v) : v(v) { } 323e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik EGLint v; 324e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik bool operator < (const Attribute& other) const { 325e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik // this places EGL_NONE at the end 326e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik EGLint lhs(v); 327e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik EGLint rhs(other.v); 328e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik if (lhs == EGL_NONE) lhs = 0x7FFFFFFF; 329e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik if (rhs == EGL_NONE) rhs = 0x7FFFFFFF; 330e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik return lhs < rhs; 331e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik } 332e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik }; 333e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik class Adder { 334e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik friend class EGLAttributeVector; 33515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EGLAttributeVector& v; 33615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EGLint attribute; 33715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik Adder(EGLAttributeVector& v, EGLint attribute) 33815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik : v(v), attribute(attribute) { 33915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 34015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik public: 34115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik void operator = (EGLint value) { 342b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (attribute != EGL_NONE) { 343b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik v.mList.add(Attribute(attribute), value); 344 } 345 } 346 operator EGLint () const { return v.mList[attribute]; } 347 }; 348public: 349 EGLAttributeVector() { 350 mList.add(Attribute(EGL_NONE), EGL_NONE); 351 } 352 void remove(EGLint attribute) { 353 if (attribute != EGL_NONE) { 354 mList.removeItem(Attribute(attribute)); 355 } 356 } 357 Adder operator [] (EGLint attribute) { 358 return Adder(*this, attribute); 359 } 360 EGLint operator [] (EGLint attribute) const { 361 return mList[attribute]; 362 } 363 // cast-operator to (EGLint const*) 364 operator EGLint const* () const { return &mList.keyAt(0).v; } 365}; 366 367 368static status_t selectEGLConfig(EGLDisplay display, EGLint format, 369 EGLint renderableType, EGLConfig* config) { 370 // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if 371 // it is to be used with WIFI displays 372 status_t err; 373 EGLint wantedAttribute; 374 EGLint wantedAttributeValue; 375 376 EGLAttributeVector attribs; 377 if (renderableType) { 378 attribs[EGL_RENDERABLE_TYPE] = renderableType; 379 attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE; 380 attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT|EGL_PBUFFER_BIT; 381 attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE; 382 attribs[EGL_RED_SIZE] = 8; 383 attribs[EGL_GREEN_SIZE] = 8; 384 attribs[EGL_BLUE_SIZE] = 8; 385 wantedAttribute = EGL_NONE; 386 wantedAttributeValue = EGL_NONE; 387 } else { 388 // if no renderable type specified, fallback to a simplified query 389 wantedAttribute = EGL_NATIVE_VISUAL_ID; 390 wantedAttributeValue = format; 391 } 392 393 err = selectConfigForAttribute(display, attribs, 394 wantedAttribute, wantedAttributeValue, config); 395 if (err == NO_ERROR) { 396 EGLint caveat; 397 if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat)) 398 ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!"); 399 } 400 401 return err; 402} 403 404EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) { 405 status_t err; 406 EGLConfig config; 407 408 // First try to get an ES2 config 409 err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config); 410 if (err != NO_ERROR) { 411 // If ES2 fails, try ES1 412 err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config); 413 if (err != NO_ERROR) { 414 // still didn't work, probably because we're on the emulator... 415 // try a simplified query 416 ALOGW("no suitable EGLConfig found, trying a simpler query"); 417 err = selectEGLConfig(display, format, 0, &config); 418 if (err != NO_ERROR) { 419 // this EGL is too lame for android 420 LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); 421 } 422 } 423 } 424 425 // print some debugging info 426 EGLint r,g,b,a; 427 eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); 428 eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); 429 eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b); 430 eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a); 431 ALOGI("EGL information:"); 432 ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); 433 ALOGI("version : %s", eglQueryString(display, EGL_VERSION)); 434 ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS)); 435 ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); 436 ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config); 437 438 return config; 439} 440 441 442void RenderEngine::primeCache() const { 443 // Getting the ProgramCache instance causes it to prime its shader cache, 444 // which is performed in its constructor 445 ProgramCache::getInstance(); 446} 447 448// --------------------------------------------------------------------------- 449}; // namespace android 450// --------------------------------------------------------------------------- 451