EglManager.cpp revision a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9
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 19d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reck#include "Caches.h" 20d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reck#include "Properties.h" 213b20251a355c88193c439f928a84ae69483fb488John Reck#include "RenderThread.h" 22d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reck#include "renderstate/RenderState.h" 236e6646c03788f198a9878763680c05342d7622f3Chris Craik#include "utils/StringUtils.h" 243b20251a355c88193c439f928a84ae69483fb488John Reck 2565fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <cutils/log.h> 2665fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik#include <cutils/properties.h> 275515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck#include <EGL/eglext.h> 2865fe5eeb19e2e15c8b1ee91e8a2dcf0c25e48ca6Chris Craik 29149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck#include <string> 30149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 313b20251a355c88193c439f928a84ae69483fb488John Reck#define GLES_VERSION 2 323b20251a355c88193c439f928a84ae69483fb488John Reck 335515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck#define WAIT_FOR_GPU_COMPLETION 0 345515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck 353b20251a355c88193c439f928a84ae69483fb488John Reck// Android-specific addition that is used to show when frames began in systrace 363b20251a355c88193c439f928a84ae69483fb488John ReckEGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface); 373b20251a355c88193c439f928a84ae69483fb488John Reck 383b20251a355c88193c439f928a84ae69483fb488John Recknamespace android { 393b20251a355c88193c439f928a84ae69483fb488John Recknamespace uirenderer { 403b20251a355c88193c439f928a84ae69483fb488John Recknamespace renderthread { 413b20251a355c88193c439f928a84ae69483fb488John Reck 423b20251a355c88193c439f928a84ae69483fb488John Reck#define ERROR_CASE(x) case x: return #x; 433b20251a355c88193c439f928a84ae69483fb488John Reckstatic const char* egl_error_str(EGLint error) { 443b20251a355c88193c439f928a84ae69483fb488John Reck switch (error) { 453b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_SUCCESS) 463b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_NOT_INITIALIZED) 473b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ACCESS) 483b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ALLOC) 493b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ATTRIBUTE) 503b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CONFIG) 513b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CONTEXT) 523b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CURRENT_SURFACE) 533b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_DISPLAY) 543b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_MATCH) 553b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_NATIVE_PIXMAP) 563b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_NATIVE_WINDOW) 573b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_PARAMETER) 583b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_SURFACE) 593b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_CONTEXT_LOST) 603b20251a355c88193c439f928a84ae69483fb488John Reck default: 613b20251a355c88193c439f928a84ae69483fb488John Reck return "Unknown error"; 623b20251a355c88193c439f928a84ae69483fb488John Reck } 633b20251a355c88193c439f928a84ae69483fb488John Reck} 643b20251a355c88193c439f928a84ae69483fb488John Reckstatic const char* egl_error_str() { 653b20251a355c88193c439f928a84ae69483fb488John Reck return egl_error_str(eglGetError()); 663b20251a355c88193c439f928a84ae69483fb488John Reck} 673b20251a355c88193c439f928a84ae69483fb488John Reck 68149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckstatic struct { 69149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck bool bufferAge = false; 70149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck bool setDamage = false; 71149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck} EglExtensions; 72149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 73149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckvoid Frame::map(const SkRect& in, EGLint* out) const { 74149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck /* The rectangles are specified relative to the bottom-left of the surface 75149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * and the x and y components of each rectangle specify the bottom-left 76149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * position of that rectangle. 77149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * 78149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * HWUI does everything with 0,0 being top-left, so need to map 79149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck * the rect 80149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck */ 81149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck SkIRect idirty; 82149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck in.roundOut(&idirty); 83149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck EGLint y = mHeight - (idirty.y() + idirty.height()); 84149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck // layout: {x, y, width, height} 85149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck out[0] = idirty.x(); 86149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck out[1] = y; 87149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck out[2] = idirty.width(); 88149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck out[3] = idirty.height(); 893b20251a355c88193c439f928a84ae69483fb488John Reck} 903b20251a355c88193c439f928a84ae69483fb488John Reck 913b20251a355c88193c439f928a84ae69483fb488John ReckEglManager::EglManager(RenderThread& thread) 923b20251a355c88193c439f928a84ae69483fb488John Reck : mRenderThread(thread) 933b20251a355c88193c439f928a84ae69483fb488John Reck , mEglDisplay(EGL_NO_DISPLAY) 94d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik , mEglConfig(nullptr) 953b20251a355c88193c439f928a84ae69483fb488John Reck , mEglContext(EGL_NO_CONTEXT) 963b20251a355c88193c439f928a84ae69483fb488John Reck , mPBufferSurface(EGL_NO_SURFACE) 973b20251a355c88193c439f928a84ae69483fb488John Reck , mCurrentSurface(EGL_NO_SURFACE) 98d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik , mAtlasMap(nullptr) 99d7db4d767246b41d44995acb93d03d220b53c748John Reck , mAtlasMapSize(0) { 1003b20251a355c88193c439f928a84ae69483fb488John Reck} 1013b20251a355c88193c439f928a84ae69483fb488John Reck 1023b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::initialize() { 1033b20251a355c88193c439f928a84ae69483fb488John Reck if (hasEglContext()) return; 1043b20251a355c88193c439f928a84ae69483fb488John Reck 105fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck ATRACE_NAME("Creating EGLContext"); 106fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck 1073b20251a355c88193c439f928a84ae69483fb488John Reck mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 1083b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, 1093b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str()); 1103b20251a355c88193c439f928a84ae69483fb488John Reck 1113b20251a355c88193c439f928a84ae69483fb488John Reck EGLint major, minor; 1123b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE, 1133b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str()); 1143b20251a355c88193c439f928a84ae69483fb488John Reck 1153b20251a355c88193c439f928a84ae69483fb488John Reck ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor); 1163b20251a355c88193c439f928a84ae69483fb488John Reck 117149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck initExtensions(); 118149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 119149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck // Now that extensions are loaded, pick a swap behavior 120149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (Properties::enablePartialUpdates) { 121149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (Properties::useBufferAge && EglExtensions.bufferAge) { 122149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck mSwapBehavior = SwapBehavior::BufferAge; 123149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } else { 124149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck mSwapBehavior = SwapBehavior::Preserved; 125149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 126149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 12713d1b4ab10fbee5e81a2ba1ac59cfae1e51d3ef0Season Li 128149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck loadConfig(); 1293b20251a355c88193c439f928a84ae69483fb488John Reck createContext(); 130d7db4d767246b41d44995acb93d03d220b53c748John Reck createPBufferSurface(); 131d7db4d767246b41d44995acb93d03d220b53c748John Reck makeCurrent(mPBufferSurface); 1323b20251a355c88193c439f928a84ae69483fb488John Reck mRenderThread.renderState().onGLContextCreated(); 1333b20251a355c88193c439f928a84ae69483fb488John Reck initAtlas(); 1343b20251a355c88193c439f928a84ae69483fb488John Reck} 1353b20251a355c88193c439f928a84ae69483fb488John Reck 136149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckvoid EglManager::initExtensions() { 1376e6646c03788f198a9878763680c05342d7622f3Chris Craik StringCollection extensions(eglQueryString(mEglDisplay, EGL_EXTENSIONS)); 1386e6646c03788f198a9878763680c05342d7622f3Chris Craik EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age"); 1396e6646c03788f198a9878763680c05342d7622f3Chris Craik EglExtensions.setDamage = extensions.has("EGL_KHR_partial_update"); 1403b20251a355c88193c439f928a84ae69483fb488John Reck} 1413b20251a355c88193c439f928a84ae69483fb488John Reck 142149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckbool EglManager::hasEglContext() { 143149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return mEglDisplay != EGL_NO_DISPLAY; 14413d1b4ab10fbee5e81a2ba1ac59cfae1e51d3ef0Season Li} 14513d1b4ab10fbee5e81a2ba1ac59cfae1e51d3ef0Season Li 146149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckvoid EglManager::loadConfig() { 147149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior)); 148149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck EGLint swapBehavior = (mSwapBehavior == SwapBehavior::Preserved) 149149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0; 1503b20251a355c88193c439f928a84ae69483fb488John Reck EGLint attribs[] = { 1513b20251a355c88193c439f928a84ae69483fb488John Reck EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 1523b20251a355c88193c439f928a84ae69483fb488John Reck EGL_RED_SIZE, 8, 1533b20251a355c88193c439f928a84ae69483fb488John Reck EGL_GREEN_SIZE, 8, 1543b20251a355c88193c439f928a84ae69483fb488John Reck EGL_BLUE_SIZE, 8, 1553b20251a355c88193c439f928a84ae69483fb488John Reck EGL_ALPHA_SIZE, 8, 1563b20251a355c88193c439f928a84ae69483fb488John Reck EGL_DEPTH_SIZE, 0, 1573b20251a355c88193c439f928a84ae69483fb488John Reck EGL_CONFIG_CAVEAT, EGL_NONE, 1583b20251a355c88193c439f928a84ae69483fb488John Reck EGL_STENCIL_SIZE, Stencil::getStencilSize(), 1593b20251a355c88193c439f928a84ae69483fb488John Reck EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior, 1603b20251a355c88193c439f928a84ae69483fb488John Reck EGL_NONE 1613b20251a355c88193c439f928a84ae69483fb488John Reck }; 1623b20251a355c88193c439f928a84ae69483fb488John Reck 1633b20251a355c88193c439f928a84ae69483fb488John Reck EGLint num_configs = 1; 1643b20251a355c88193c439f928a84ae69483fb488John Reck if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs) 1653b20251a355c88193c439f928a84ae69483fb488John Reck || num_configs != 1) { 166149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (mSwapBehavior == SwapBehavior::Preserved) { 1673b20251a355c88193c439f928a84ae69483fb488John Reck // Try again without dirty regions enabled 168149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without..."); 169149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck mSwapBehavior = SwapBehavior::Discard; 170149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck loadConfig(); 1713b20251a355c88193c439f928a84ae69483fb488John Reck } else { 172149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck // Failed to get a valid config 1733b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str()); 1743b20251a355c88193c439f928a84ae69483fb488John Reck } 1753b20251a355c88193c439f928a84ae69483fb488John Reck } 1763b20251a355c88193c439f928a84ae69483fb488John Reck} 1773b20251a355c88193c439f928a84ae69483fb488John Reck 1783b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::createContext() { 1793b20251a355c88193c439f928a84ae69483fb488John Reck EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE }; 1803b20251a355c88193c439f928a84ae69483fb488John Reck mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs); 1813b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, 1823b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to create context, error = %s", egl_error_str()); 1833b20251a355c88193c439f928a84ae69483fb488John Reck} 1843b20251a355c88193c439f928a84ae69483fb488John Reck 1853b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::setTextureAtlas(const sp<GraphicBuffer>& buffer, 1863b20251a355c88193c439f928a84ae69483fb488John Reck int64_t* map, size_t mapSize) { 1873b20251a355c88193c439f928a84ae69483fb488John Reck 1883b20251a355c88193c439f928a84ae69483fb488John Reck // Already initialized 1893b20251a355c88193c439f928a84ae69483fb488John Reck if (mAtlasBuffer.get()) { 1903b20251a355c88193c439f928a84ae69483fb488John Reck ALOGW("Multiple calls to setTextureAtlas!"); 1913b20251a355c88193c439f928a84ae69483fb488John Reck delete map; 1923b20251a355c88193c439f928a84ae69483fb488John Reck return; 1933b20251a355c88193c439f928a84ae69483fb488John Reck } 1943b20251a355c88193c439f928a84ae69483fb488John Reck 1953b20251a355c88193c439f928a84ae69483fb488John Reck mAtlasBuffer = buffer; 1963b20251a355c88193c439f928a84ae69483fb488John Reck mAtlasMap = map; 1973b20251a355c88193c439f928a84ae69483fb488John Reck mAtlasMapSize = mapSize; 1983b20251a355c88193c439f928a84ae69483fb488John Reck 1993b20251a355c88193c439f928a84ae69483fb488John Reck if (hasEglContext()) { 2003b20251a355c88193c439f928a84ae69483fb488John Reck initAtlas(); 2013b20251a355c88193c439f928a84ae69483fb488John Reck } 2023b20251a355c88193c439f928a84ae69483fb488John Reck} 2033b20251a355c88193c439f928a84ae69483fb488John Reck 2043b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::initAtlas() { 2053b20251a355c88193c439f928a84ae69483fb488John Reck if (mAtlasBuffer.get()) { 206ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mRenderThread.renderState().assetAtlas().init(mAtlasBuffer, 207ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mAtlasMap, mAtlasMapSize); 2083b20251a355c88193c439f928a84ae69483fb488John Reck } 2093b20251a355c88193c439f928a84ae69483fb488John Reck} 2103b20251a355c88193c439f928a84ae69483fb488John Reck 211d7db4d767246b41d44995acb93d03d220b53c748John Reckvoid EglManager::createPBufferSurface() { 2123b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, 2133b20251a355c88193c439f928a84ae69483fb488John Reck "usePBufferSurface() called on uninitialized GlobalContext!"); 2143b20251a355c88193c439f928a84ae69483fb488John Reck 2153b20251a355c88193c439f928a84ae69483fb488John Reck if (mPBufferSurface == EGL_NO_SURFACE) { 2163b20251a355c88193c439f928a84ae69483fb488John Reck EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; 2173b20251a355c88193c439f928a84ae69483fb488John Reck mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs); 2183b20251a355c88193c439f928a84ae69483fb488John Reck } 2193b20251a355c88193c439f928a84ae69483fb488John Reck} 2203b20251a355c88193c439f928a84ae69483fb488John Reck 2213b20251a355c88193c439f928a84ae69483fb488John ReckEGLSurface EglManager::createSurface(EGLNativeWindowType window) { 2223b20251a355c88193c439f928a84ae69483fb488John Reck initialize(); 223d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, nullptr); 2243b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, 2253b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to create EGLSurface for window %p, eglErr = %s", 2263b20251a355c88193c439f928a84ae69483fb488John Reck (void*) window, egl_error_str()); 2273b20251a355c88193c439f928a84ae69483fb488John Reck return surface; 2283b20251a355c88193c439f928a84ae69483fb488John Reck} 2293b20251a355c88193c439f928a84ae69483fb488John Reck 2303b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::destroySurface(EGLSurface surface) { 2313b20251a355c88193c439f928a84ae69483fb488John Reck if (isCurrent(surface)) { 2323b20251a355c88193c439f928a84ae69483fb488John Reck makeCurrent(EGL_NO_SURFACE); 2333b20251a355c88193c439f928a84ae69483fb488John Reck } 2343b20251a355c88193c439f928a84ae69483fb488John Reck if (!eglDestroySurface(mEglDisplay, surface)) { 2353b20251a355c88193c439f928a84ae69483fb488John Reck ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str()); 2363b20251a355c88193c439f928a84ae69483fb488John Reck } 2373b20251a355c88193c439f928a84ae69483fb488John Reck} 2383b20251a355c88193c439f928a84ae69483fb488John Reck 2393b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::destroy() { 2403b20251a355c88193c439f928a84ae69483fb488John Reck if (mEglDisplay == EGL_NO_DISPLAY) return; 2413b20251a355c88193c439f928a84ae69483fb488John Reck 2421d4774233304c484673e2af2c1de2ab41021c979Chris Craik mRenderThread.renderState().onGLContextDestroyed(); 2433b20251a355c88193c439f928a84ae69483fb488John Reck eglDestroyContext(mEglDisplay, mEglContext); 2443b20251a355c88193c439f928a84ae69483fb488John Reck eglDestroySurface(mEglDisplay, mPBufferSurface); 2453b20251a355c88193c439f928a84ae69483fb488John Reck eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 2463b20251a355c88193c439f928a84ae69483fb488John Reck eglTerminate(mEglDisplay); 2473b20251a355c88193c439f928a84ae69483fb488John Reck eglReleaseThread(); 2483b20251a355c88193c439f928a84ae69483fb488John Reck 2493b20251a355c88193c439f928a84ae69483fb488John Reck mEglDisplay = EGL_NO_DISPLAY; 2503b20251a355c88193c439f928a84ae69483fb488John Reck mEglContext = EGL_NO_CONTEXT; 2513b20251a355c88193c439f928a84ae69483fb488John Reck mPBufferSurface = EGL_NO_SURFACE; 2523b20251a355c88193c439f928a84ae69483fb488John Reck mCurrentSurface = EGL_NO_SURFACE; 2533b20251a355c88193c439f928a84ae69483fb488John Reck} 2543b20251a355c88193c439f928a84ae69483fb488John Reck 255f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reckbool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) { 2563b20251a355c88193c439f928a84ae69483fb488John Reck if (isCurrent(surface)) return false; 2573b20251a355c88193c439f928a84ae69483fb488John Reck 2583b20251a355c88193c439f928a84ae69483fb488John Reck if (surface == EGL_NO_SURFACE) { 259d7db4d767246b41d44995acb93d03d220b53c748John Reck // Ensure we always have a valid surface & context 260d7db4d767246b41d44995acb93d03d220b53c748John Reck surface = mPBufferSurface; 261d7db4d767246b41d44995acb93d03d220b53c748John Reck } 262d7db4d767246b41d44995acb93d03d220b53c748John Reck if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) { 263f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck if (errOut) { 264f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck *errOut = eglGetError(); 265f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck ALOGW("Failed to make current on surface %p, error=%s", 266f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck (void*)surface, egl_error_str(*errOut)); 267f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck } else { 268f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", 269f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck (void*)surface, egl_error_str()); 270f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck } 2713b20251a355c88193c439f928a84ae69483fb488John Reck } 2723b20251a355c88193c439f928a84ae69483fb488John Reck mCurrentSurface = surface; 2733b20251a355c88193c439f928a84ae69483fb488John Reck return true; 2743b20251a355c88193c439f928a84ae69483fb488John Reck} 2753b20251a355c88193c439f928a84ae69483fb488John Reck 276149173d28c0843aba86b0810ce75b34be6a0d08fJohn ReckEGLint EglManager::queryBufferAge(EGLSurface surface) { 277149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck switch (mSwapBehavior) { 278149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck case SwapBehavior::Discard: 279149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return 0; 280149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck case SwapBehavior::Preserved: 281149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return 1; 282149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck case SwapBehavior::BufferAge: 283149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck EGLint bufferAge; 284149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck eglQuerySurface(mEglDisplay, surface, EGL_BUFFER_AGE_EXT, &bufferAge); 285149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return bufferAge; 286149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 287149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return 0; 288149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck} 289149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 290149173d28c0843aba86b0810ce75b34be6a0d08fJohn ReckFrame EglManager::beginFrame(EGLSurface surface) { 2913b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, 2923b20251a355c88193c439f928a84ae69483fb488John Reck "Tried to beginFrame on EGL_NO_SURFACE!"); 2933b20251a355c88193c439f928a84ae69483fb488John Reck makeCurrent(surface); 294149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck Frame frame; 295149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck frame.mSurface = surface; 296149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, &frame.mWidth); 297149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, &frame.mHeight); 298149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck frame.mBufferAge = queryBufferAge(surface); 2993b20251a355c88193c439f928a84ae69483fb488John Reck eglBeginFrame(mEglDisplay, surface); 300149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return frame; 301149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck} 302149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 303149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckvoid EglManager::damageFrame(const Frame& frame, const SkRect& dirty) { 304149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck#ifdef EGL_KHR_partial_update 305149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (EglExtensions.setDamage && mSwapBehavior == SwapBehavior::BufferAge) { 306149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck EGLint rects[4]; 307149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck frame.map(dirty, rects); 308149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (!eglSetDamageRegionKHR(mEglDisplay, frame.mSurface, rects, 1)) { 309149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck LOG_ALWAYS_FATAL("Failed to set damage region on surface %p, error=%s", 310149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck (void*)frame.mSurface, egl_error_str()); 311149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 312149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 313149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck#endif 3143b20251a355c88193c439f928a84ae69483fb488John Reck} 3153b20251a355c88193c439f928a84ae69483fb488John Reck 316149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckbool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) { 3175515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck 3185515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck#if WAIT_FOR_GPU_COMPLETION 3195515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck { 3205515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck ATRACE_NAME("Finishing GPU work"); 3215515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck fence(); 3225515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck } 3235515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck#endif 3245515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck 325a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9John Reck EGLint rects[4]; 326a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9John Reck frame.map(screenDirty, rects); 327a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9John Reck eglSwapBuffersWithDamageKHR(mEglDisplay, frame.mSurface, rects, 328a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9John Reck screenDirty.isEmpty() ? 0 : 1); 329d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reck 3303b20251a355c88193c439f928a84ae69483fb488John Reck EGLint err = eglGetError(); 3312cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck if (CC_LIKELY(err == EGL_SUCCESS)) { 3322cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return true; 3332cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck } 3342cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck if (err == EGL_BAD_SURFACE) { 3352cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // For some reason our surface was destroyed out from under us 3362cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // This really shouldn't happen, but if it does we can recover easily 3372cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // by just not trying to use the surface anymore 338149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ALOGW("swapBuffers encountered EGL_BAD_SURFACE on %p, halting rendering...", 339149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck frame.mSurface); 3402cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return false; 3412cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck } 3422cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering", 3432cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck err, egl_error_str(err)); 3442cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // Impossible to hit this, but the compiler doesn't know that 3452cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return false; 3463b20251a355c88193c439f928a84ae69483fb488John Reck} 3473b20251a355c88193c439f928a84ae69483fb488John Reck 3485515637540bedd8fc9a1a6e46a4b512dd45520a5John Reckvoid EglManager::fence() { 3495515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL); 3505515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck eglClientWaitSyncKHR(mEglDisplay, fence, 3515515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); 3525515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck eglDestroySyncKHR(mEglDisplay, fence); 3535515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck} 3545515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck 3551125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reckbool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) { 356149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (mSwapBehavior != SwapBehavior::Preserved) return false; 357149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 358149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck bool preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, 359149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED); 360149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (!preserved) { 361149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", 362149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck (void*) surface, egl_error_str()); 3631125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck // Maybe it's already set? 3641125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck EGLint swapBehavior; 3651125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) { 3661125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck preserved = (swapBehavior == EGL_BUFFER_PRESERVED); 3671125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck } else { 3681125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", 3691125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck (void*) surface, egl_error_str()); 3701125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck } 3713b20251a355c88193c439f928a84ae69483fb488John Reck } 3721125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck 3731125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck return preserved; 3743b20251a355c88193c439f928a84ae69483fb488John Reck} 3753b20251a355c88193c439f928a84ae69483fb488John Reck 3763b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace renderthread */ 3773b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace uirenderer */ 3783b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace android */ 379