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