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