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 1996bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn#include <string> 2096bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn 2196bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn#include "utils/StringUtils.h" 2296bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn#include <cutils/properties.h> 2396bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn#include <log/log.h> 2496bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn 25d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reck#include "Caches.h" 26704bed0da7cc75d0c517d425445de70ceb58060bJohn Reck#include "DeviceInfo.h" 27cd55852fcd840f7f4c4d7a0a7253a2995c77afa2Greg Daniel#include "Frame.h" 28d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reck#include "Properties.h" 293b20251a355c88193c439f928a84ae69483fb488John Reck#include "RenderThread.h" 30d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reck#include "renderstate/RenderState.h" 31173215d1b20b70908a9d1807f1372bd95b7ad5f1Mark Salyzyn#include "Texture.h" 32173215d1b20b70908a9d1807f1372bd95b7ad5f1Mark Salyzyn 335515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck#include <EGL/eglext.h> 3498f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger#include <GrContextOptions.h> 3598f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger#include <gl/GrGLInterface.h> 36149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 377e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger#ifdef HWUI_GLES_WRAP_ENABLED 387e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger#include "debug/GlesDriver.h" 397e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger#endif 407e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger 413b20251a355c88193c439f928a84ae69483fb488John Reck#define GLES_VERSION 2 423b20251a355c88193c439f928a84ae69483fb488John Reck 433b20251a355c88193c439f928a84ae69483fb488John Reck// Android-specific addition that is used to show when frames began in systrace 443b20251a355c88193c439f928a84ae69483fb488John ReckEGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface); 453b20251a355c88193c439f928a84ae69483fb488John Reck 463b20251a355c88193c439f928a84ae69483fb488John Recknamespace android { 473b20251a355c88193c439f928a84ae69483fb488John Recknamespace uirenderer { 483b20251a355c88193c439f928a84ae69483fb488John Recknamespace renderthread { 493b20251a355c88193c439f928a84ae69483fb488John Reck 503b20251a355c88193c439f928a84ae69483fb488John Reck#define ERROR_CASE(x) case x: return #x; 513b20251a355c88193c439f928a84ae69483fb488John Reckstatic const char* egl_error_str(EGLint error) { 523b20251a355c88193c439f928a84ae69483fb488John Reck switch (error) { 533b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_SUCCESS) 543b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_NOT_INITIALIZED) 553b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ACCESS) 563b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ALLOC) 573b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_ATTRIBUTE) 583b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CONFIG) 593b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CONTEXT) 603b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_CURRENT_SURFACE) 613b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_DISPLAY) 623b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_MATCH) 633b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_NATIVE_PIXMAP) 643b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_NATIVE_WINDOW) 653b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_PARAMETER) 663b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_BAD_SURFACE) 673b20251a355c88193c439f928a84ae69483fb488John Reck ERROR_CASE(EGL_CONTEXT_LOST) 683b20251a355c88193c439f928a84ae69483fb488John Reck default: 693b20251a355c88193c439f928a84ae69483fb488John Reck return "Unknown error"; 703b20251a355c88193c439f928a84ae69483fb488John Reck } 713b20251a355c88193c439f928a84ae69483fb488John Reck} 72694d499662838123f474f41b31dea84ec5d563f0sergeyvconst char* EglManager::eglErrorString() { 733b20251a355c88193c439f928a84ae69483fb488John Reck return egl_error_str(eglGetError()); 743b20251a355c88193c439f928a84ae69483fb488John Reck} 753b20251a355c88193c439f928a84ae69483fb488John Reck 76149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckstatic struct { 77149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck bool bufferAge = false; 78149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck bool setDamage = false; 79149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck} EglExtensions; 80149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 813b20251a355c88193c439f928a84ae69483fb488John ReckEglManager::EglManager(RenderThread& thread) 823b20251a355c88193c439f928a84ae69483fb488John Reck : mRenderThread(thread) 833b20251a355c88193c439f928a84ae69483fb488John Reck , mEglDisplay(EGL_NO_DISPLAY) 84d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik , mEglConfig(nullptr) 853b20251a355c88193c439f928a84ae69483fb488John Reck , mEglContext(EGL_NO_CONTEXT) 863b20251a355c88193c439f928a84ae69483fb488John Reck , mPBufferSurface(EGL_NO_SURFACE) 87253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy , mCurrentSurface(EGL_NO_SURFACE) { 883b20251a355c88193c439f928a84ae69483fb488John Reck} 893b20251a355c88193c439f928a84ae69483fb488John Reck 903b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::initialize() { 913b20251a355c88193c439f928a84ae69483fb488John Reck if (hasEglContext()) return; 923b20251a355c88193c439f928a84ae69483fb488John Reck 93fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck ATRACE_NAME("Creating EGLContext"); 94fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck 953b20251a355c88193c439f928a84ae69483fb488John Reck mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 963b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, 97694d499662838123f474f41b31dea84ec5d563f0sergeyv "Failed to get EGL_DEFAULT_DISPLAY! err=%s", eglErrorString()); 983b20251a355c88193c439f928a84ae69483fb488John Reck 993b20251a355c88193c439f928a84ae69483fb488John Reck EGLint major, minor; 1003b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE, 101694d499662838123f474f41b31dea84ec5d563f0sergeyv "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString()); 1023b20251a355c88193c439f928a84ae69483fb488John Reck 1033b20251a355c88193c439f928a84ae69483fb488John Reck ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor); 1043b20251a355c88193c439f928a84ae69483fb488John Reck 105149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck initExtensions(); 106149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 107149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck // Now that extensions are loaded, pick a swap behavior 108149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (Properties::enablePartialUpdates) { 109b77c94a96abeeecf65c5b3292db679c049af6271Matt Sarett // An Adreno driver bug is causing rendering problems for SkiaGL with 110b77c94a96abeeecf65c5b3292db679c049af6271Matt Sarett // buffer age swap behavior (b/31957043). To temporarily workaround, 111b77c94a96abeeecf65c5b3292db679c049af6271Matt Sarett // we will use preserved swap behavior. 112b77c94a96abeeecf65c5b3292db679c049af6271Matt Sarett if (Properties::useBufferAge && EglExtensions.bufferAge && !Properties::isSkiaEnabled()) { 113149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck mSwapBehavior = SwapBehavior::BufferAge; 114149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } else { 115149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck mSwapBehavior = SwapBehavior::Preserved; 116149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 117149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 11813d1b4ab10fbee5e81a2ba1ac59cfae1e51d3ef0Season Li 119149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck loadConfig(); 1203b20251a355c88193c439f928a84ae69483fb488John Reck createContext(); 121d7db4d767246b41d44995acb93d03d220b53c748John Reck createPBufferSurface(); 122d7db4d767246b41d44995acb93d03d220b53c748John Reck makeCurrent(mPBufferSurface); 123704bed0da7cc75d0c517d425445de70ceb58060bJohn Reck DeviceInfo::initialize(); 1243b20251a355c88193c439f928a84ae69483fb488John Reck mRenderThread.renderState().onGLContextCreated(); 12598f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger 12698f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { 1277e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger#ifdef HWUI_GLES_WRAP_ENABLED 1287e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger debug::GlesDriver* driver = debug::GlesDriver::get(); 1297e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger sk_sp<const GrGLInterface> glInterface(driver->getSkiaInterface()); 1307e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger#else 13198f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface()); 1327e044fef628c7deb25189958714cb93a714a3617Derek Sollenberger#endif 13398f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger LOG_ALWAYS_FATAL_IF(!glInterface.get()); 13498f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger 13598f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger GrContextOptions options; 136ab61fb8b5f3e7fc807bd335fcfe088d2d0fcb13aDerek Sollenberger options.fGpuPathRenderers &= ~GrContextOptions::GpuPathRenderers::kDistanceField; 13798f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger options.fAllowPathMaskCaching = true; 13898f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend, 13998f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger (GrBackendContext)glInterface.get(), options)); 14098f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger } 1413b20251a355c88193c439f928a84ae69483fb488John Reck} 1423b20251a355c88193c439f928a84ae69483fb488John Reck 143149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckvoid EglManager::initExtensions() { 144704bed0da7cc75d0c517d425445de70ceb58060bJohn Reck auto extensions = StringUtils::split( 145704bed0da7cc75d0c517d425445de70ceb58060bJohn Reck eglQueryString(mEglDisplay, EGL_EXTENSIONS)); 1468733bff058e12075e50c15c0c56c20298cc5f44fJohn Reck // For our purposes we don't care if EGL_BUFFER_AGE is a result of 1478733bff058e12075e50c15c0c56c20298cc5f44fJohn Reck // EGL_EXT_buffer_age or EGL_KHR_partial_update as our usage is covered 1488733bff058e12075e50c15c0c56c20298cc5f44fJohn Reck // under EGL_KHR_partial_update and we don't need the expanded scope 1498733bff058e12075e50c15c0c56c20298cc5f44fJohn Reck // that EGL_EXT_buffer_age provides. 1508733bff058e12075e50c15c0c56c20298cc5f44fJohn Reck EglExtensions.bufferAge = extensions.has("EGL_EXT_buffer_age") 1518733bff058e12075e50c15c0c56c20298cc5f44fJohn Reck || extensions.has("EGL_KHR_partial_update"); 1526e6646c03788f198a9878763680c05342d7622f3Chris Craik EglExtensions.setDamage = extensions.has("EGL_KHR_partial_update"); 153708b6687da23d2ac5bd394dec3e6d950b34d5b6cJohn Reck LOG_ALWAYS_FATAL_IF(!extensions.has("EGL_KHR_swap_buffers_with_damage"), 154708b6687da23d2ac5bd394dec3e6d950b34d5b6cJohn Reck "Missing required extension EGL_KHR_swap_buffers_with_damage"); 1553b20251a355c88193c439f928a84ae69483fb488John Reck} 1563b20251a355c88193c439f928a84ae69483fb488John Reck 157149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckbool EglManager::hasEglContext() { 158149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return mEglDisplay != EGL_NO_DISPLAY; 15913d1b4ab10fbee5e81a2ba1ac59cfae1e51d3ef0Season Li} 16013d1b4ab10fbee5e81a2ba1ac59cfae1e51d3ef0Season Li 161149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckvoid EglManager::loadConfig() { 162149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior)); 163149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck EGLint swapBehavior = (mSwapBehavior == SwapBehavior::Preserved) 164149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0; 1653b20251a355c88193c439f928a84ae69483fb488John Reck EGLint attribs[] = { 1663b20251a355c88193c439f928a84ae69483fb488John Reck EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 1673b20251a355c88193c439f928a84ae69483fb488John Reck EGL_RED_SIZE, 8, 1683b20251a355c88193c439f928a84ae69483fb488John Reck EGL_GREEN_SIZE, 8, 1693b20251a355c88193c439f928a84ae69483fb488John Reck EGL_BLUE_SIZE, 8, 1703b20251a355c88193c439f928a84ae69483fb488John Reck EGL_ALPHA_SIZE, 8, 1713b20251a355c88193c439f928a84ae69483fb488John Reck EGL_DEPTH_SIZE, 0, 1723b20251a355c88193c439f928a84ae69483fb488John Reck EGL_CONFIG_CAVEAT, EGL_NONE, 1733b20251a355c88193c439f928a84ae69483fb488John Reck EGL_STENCIL_SIZE, Stencil::getStencilSize(), 1743b20251a355c88193c439f928a84ae69483fb488John Reck EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior, 1753b20251a355c88193c439f928a84ae69483fb488John Reck EGL_NONE 1763b20251a355c88193c439f928a84ae69483fb488John Reck }; 1773b20251a355c88193c439f928a84ae69483fb488John Reck 1783b20251a355c88193c439f928a84ae69483fb488John Reck EGLint num_configs = 1; 1793b20251a355c88193c439f928a84ae69483fb488John Reck if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs) 1803b20251a355c88193c439f928a84ae69483fb488John Reck || num_configs != 1) { 181149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (mSwapBehavior == SwapBehavior::Preserved) { 1823b20251a355c88193c439f928a84ae69483fb488John Reck // Try again without dirty regions enabled 183149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without..."); 184149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck mSwapBehavior = SwapBehavior::Discard; 185149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck loadConfig(); 1863b20251a355c88193c439f928a84ae69483fb488John Reck } else { 187149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck // Failed to get a valid config 188694d499662838123f474f41b31dea84ec5d563f0sergeyv LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString()); 1893b20251a355c88193c439f928a84ae69483fb488John Reck } 1903b20251a355c88193c439f928a84ae69483fb488John Reck } 1913b20251a355c88193c439f928a84ae69483fb488John Reck} 1923b20251a355c88193c439f928a84ae69483fb488John Reck 1933b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::createContext() { 194682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck EGLint attribs[] = { 195682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, 196682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck EGL_NONE 197682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck }; 1983b20251a355c88193c439f928a84ae69483fb488John Reck mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs); 1993b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, 200694d499662838123f474f41b31dea84ec5d563f0sergeyv "Failed to create context, error = %s", eglErrorString()); 2013b20251a355c88193c439f928a84ae69483fb488John Reck} 2023b20251a355c88193c439f928a84ae69483fb488John Reck 203d7db4d767246b41d44995acb93d03d220b53c748John Reckvoid EglManager::createPBufferSurface() { 2043b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, 2053b20251a355c88193c439f928a84ae69483fb488John Reck "usePBufferSurface() called on uninitialized GlobalContext!"); 2063b20251a355c88193c439f928a84ae69483fb488John Reck 2073b20251a355c88193c439f928a84ae69483fb488John Reck if (mPBufferSurface == EGL_NO_SURFACE) { 2083b20251a355c88193c439f928a84ae69483fb488John Reck EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; 2093b20251a355c88193c439f928a84ae69483fb488John Reck mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs); 2103b20251a355c88193c439f928a84ae69483fb488John Reck } 2113b20251a355c88193c439f928a84ae69483fb488John Reck} 2123b20251a355c88193c439f928a84ae69483fb488John Reck 2133b20251a355c88193c439f928a84ae69483fb488John ReckEGLSurface EglManager::createSurface(EGLNativeWindowType window) { 2143b20251a355c88193c439f928a84ae69483fb488John Reck initialize(); 215253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy 216253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy EGLint attribs[] = { 217253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy#ifdef ANDROID_ENABLE_LINEAR_BLENDING 218253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR, 219253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy EGL_COLORSPACE, EGL_COLORSPACE_sRGB, 220253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy#endif 221253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy EGL_NONE 222253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy }; 223253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy 224253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, attribs); 2253b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, 2263b20251a355c88193c439f928a84ae69483fb488John Reck "Failed to create EGLSurface for window %p, eglErr = %s", 227694d499662838123f474f41b31dea84ec5d563f0sergeyv (void*) window, eglErrorString()); 2289a878a646f6aca6160f22c139a5efd4de94199f8Christian Poetzsch 2299a878a646f6aca6160f22c139a5efd4de94199f8Christian Poetzsch if (mSwapBehavior != SwapBehavior::Preserved) { 2309a878a646f6aca6160f22c139a5efd4de94199f8Christian Poetzsch LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED) == EGL_FALSE, 2319a878a646f6aca6160f22c139a5efd4de94199f8Christian Poetzsch "Failed to set swap behavior to destroyed for window %p, eglErr = %s", 232694d499662838123f474f41b31dea84ec5d563f0sergeyv (void*) window, eglErrorString()); 2339a878a646f6aca6160f22c139a5efd4de94199f8Christian Poetzsch } 2349a878a646f6aca6160f22c139a5efd4de94199f8Christian Poetzsch 2353b20251a355c88193c439f928a84ae69483fb488John Reck return surface; 2363b20251a355c88193c439f928a84ae69483fb488John Reck} 2373b20251a355c88193c439f928a84ae69483fb488John Reck 2383b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::destroySurface(EGLSurface surface) { 2393b20251a355c88193c439f928a84ae69483fb488John Reck if (isCurrent(surface)) { 2403b20251a355c88193c439f928a84ae69483fb488John Reck makeCurrent(EGL_NO_SURFACE); 2413b20251a355c88193c439f928a84ae69483fb488John Reck } 2423b20251a355c88193c439f928a84ae69483fb488John Reck if (!eglDestroySurface(mEglDisplay, surface)) { 243694d499662838123f474f41b31dea84ec5d563f0sergeyv ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, eglErrorString()); 2443b20251a355c88193c439f928a84ae69483fb488John Reck } 2453b20251a355c88193c439f928a84ae69483fb488John Reck} 2463b20251a355c88193c439f928a84ae69483fb488John Reck 2473b20251a355c88193c439f928a84ae69483fb488John Reckvoid EglManager::destroy() { 2483b20251a355c88193c439f928a84ae69483fb488John Reck if (mEglDisplay == EGL_NO_DISPLAY) return; 2493b20251a355c88193c439f928a84ae69483fb488John Reck 25098f75d53dbe243b1661c616643698e025d4978f6Derek Sollenberger mRenderThread.setGrContext(nullptr); 2511d4774233304c484673e2af2c1de2ab41021c979Chris Craik mRenderThread.renderState().onGLContextDestroyed(); 2523b20251a355c88193c439f928a84ae69483fb488John Reck eglDestroyContext(mEglDisplay, mEglContext); 2533b20251a355c88193c439f928a84ae69483fb488John Reck eglDestroySurface(mEglDisplay, mPBufferSurface); 2543b20251a355c88193c439f928a84ae69483fb488John Reck eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 2553b20251a355c88193c439f928a84ae69483fb488John Reck eglTerminate(mEglDisplay); 2563b20251a355c88193c439f928a84ae69483fb488John Reck eglReleaseThread(); 2573b20251a355c88193c439f928a84ae69483fb488John Reck 2583b20251a355c88193c439f928a84ae69483fb488John Reck mEglDisplay = EGL_NO_DISPLAY; 2593b20251a355c88193c439f928a84ae69483fb488John Reck mEglContext = EGL_NO_CONTEXT; 2603b20251a355c88193c439f928a84ae69483fb488John Reck mPBufferSurface = EGL_NO_SURFACE; 2613b20251a355c88193c439f928a84ae69483fb488John Reck mCurrentSurface = EGL_NO_SURFACE; 2623b20251a355c88193c439f928a84ae69483fb488John Reck} 2633b20251a355c88193c439f928a84ae69483fb488John Reck 264f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reckbool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) { 2653b20251a355c88193c439f928a84ae69483fb488John Reck if (isCurrent(surface)) return false; 2663b20251a355c88193c439f928a84ae69483fb488John Reck 2673b20251a355c88193c439f928a84ae69483fb488John Reck if (surface == EGL_NO_SURFACE) { 268d7db4d767246b41d44995acb93d03d220b53c748John Reck // Ensure we always have a valid surface & context 269d7db4d767246b41d44995acb93d03d220b53c748John Reck surface = mPBufferSurface; 270d7db4d767246b41d44995acb93d03d220b53c748John Reck } 271d7db4d767246b41d44995acb93d03d220b53c748John Reck if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) { 272f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck if (errOut) { 273f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck *errOut = eglGetError(); 274f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck ALOGW("Failed to make current on surface %p, error=%s", 275f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck (void*)surface, egl_error_str(*errOut)); 276f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck } else { 277f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", 278694d499662838123f474f41b31dea84ec5d563f0sergeyv (void*)surface, eglErrorString()); 279f2dcc2aecb94e726096256c47b913ed0a57ae7e2John Reck } 2803b20251a355c88193c439f928a84ae69483fb488John Reck } 2813b20251a355c88193c439f928a84ae69483fb488John Reck mCurrentSurface = surface; 282a896306c38c4d11c43b967a21db6d74c251b2520John Reck if (Properties::disableVsync) { 283a896306c38c4d11c43b967a21db6d74c251b2520John Reck eglSwapInterval(mEglDisplay, 0); 284a896306c38c4d11c43b967a21db6d74c251b2520John Reck } 2853b20251a355c88193c439f928a84ae69483fb488John Reck return true; 2863b20251a355c88193c439f928a84ae69483fb488John Reck} 2873b20251a355c88193c439f928a84ae69483fb488John Reck 288149173d28c0843aba86b0810ce75b34be6a0d08fJohn ReckEGLint EglManager::queryBufferAge(EGLSurface surface) { 289149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck switch (mSwapBehavior) { 290149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck case SwapBehavior::Discard: 291149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return 0; 292149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck case SwapBehavior::Preserved: 293149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return 1; 294149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck case SwapBehavior::BufferAge: 295149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck EGLint bufferAge; 296149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck eglQuerySurface(mEglDisplay, surface, EGL_BUFFER_AGE_EXT, &bufferAge); 297149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return bufferAge; 298149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 299149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return 0; 300149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck} 301149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 302149173d28c0843aba86b0810ce75b34be6a0d08fJohn ReckFrame EglManager::beginFrame(EGLSurface surface) { 3033b20251a355c88193c439f928a84ae69483fb488John Reck LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, 3043b20251a355c88193c439f928a84ae69483fb488John Reck "Tried to beginFrame on EGL_NO_SURFACE!"); 3053b20251a355c88193c439f928a84ae69483fb488John Reck makeCurrent(surface); 306149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck Frame frame; 307149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck frame.mSurface = surface; 308149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, &frame.mWidth); 309149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, &frame.mHeight); 310149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck frame.mBufferAge = queryBufferAge(surface); 3113b20251a355c88193c439f928a84ae69483fb488John Reck eglBeginFrame(mEglDisplay, surface); 312149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck return frame; 313149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck} 314149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 315149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckvoid EglManager::damageFrame(const Frame& frame, const SkRect& dirty) { 316149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck#ifdef EGL_KHR_partial_update 317149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (EglExtensions.setDamage && mSwapBehavior == SwapBehavior::BufferAge) { 318149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck EGLint rects[4]; 319149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck frame.map(dirty, rects); 320149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (!eglSetDamageRegionKHR(mEglDisplay, frame.mSurface, rects, 1)) { 321149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck LOG_ALWAYS_FATAL("Failed to set damage region on surface %p, error=%s", 322694d499662838123f474f41b31dea84ec5d563f0sergeyv (void*)frame.mSurface, eglErrorString()); 323149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 324149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck } 325149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck#endif 3263b20251a355c88193c439f928a84ae69483fb488John Reck} 3273b20251a355c88193c439f928a84ae69483fb488John Reck 328c96955d9bb997b51be5fa929b5a67349d0459c3aJohn Reckbool EglManager::damageRequiresSwap() { 329c96955d9bb997b51be5fa929b5a67349d0459c3aJohn Reck return EglExtensions.setDamage && mSwapBehavior == SwapBehavior::BufferAge; 330c96955d9bb997b51be5fa929b5a67349d0459c3aJohn Reck} 331c96955d9bb997b51be5fa929b5a67349d0459c3aJohn Reck 332149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reckbool EglManager::swapBuffers(const Frame& frame, const SkRect& screenDirty) { 3335515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck 334682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck if (CC_UNLIKELY(Properties::waitForGpuCompletion)) { 3355515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck ATRACE_NAME("Finishing GPU work"); 3365515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck fence(); 3375515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck } 3385515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck 339a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9John Reck EGLint rects[4]; 340a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9John Reck frame.map(screenDirty, rects); 341a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9John Reck eglSwapBuffersWithDamageKHR(mEglDisplay, frame.mSurface, rects, 342a672f6ba4c9f65de0b94bcdc639f1e053d7ee5d9John Reck screenDirty.isEmpty() ? 0 : 1); 343d04794a9a3f9edc8b7ca336175d66eb81a8f55faJohn Reck 3443b20251a355c88193c439f928a84ae69483fb488John Reck EGLint err = eglGetError(); 3452cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck if (CC_LIKELY(err == EGL_SUCCESS)) { 3462cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return true; 3472cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck } 348c2547fa6f9a0f4247b35edcee69f3c3cc3510b1aJohn Reck if (err == EGL_BAD_SURFACE || err == EGL_BAD_NATIVE_WINDOW) { 3492cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // For some reason our surface was destroyed out from under us 3502cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // This really shouldn't happen, but if it does we can recover easily 3512cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // by just not trying to use the surface anymore 352d1ddcf19bbb17cad09ec93b2ad09b1e1e0bfb3ffJohn Reck ALOGW("swapBuffers encountered EGL error %d on %p, halting rendering...", 353d1ddcf19bbb17cad09ec93b2ad09b1e1e0bfb3ffJohn Reck err, frame.mSurface); 3542cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return false; 3552cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck } 3562cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck LOG_ALWAYS_FATAL("Encountered EGL error %d %s during rendering", 3572cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck err, egl_error_str(err)); 3582cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck // Impossible to hit this, but the compiler doesn't know that 3592cdbc7d2283aae3d77b12c8fdbba8ca4bd3db5eaJohn Reck return false; 3603b20251a355c88193c439f928a84ae69483fb488John Reck} 3613b20251a355c88193c439f928a84ae69483fb488John Reck 3625515637540bedd8fc9a1a6e46a4b512dd45520a5John Reckvoid EglManager::fence() { 3635515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck EGLSyncKHR fence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, NULL); 3645515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck eglClientWaitSyncKHR(mEglDisplay, fence, 3655515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); 3665515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck eglDestroySyncKHR(mEglDisplay, fence); 3675515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck} 3685515637540bedd8fc9a1a6e46a4b512dd45520a5John Reck 3691125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reckbool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) { 370149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (mSwapBehavior != SwapBehavior::Preserved) return false; 371149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck 372149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck bool preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, 373149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED); 374149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck if (!preserved) { 375149173d28c0843aba86b0810ce75b34be6a0d08fJohn Reck ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", 376694d499662838123f474f41b31dea84ec5d563f0sergeyv (void*) surface, eglErrorString()); 3771125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck // Maybe it's already set? 3781125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck EGLint swapBehavior; 3791125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) { 3801125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck preserved = (swapBehavior == EGL_BUFFER_PRESERVED); 3811125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck } else { 3821125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", 383694d499662838123f474f41b31dea84ec5d563f0sergeyv (void*) surface, eglErrorString()); 3841125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck } 3853b20251a355c88193c439f928a84ae69483fb488John Reck } 3861125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck 3871125d1fa92ab9f3b8315bbfb72e038b62dfd454bJohn Reck return preserved; 3883b20251a355c88193c439f928a84ae69483fb488John Reck} 3893b20251a355c88193c439f928a84ae69483fb488John Reck 3903b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace renderthread */ 3913b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace uirenderer */ 3923b20251a355c88193c439f928a84ae69483fb488John Reck} /* namespace android */ 393