EglManager.cpp revision fbc8df03e498baf47ff1a5e05e182f1bcd60c770
13b20251a355c88193c439f928a84ae69483fb488John Reck/* 23b20251a355c88193c439f928a84ae69483fb488John Reck * Copyright (C) 2014 The Android Open Source Project 33b20251a355c88193c439f928a84ae69483fb488John Reck * 43b20251a355c88193c439f928a84ae69483fb488John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 53b20251a355c88193c439f928a84ae69483fb488John Reck * you may not use this file except in compliance with the License. 63b20251a355c88193c439f928a84ae69483fb488John Reck * You may obtain a copy of the License at 73b20251a355c88193c439f928a84ae69483fb488John Reck * 83b20251a355c88193c439f928a84ae69483fb488John Reck * http://www.apache.org/licenses/LICENSE-2.0 93b20251a355c88193c439f928a84ae69483fb488John Reck * 103b20251a355c88193c439f928a84ae69483fb488John Reck * Unless required by applicable law or agreed to in writing, software 113b20251a355c88193c439f928a84ae69483fb488John Reck * distributed under the License is distributed on an "AS IS" BASIS, 123b20251a355c88193c439f928a84ae69483fb488John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133b20251a355c88193c439f928a84ae69483fb488John Reck * See the License for the specific language governing permissions and 143b20251a355c88193c439f928a84ae69483fb488John Reck * limitations under the License. 153b20251a355c88193c439f928a84ae69483fb488John Reck */ 163b20251a355c88193c439f928a84ae69483fb488John Reck 173b20251a355c88193c439f928a84ae69483fb488John Reck#include "EglManager.h" 183b20251a355c88193c439f928a84ae69483fb488John Reck 193b20251a355c88193c439f928a84ae69483fb488John Reck#include <cutils/log.h> 203b20251a355c88193c439f928a84ae69483fb488John Reck#include <cutils/properties.h> 213b20251a355c88193c439f928a84ae69483fb488John Reck 223b20251a355c88193c439f928a84ae69483fb488John Reck#include "../RenderState.h" 233b20251a355c88193c439f928a84ae69483fb488John Reck#include "RenderThread.h" 243b20251a355c88193c439f928a84ae69483fb488John Reck 253b20251a355c88193c439f928a84ae69483fb488John Reck#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions" 263b20251a355c88193c439f928a84ae69483fb488John Reck#define GLES_VERSION 2 273b20251a355c88193c439f928a84ae69483fb488John Reck 283b20251a355c88193c439f928a84ae69483fb488John Reck// Android-specific addition that is used to show when frames began in systrace 293b20251a355c88193c439f928a84ae69483fb488John ReckEGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface); 303b20251a355c88193c439f928a84ae69483fb488John Reck 313b20251a355c88193c439f928a84ae69483fb488John Recknamespace android { 323b20251a355c88193c439f928a84ae69483fb488John Recknamespace uirenderer { 333b20251a355c88193c439f928a84ae69483fb488John Recknamespace renderthread { 343b20251a355c88193c439f928a84ae69483fb488John Reck 353b20251a355c88193c439f928a84ae69483fb488John Reck#define ERROR_CASE(x) case x: return #x; 363b20251a355c88193c439f928a84ae69483fb488John Reckstatic const char* egl_error_str(EGLint error) { 373b20251a355c88193c439f928a84ae69483fb488John Reck switch (error) { 383b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_SUCCESS) 393b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_NOT_INITIALIZED) 403b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ACCESS) 413b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ALLOC) 423b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ATTRIBUTE) 433b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CONFIG) 443b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CONTEXT) 453b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CURRENT_SURFACE) 463b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_DISPLAY) 473b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_MATCH) 483b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_NATIVE_PIXMAP) 493b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_NATIVE_WINDOW) 503b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_PARAMETER) 513b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_SURFACE) 523b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_CONTEXT_LOST) 533b20251a355c88193c439f928a84ae69483fb488John Reck default: 543b20251a355c88193c439f928a84ae69483fb488John Reck return "Unknown error"; 553b20251a355c88193c439f928a84ae69483fb488John Reck } 563b20251a355c88193c439f928a84ae69483fb488John Reck} 573b20251a355c88193c439f928a84ae69483fb488John Reckstatic const char* egl_error_str() { 583b20251a355c88193c439f928a84ae69483fb488John Reck return egl_error_str(eglGetError()); 593b20251a355c88193c439f928a84ae69483fb488John Reck} 603b20251a355c88193c439f928a84ae69483fb488John Reck 613b20251a355c88193c439f928a84ae69483fb488John Reckstatic bool load_dirty_regions_property() { 623b20251a355c88193c439f928a84ae69483fb488John Reck char buf[PROPERTY_VALUE_MAX]; 633b20251a355c88193c439f928a84ae69483fb488John Reck int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true"); 643b20251a355c88193c439f928a84ae69483fb488John Reck return !strncasecmp("true", buf, len); 653b20251a355c88193c439f928a84ae69483fb488John Reck} 663b20251a355c88193c439f928a84ae69483fb488John Reck 673b20251a355c88193c439f928a84ae69483fb488John ReckEglManager::EglManager(RenderThread& thread) 683b20251a355c88193c439f928a84ae69483fb488John Reck : mRenderThread(thread) 693b20251a355c88193c439f928a84ae69483fb488John Reck , mEglDisplay(EGL_NO_DISPLAY) 703b20251a355c88193c439f928a84ae69483fb488John Reck , mEglConfig(0) 713b20251a355c88193c439f928a84ae69483fb488John Reck , mEglContext(EGL_NO_CONTEXT) 723b20251a355c88193c439f928a84ae69483fb488John Reck , mPBufferSurface(EGL_NO_SURFACE) 731125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck , mAllowPreserveBuffer(load_dirty_regions_property()) 743b20251a355c88193c439f928a84ae69483fb488John Reck , mCurrentSurface(EGL_NO_SURFACE) 753b20251a355c88193c439f928a84ae69483fb488John Reck , mAtlasMap(NULL) 760e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck , mAtlasMapSize(0) 770e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck , mInFrame(false) { 781125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck mCanSetPreserveBuffer = mAllowPreserveBuffer; 791125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck ALOGD("Use EGL_SWAP_BEHAVIOR_PRESERVED: %s", mAllowPreserveBuffer ? "true" : "false"); 803b20251a355c88193c439f928a84ae69483fb488John Reck} 813b20251a355c88193c439f928a84ae69483fb488John Reck 823b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::initialize() { 833b20251a355c88193c439f928a84ae69483fb488John Reck if (hasEglContext()) return; 843b20251a355c88193c439f928a84ae69483fb488John Reck 85fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck ATRACE_NAME("Creating EGLContext"); 86fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck 873b20251a355c88193c439f928a84ae69483fb488John Reck mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 883b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, 893b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str()); 903b20251a355c88193c439f928a84ae69483fb488John Reck 913b20251a355c88193c439f928a84ae69483fb488John Reck EGLint major, minor; 923b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE, 933b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str()); 943b20251a355c88193c439f928a84ae69483fb488John Reck 953b20251a355c88193c439f928a84ae69483fb488John Reck ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor); 963b20251a355c88193c439f928a84ae69483fb488John Reck 973b20251a355c88193c439f928a84ae69483fb488John Reck loadConfig(); 983b20251a355c88193c439f928a84ae69483fb488John Reck createContext(); 993b20251a355c88193c439f928a84ae69483fb488John Reck usePBufferSurface(); 1003b20251a355c88193c439f928a84ae69483fb488John Reck mRenderThread.renderState().onGLContextCreated(); 1013b20251a355c88193c439f928a84ae69483fb488John Reck initAtlas(); 1023b20251a355c88193c439f928a84ae69483fb488John Reck} 1033b20251a355c88193c439f928a84ae69483fb488John Reck 1043b20251a355c88193c439f928a84ae69483fb488John Reckbool EglManager::hasEglContext() { 1053b20251a355c88193c439f928a84ae69483fb488John Reck return mEglDisplay != EGL_NO_DISPLAY; 1063b20251a355c88193c439f928a84ae69483fb488John Reck} 1073b20251a355c88193c439f928a84ae69483fb488John Reck 1083b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::requireGlContext() { 1093b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context"); 1103b20251a355c88193c439f928a84ae69483fb488John Reck 1110e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck if (!mInFrame) { 1120e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck // We can't be certain about the state of the current surface (whether 1130e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck // or not it is destroyed, for example), so err on the side of using 1140e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck // the pbuffer surface which we fully control 1150e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck usePBufferSurface(); 1160e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck } 1173b20251a355c88193c439f928a84ae69483fb488John Reck} 1183b20251a355c88193c439f928a84ae69483fb488John Reck 1193b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::loadConfig() { 1201125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck EGLint swapBehavior = mCanSetPreserveBuffer ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0; 1213b20251a355c88193c439f928a84ae69483fb488John Reck EGLint attribs[] = { 1223b20251a355c88193c439f928a84ae69483fb488John Reck EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 1233b20251a355c88193c439f928a84ae69483fb488John Reck EGL_RED_SIZE, 8, 1243b20251a355c88193c439f928a84ae69483fb488John Reck EGL_GREEN_SIZE, 8, 1253b20251a355c88193c439f928a84ae69483fb488John Reck EGL_BLUE_SIZE, 8, 1263b20251a355c88193c439f928a84ae69483fb488John Reck EGL_ALPHA_SIZE, 8, 1273b20251a355c88193c439f928a84ae69483fb488John Reck EGL_DEPTH_SIZE, 0, 1283b20251a355c88193c439f928a84ae69483fb488John Reck EGL_CONFIG_CAVEAT, EGL_NONE, 1293b20251a355c88193c439f928a84ae69483fb488John Reck EGL_STENCIL_SIZE, Stencil::getStencilSize(), 1303b20251a355c88193c439f928a84ae69483fb488John Reck EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior, 1313b20251a355c88193c439f928a84ae69483fb488John Reck EGL_NONE 1323b20251a355c88193c439f928a84ae69483fb488John Reck }; 1333b20251a355c88193c439f928a84ae69483fb488John Reck 1343b20251a355c88193c439f928a84ae69483fb488John Reck EGLint num_configs = 1; 1353b20251a355c88193c439f928a84ae69483fb488John Reck if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs) 1363b20251a355c88193c439f928a84ae69483fb488John Reck || num_configs != 1) { 1373b20251a355c88193c439f928a84ae69483fb488John Reck // Failed to get a valid config 1381125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck if (mCanSetPreserveBuffer) { 1393b20251a355c88193c439f928a84ae69483fb488John Reck ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without..."); 1403b20251a355c88193c439f928a84ae69483fb488John Reck // Try again without dirty regions enabled 1411125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck mCanSetPreserveBuffer = false; 1423b20251a355c88193c439f928a84ae69483fb488John Reck loadConfig(); 1433b20251a355c88193c439f928a84ae69483fb488John Reck } else { 1443b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str()); 1453b20251a355c88193c439f928a84ae69483fb488John Reck } 1463b20251a355c88193c439f928a84ae69483fb488John Reck } 1473b20251a355c88193c439f928a84ae69483fb488John Reck} 1483b20251a355c88193c439f928a84ae69483fb488John Reck 1493b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::createContext() { 1503b20251a355c88193c439f928a84ae69483fb488John Reck EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE }; 1513b20251a355c88193c439f928a84ae69483fb488John Reck mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs); 1523b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, 1533b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to create context, error = %s", egl_error_str()); 1543b20251a355c88193c439f928a84ae69483fb488John Reck} 1553b20251a355c88193c439f928a84ae69483fb488John Reck 1563b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::setTextureAtlas(const sp<GraphicBuffer>& buffer, 1573b20251a355c88193c439f928a84ae69483fb488John Reck int64_t* map, size_t mapSize) { 1583b20251a355c88193c439f928a84ae69483fb488John Reck 1593b20251a355c88193c439f928a84ae69483fb488John Reck // Already initialized 1603b20251a355c88193c439f928a84ae69483fb488John Reck if (mAtlasBuffer.get()) { 1613b20251a355c88193c439f928a84ae69483fb488John Reck ALOGW("Multiple calls to setTextureAtlas!"); 1623b20251a355c88193c439f928a84ae69483fb488John Reck delete map; 1633b20251a355c88193c439f928a84ae69483fb488John Reck return; 1643b20251a355c88193c439f928a84ae69483fb488John Reck } 1653b20251a355c88193c439f928a84ae69483fb488John Reck 1663b20251a355c88193c439f928a84ae69483fb488John Reck mAtlasBuffer = buffer; 1673b20251a355c88193c439f928a84ae69483fb488John Reck mAtlasMap = map; 1683b20251a355c88193c439f928a84ae69483fb488John Reck mAtlasMapSize = mapSize; 1693b20251a355c88193c439f928a84ae69483fb488John Reck 1703b20251a355c88193c439f928a84ae69483fb488John Reck if (hasEglContext()) { 1713b20251a355c88193c439f928a84ae69483fb488John Reck usePBufferSurface(); 1723b20251a355c88193c439f928a84ae69483fb488John Reck initAtlas(); 1733b20251a355c88193c439f928a84ae69483fb488John Reck } 1743b20251a355c88193c439f928a84ae69483fb488John Reck} 1753b20251a355c88193c439f928a84ae69483fb488John Reck 1763b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::initAtlas() { 1773b20251a355c88193c439f928a84ae69483fb488John Reck if (mAtlasBuffer.get()) { 1783b20251a355c88193c439f928a84ae69483fb488John Reck Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize); 1793b20251a355c88193c439f928a84ae69483fb488John Reck } 1803b20251a355c88193c439f928a84ae69483fb488John Reck} 1813b20251a355c88193c439f928a84ae69483fb488John Reck 1823b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::usePBufferSurface() { 1833b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, 1843b20251a355c88193c439f928a84ae69483fb488John Reck "usePBufferSurface() called on uninitialized GlobalContext!"); 1853b20251a355c88193c439f928a84ae69483fb488John Reck 1863b20251a355c88193c439f928a84ae69483fb488John Reck if (mPBufferSurface == EGL_NO_SURFACE) { 1873b20251a355c88193c439f928a84ae69483fb488John Reck EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; 1883b20251a355c88193c439f928a84ae69483fb488John Reck mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs); 1893b20251a355c88193c439f928a84ae69483fb488John Reck } 1903b20251a355c88193c439f928a84ae69483fb488John Reck makeCurrent(mPBufferSurface); 1913b20251a355c88193c439f928a84ae69483fb488John Reck} 1923b20251a355c88193c439f928a84ae69483fb488John Reck 1933b20251a355c88193c439f928a84ae69483fb488John ReckEGLSurface EglManager::createSurface(EGLNativeWindowType window) { 1943b20251a355c88193c439f928a84ae69483fb488John Reck initialize(); 1953b20251a355c88193c439f928a84ae69483fb488John Reck EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL); 1963b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, 1973b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to create EGLSurface for window %p, eglErr = %s", 1983b20251a355c88193c439f928a84ae69483fb488John Reck (void*) window, egl_error_str()); 1993b20251a355c88193c439f928a84ae69483fb488John Reck return surface; 2003b20251a355c88193c439f928a84ae69483fb488John Reck} 2013b20251a355c88193c439f928a84ae69483fb488John Reck 2023b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::destroySurface(EGLSurface surface) { 2033b20251a355c88193c439f928a84ae69483fb488John Reck if (isCurrent(surface)) { 2043b20251a355c88193c439f928a84ae69483fb488John Reck makeCurrent(EGL_NO_SURFACE); 2053b20251a355c88193c439f928a84ae69483fb488John Reck } 2063b20251a355c88193c439f928a84ae69483fb488John Reck if (!eglDestroySurface(mEglDisplay, surface)) { 2073b20251a355c88193c439f928a84ae69483fb488John Reck ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str()); 2083b20251a355c88193c439f928a84ae69483fb488John Reck } 2093b20251a355c88193c439f928a84ae69483fb488John Reck} 2103b20251a355c88193c439f928a84ae69483fb488John Reck 2113b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::destroy() { 2123b20251a355c88193c439f928a84ae69483fb488John Reck if (mEglDisplay == EGL_NO_DISPLAY) return; 2133b20251a355c88193c439f928a84ae69483fb488John Reck 2143b20251a355c88193c439f928a84ae69483fb488John Reck usePBufferSurface(); 2153b20251a355c88193c439f928a84ae69483fb488John Reck if (Caches::hasInstance()) { 2163b20251a355c88193c439f928a84ae69483fb488John Reck Caches::getInstance().terminate(); 2173b20251a355c88193c439f928a84ae69483fb488John Reck } 2183b20251a355c88193c439f928a84ae69483fb488John Reck 2191d4774233304c484673e2af2c1de2ab41021c979Chris Craik mRenderThread.renderState().onGLContextDestroyed(); 2203b20251a355c88193c439f928a84ae69483fb488John Reck eglDestroyContext(mEglDisplay, mEglContext); 2213b20251a355c88193c439f928a84ae69483fb488John Reck eglDestroySurface(mEglDisplay, mPBufferSurface); 2223b20251a355c88193c439f928a84ae69483fb488John Reck eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 2233b20251a355c88193c439f928a84ae69483fb488John Reck eglTerminate(mEglDisplay); 2243b20251a355c88193c439f928a84ae69483fb488John Reck eglReleaseThread(); 2253b20251a355c88193c439f928a84ae69483fb488John Reck 2263b20251a355c88193c439f928a84ae69483fb488John Reck mEglDisplay = EGL_NO_DISPLAY; 2273b20251a355c88193c439f928a84ae69483fb488John Reck mEglContext = EGL_NO_CONTEXT; 2283b20251a355c88193c439f928a84ae69483fb488John Reck mPBufferSurface = EGL_NO_SURFACE; 2293b20251a355c88193c439f928a84ae69483fb488John Reck mCurrentSurface = EGL_NO_SURFACE; 2303b20251a355c88193c439f928a84ae69483fb488John Reck} 2313b20251a355c88193c439f928a84ae69483fb488John Reck 2323b20251a355c88193c439f928a84ae69483fb488John Reckbool EglManager::makeCurrent(EGLSurface surface) { 2333b20251a355c88193c439f928a84ae69483fb488John Reck if (isCurrent(surface)) return false; 2343b20251a355c88193c439f928a84ae69483fb488John Reck 2353b20251a355c88193c439f928a84ae69483fb488John Reck if (surface == EGL_NO_SURFACE) { 2363b20251a355c88193c439f928a84ae69483fb488John Reck // If we are setting EGL_NO_SURFACE we don't care about any of the potential 2373b20251a355c88193c439f928a84ae69483fb488John Reck // return errors, which would only happen if mEglDisplay had already been 2383b20251a355c88193c439f928a84ae69483fb488John Reck // destroyed in which case the current context is already NO_CONTEXT 2393b20251a355c88193c439f928a84ae69483fb488John Reck eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 2403b20251a355c88193c439f928a84ae69483fb488John Reck } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) { 2413b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", 2423b20251a355c88193c439f928a84ae69483fb488John Reck (void*)surface, egl_error_str()); 2433b20251a355c88193c439f928a84ae69483fb488John Reck } 2443b20251a355c88193c439f928a84ae69483fb488John Reck mCurrentSurface = surface; 2453b20251a355c88193c439f928a84ae69483fb488John Reck return true; 2463b20251a355c88193c439f928a84ae69483fb488John Reck} 2473b20251a355c88193c439f928a84ae69483fb488John Reck 2483b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) { 2493b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, 2503b20251a355c88193c439f928a84ae69483fb488John Reck "Tried to beginFrame on EGL_NO_SURFACE!"); 2513b20251a355c88193c439f928a84ae69483fb488John Reck makeCurrent(surface); 2523b20251a355c88193c439f928a84ae69483fb488John Reck if (width) { 2533b20251a355c88193c439f928a84ae69483fb488John Reck eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width); 2543b20251a355c88193c439f928a84ae69483fb488John Reck } 2553b20251a355c88193c439f928a84ae69483fb488John Reck if (height) { 2563b20251a355c88193c439f928a84ae69483fb488John Reck eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); 2573b20251a355c88193c439f928a84ae69483fb488John Reck } 2583b20251a355c88193c439f928a84ae69483fb488John Reck eglBeginFrame(mEglDisplay, surface); 2590e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck mInFrame = true; 2603b20251a355c88193c439f928a84ae69483fb488John Reck} 2613b20251a355c88193c439f928a84ae69483fb488John Reck 2622cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reckbool EglManager::swapBuffers(EGLSurface surface) { 2630e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck mInFrame = false; 2643b20251a355c88193c439f928a84ae69483fb488John Reck eglSwapBuffers(mEglDisplay, surface); 2653b20251a355c88193c439f928a84ae69483fb488John Reck EGLint err = eglGetError(); 2662cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck if (CC_LIKELY(err == EGL_SUCCESS)) { 2672cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return true; 2682cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck } 2692cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck if (err == EGL_BAD_SURFACE) { 2702cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // For some reason our surface was destroyed out from under us 2712cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // This really shouldn't happen, but if it does we can recover easily 2722cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // by just not trying to use the surface anymore 2732cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck ALOGW("swapBuffers encountered EGL_BAD_SURFACE on %p, halting rendering...", surface); 2742cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return false; 2752cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck } 2762cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering", 2772cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck err, egl_error_str(err)); 2782cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // Impossible to hit this, but the compiler doesn't know that 2792cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return false; 2803b20251a355c88193c439f928a84ae69483fb488John Reck} 2813b20251a355c88193c439f928a84ae69483fb488John Reck 2820e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reckvoid EglManager::cancelFrame() { 2830e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck mInFrame = false; 2840e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck} 2850e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck 2861125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reckbool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) { 2871125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck if (CC_UNLIKELY(!mAllowPreserveBuffer)) return false; 2883b20251a355c88193c439f928a84ae69483fb488John Reck 2891125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck bool preserved = false; 2901125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck if (mCanSetPreserveBuffer) { 2911125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, 2921125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED); 2931125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck if (CC_UNLIKELY(!preserved)) { 2943b20251a355c88193c439f928a84ae69483fb488John Reck ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", 2953b20251a355c88193c439f928a84ae69483fb488John Reck (void*) surface, egl_error_str()); 2963b20251a355c88193c439f928a84ae69483fb488John Reck } 2973b20251a355c88193c439f928a84ae69483fb488John Reck } 2981125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck if (CC_UNLIKELY(!preserved)) { 2991125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck // Maybe it's already set? 3001125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck EGLint swapBehavior; 3011125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) { 3021125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck preserved = (swapBehavior == EGL_BUFFER_PRESERVED); 3031125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck } else { 3041125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", 3051125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck (void*) surface, egl_error_str()); 3061125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck } 3073b20251a355c88193c439f928a84ae69483fb488John Reck } 3081125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck 3091125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck return preserved; 3103b20251a355c88193c439f928a84ae69483fb488John Reck} 3113b20251a355c88193c439f928a84ae69483fb488John Reck 3123b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace renderthread */ 3133b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace uirenderer */ 3143b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace android */ 315