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