CanvasContext.cpp revision a5dda645da738da7b4ae15e28fa7d93d3b04b94f
123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck/*
223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Copyright (C) 2014 The Android Open Source Project
323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck *
423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Licensed under the Apache License, Version 2.0 (the "License");
523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * you may not use this file except in compliance with the License.
623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * You may obtain a copy of the License at
723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck *
823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck *      http://www.apache.org/licenses/LICENSE-2.0
923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck *
1023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Unless required by applicable law or agreed to in writing, software
1123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * distributed under the License is distributed on an "AS IS" BASIS,
1223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * See the License for the specific language governing permissions and
1423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * limitations under the License.
1523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck */
1623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#define LOG_TAG "CanvasContext"
1823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include "CanvasContext.h"
2023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
2123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include <cutils/properties.h>
224f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <private/hwui/DrawGlInfo.h>
2323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include <strings.h>
2423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
254f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include "RenderThread.h"
2623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include "../Caches.h"
2719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck#include "../DeferredLayerUpdater.h"
2819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck#include "../LayerRenderer.h"
294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include "../OpenGLRenderer.h"
3023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include "../Stencil.h"
3123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
3223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
3323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#define GLES_VERSION 2
34cdfeef6624613ca06fe8a7edfb92608afb0499eeJohn Reck#define USE_TEXTURE_ATLAS false
3523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
364f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck// Android-specific addition that is used to show when frames began in systrace
374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John ReckEGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
384f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3923b797ab5151eb2474f3bdd679f2f07bfd723042John Recknamespace android {
4023b797ab5151eb2474f3bdd679f2f07bfd723042John Recknamespace uirenderer {
4123b797ab5151eb2474f3bdd679f2f07bfd723042John Recknamespace renderthread {
4223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
4323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#define ERROR_CASE(x) case x: return #x;
4423b797ab5151eb2474f3bdd679f2f07bfd723042John Reckstatic const char* egl_error_str(EGLint error) {
4523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    switch (error) {
4623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_SUCCESS)
4723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_NOT_INITIALIZED)
4823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_ACCESS)
4923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_ALLOC)
5023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_ATTRIBUTE)
5123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_CONFIG)
5223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_CONTEXT)
5323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
5423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_DISPLAY)
5523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_MATCH)
5623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
5723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
5823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_PARAMETER)
5923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_SURFACE)
6023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_CONTEXT_LOST)
6123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    default:
6223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        return "Unknown error";
6323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
6423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
6523b797ab5151eb2474f3bdd679f2f07bfd723042John Reckstatic const char* egl_error_str() {
6623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return egl_error_str(eglGetError());
6723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
6823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
6923b797ab5151eb2474f3bdd679f2f07bfd723042John Reckstatic bool load_dirty_regions_property() {
7023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    char buf[PROPERTY_VALUE_MAX];
7123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true");
7223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return !strncasecmp("true", buf, len);
7323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
7423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
7523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck// This class contains the shared global EGL objects, such as EGLDisplay
7623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck// and EGLConfig, which are re-used by CanvasContext
7723b797ab5151eb2474f3bdd679f2f07bfd723042John Reckclass GlobalContext {
7823b797ab5151eb2474f3bdd679f2f07bfd723042John Reckpublic:
7923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    static GlobalContext* get();
8023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
814f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // Returns true on success, false on failure
824f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void initialize();
8323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
840d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    bool hasContext();
850d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck
864f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void usePBufferSurface();
8723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLSurface createSurface(EGLNativeWindowType window);
8823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    void destroySurface(EGLSurface surface);
8923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
9023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    void destroy();
9123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
9223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
93dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    // Returns true if the current surface changed, false if it was already current
94dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    bool makeCurrent(EGLSurface surface);
954f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
964f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void swapBuffers(EGLSurface surface);
9723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
9823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    bool enableDirtyRegions(EGLSurface surface);
9923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
10066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
10166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
10223b797ab5151eb2474f3bdd679f2f07bfd723042John Reckprivate:
10323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    GlobalContext();
10423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    // GlobalContext is never destroyed, method is purposely not implemented
10523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    ~GlobalContext();
10623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1074f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void loadConfig();
1084f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void createContext();
1094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void initAtlas();
11023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
11123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    static GlobalContext* sContext;
11223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
11323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLDisplay mEglDisplay;
11423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLConfig mEglConfig;
11523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLContext mEglContext;
11623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLSurface mPBufferSurface;
11723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
11823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    const bool mRequestDirtyRegions;
11923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    bool mCanSetDirtyRegions;
12023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
12123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLSurface mCurrentSurface;
12266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
12366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    sp<GraphicBuffer> mAtlasBuffer;
12466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    int64_t* mAtlasMap;
12566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    size_t mAtlasMapSize;
12623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck};
12723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
12823b797ab5151eb2474f3bdd679f2f07bfd723042John ReckGlobalContext* GlobalContext::sContext = 0;
12923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
13023b797ab5151eb2474f3bdd679f2f07bfd723042John ReckGlobalContext* GlobalContext::get() {
13123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!sContext) {
13223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        sContext = new GlobalContext();
13323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
13423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return sContext;
13523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
13623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
13723b797ab5151eb2474f3bdd679f2f07bfd723042John ReckGlobalContext::GlobalContext()
13823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        : mEglDisplay(EGL_NO_DISPLAY)
13923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mEglConfig(0)
14023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mEglContext(EGL_NO_CONTEXT)
14123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mPBufferSurface(EGL_NO_SURFACE)
14223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mRequestDirtyRegions(load_dirty_regions_property())
14366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        , mCurrentSurface(EGL_NO_SURFACE)
14466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        , mAtlasMap(NULL)
14566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        , mAtlasMapSize(0) {
14623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mCanSetDirtyRegions = mRequestDirtyRegions;
14723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false");
14823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
14923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1504f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::initialize() {
1510d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    if (hasContext()) return;
15223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
15323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1544f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
1554f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
15623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
15723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint major, minor;
1584f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
1594f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
16023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1614f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
16223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1634f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    loadConfig();
1644f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    createContext();
1654f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    usePBufferSurface();
1664f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    Caches::getInstance().init();
1674f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    initAtlas();
16823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
16923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1700d1f634f4b5e1bb37aa51777efb6a68619488d01John Reckbool GlobalContext::hasContext() {
1710d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    return mEglDisplay != EGL_NO_DISPLAY;
1720d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck}
1730d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck
1744f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::loadConfig() {
17523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
17623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint attribs[] = {
17723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
17823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_RED_SIZE, 8,
17923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_GREEN_SIZE, 8,
18023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_BLUE_SIZE, 8,
18123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_ALPHA_SIZE, 8,
18223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_DEPTH_SIZE, 0,
18323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_CONFIG_CAVEAT, EGL_NONE,
18423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_STENCIL_SIZE, Stencil::getStencilSize(),
18523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
18623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_NONE
18723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    };
18823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
18923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint num_configs = 1;
19023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
19123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            || num_configs != 1) {
19223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        // Failed to get a valid config
19323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        if (mCanSetDirtyRegions) {
19423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
19523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            // Try again without dirty regions enabled
19623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            mCanSetDirtyRegions = false;
19723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            loadConfig();
19823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        } else {
1994f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
20023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        }
20123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
20223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
20323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
2044f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::createContext() {
20523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE };
20623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
2074f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
2084f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        "Failed to create context, error = %s", egl_error_str());
2094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
21166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckvoid GlobalContext::setTextureAtlas(const sp<GraphicBuffer>& buffer,
21266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        int64_t* map, size_t mapSize) {
21366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
21466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    // Already initialized
21566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    if (mAtlasBuffer.get()) {
21666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        ALOGW("Multiple calls to setTextureAtlas!");
21766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        delete map;
21866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        return;
21966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    }
22066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
22166f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    mAtlasBuffer = buffer;
22266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    mAtlasMap = map;
22366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    mAtlasMapSize = mapSize;
22466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
22566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    if (hasContext()) {
22666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        usePBufferSurface();
22766f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        initAtlas();
22866f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    }
22966f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck}
23066f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
2314f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::initAtlas() {
232cdfeef6624613ca06fe8a7edfb92608afb0499eeJohn Reck    if (USE_TEXTURE_ATLAS) {
233cdfeef6624613ca06fe8a7edfb92608afb0499eeJohn Reck        Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize);
234cdfeef6624613ca06fe8a7edfb92608afb0499eeJohn Reck    }
23523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
23623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
2374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::usePBufferSurface() {
2384f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
2394f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "usePBufferSurface() called on uninitialized GlobalContext!");
24023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
24123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mPBufferSurface == EGL_NO_SURFACE) {
24223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
24323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
24423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
2454f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    makeCurrent(mPBufferSurface);
24623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
24723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
24823b797ab5151eb2474f3bdd679f2f07bfd723042John ReckEGLSurface GlobalContext::createSurface(EGLNativeWindowType window) {
24923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    initialize();
25023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL);
25123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
25223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
25323b797ab5151eb2474f3bdd679f2f07bfd723042John Reckvoid GlobalContext::destroySurface(EGLSurface surface) {
25423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (isCurrent(surface)) {
25523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        makeCurrent(EGL_NO_SURFACE);
25623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
25723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!eglDestroySurface(mEglDisplay, surface)) {
25823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
25923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
26023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
26123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
26223b797ab5151eb2474f3bdd679f2f07bfd723042John Reckvoid GlobalContext::destroy() {
26323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mEglDisplay == EGL_NO_DISPLAY) return;
26423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
26523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    usePBufferSurface();
26623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (Caches::hasInstance()) {
26723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        Caches::getInstance().terminate();
26823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
26923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
27023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglDestroyContext(mEglDisplay, mEglContext);
27123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglDestroySurface(mEglDisplay, mPBufferSurface);
27223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
27323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglTerminate(mEglDisplay);
27423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglReleaseThread();
27523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
27623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mEglDisplay = EGL_NO_DISPLAY;
27723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mEglContext = EGL_NO_CONTEXT;
27823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mPBufferSurface = EGL_NO_SURFACE;
27923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mCurrentSurface = EGL_NO_SURFACE;
28023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
28123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
282dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reckbool GlobalContext::makeCurrent(EGLSurface surface) {
283dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    if (isCurrent(surface)) return false;
28423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
28523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (surface == EGL_NO_SURFACE) {
28623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        // If we are setting EGL_NO_SURFACE we don't care about any of the potential
28723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        // return errors, which would only happen if mEglDisplay had already been
28823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        // destroyed in which case the current context is already NO_CONTEXT
28923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
29023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
2914f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
2924f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                (void*)surface, egl_error_str());
29323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
29423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mCurrentSurface = surface;
295dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    return true;
29623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
29723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
2984f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
2994f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
3004f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "Tried to beginFrame on EGL_NO_SURFACE!");
3014f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    makeCurrent(surface);
3024f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (width) {
3034f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width);
30423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
3054f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (height) {
3064f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
3074f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
3084f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    eglBeginFrame(mEglDisplay, surface);
3094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3114f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::swapBuffers(EGLSurface surface) {
3124f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    eglSwapBuffers(mEglDisplay, surface);
3134f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    EGLint err = eglGetError();
3144f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS,
3154f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "Encountered EGL error %d %s during rendering", err, egl_error_str(err));
31623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
31723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
31823b797ab5151eb2474f3bdd679f2f07bfd723042John Reckbool GlobalContext::enableDirtyRegions(EGLSurface surface) {
31923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!mRequestDirtyRegions) return false;
32023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
32123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mCanSetDirtyRegions) {
32223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
32323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
32423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck                    (void*) surface, egl_error_str());
32523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            return false;
32623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        }
32723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        return true;
32823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
32923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    // Perhaps it is already enabled?
33023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint value;
33123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) {
33223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
33323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck                (void*) surface, egl_error_str());
33423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        return false;
33523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
33623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return value == EGL_BUFFER_PRESERVED;
33723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
33823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
339e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn ReckCanvasContext::CanvasContext(bool translucent, RenderNode* rootRenderNode)
3404f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        : mRenderThread(RenderThread::getInstance())
3414f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mEglSurface(EGL_NO_SURFACE)
3424f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mDirtyRegionsEnabled(false)
3434f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mOpaque(!translucent)
3444f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mCanvas(0)
345e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        , mHaveNewSurface(false)
346e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        , mRootRenderNode(rootRenderNode) {
34723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mGlobalContext = GlobalContext::get();
34823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
34923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
35023b797ab5151eb2474f3bdd679f2f07bfd723042John ReckCanvasContext::~CanvasContext() {
351fae904d63947fe1687d1d44be29234cc3d538f24John Reck    destroyCanvasAndSurface();
352e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    mRenderThread.removeFrameCallback(this);
3534f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3544f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
355fae904d63947fe1687d1d44be29234cc3d538f24John Reckvoid CanvasContext::destroyCanvasAndSurface() {
3564f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (mCanvas) {
3574f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        delete mCanvas;
3584f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        mCanvas = 0;
3594f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
36023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    setSurface(NULL);
36123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
36223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
363a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckvoid CanvasContext::setSurface(ANativeWindow* window) {
364a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    mNativeWindow = window;
365a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
36623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mEglSurface != EGL_NO_SURFACE) {
36723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mGlobalContext->destroySurface(mEglSurface);
36823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mEglSurface = EGL_NO_SURFACE;
36923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
37023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
37123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (window) {
37223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mEglSurface = mGlobalContext->createSurface(window);
3734f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
3744f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                "Failed to create EGLSurface for window %p, eglErr = %s",
3754f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                (void*) window, egl_error_str());
37623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
37723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
37823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mEglSurface != EGL_NO_SURFACE) {
37923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface);
3804f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        mHaveNewSurface = true;
381dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck        makeCurrent();
382368cdd85268999997fb495cf90c4417221797de0John Reck    } else {
383368cdd85268999997fb495cf90c4417221797de0John Reck        mRenderThread.removeFrameCallback(this);
3844f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
3854f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3864f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3874f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::swapBuffers() {
3884f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mGlobalContext->swapBuffers(mEglSurface);
3894f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mHaveNewSurface = false;
3904f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3914f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
392f7d9c1dc84671d4e99657ef071d275700d85bb11John Reckvoid CanvasContext::requireSurface() {
393f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
394f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck            "requireSurface() called but no surface set!");
395dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    makeCurrent();
3964f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3974f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
398a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckbool CanvasContext::initialize(ANativeWindow* window) {
3994f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (mCanvas) return false;
4004f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    setSurface(window);
4014f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas = new OpenGLRenderer();
4024f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas->initProperties();
4034f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    return true;
4044f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4054f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
406a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckvoid CanvasContext::updateSurface(ANativeWindow* window) {
4074f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    setSurface(window);
408f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck}
409f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck
410a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckvoid CanvasContext::pauseSurface(ANativeWindow* window) {
411f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    // TODO: For now we just need a fence, in the future suspend any animations
412f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    // and such to prevent from trying to render into this surface
4134f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4144f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
415797b95b26bbb7557678af78b9a2a61830158920fChris Craikvoid CanvasContext::setup(int width, int height, const Vector3& lightCenter, float lightRadius) {
4164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (!mCanvas) return;
4174f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas->setViewport(width, height);
418797b95b26bbb7557678af78b9a2a61830158920fChris Craik    mCanvas->initializeLight(lightCenter, lightRadius);
4194f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4204f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
42163a06673253914510bbeebd500655008682dade1John Reckvoid CanvasContext::setOpaque(bool opaque) {
42263a06673253914510bbeebd500655008682dade1John Reck    mOpaque = opaque;
42363a06673253914510bbeebd500655008682dade1John Reck}
42463a06673253914510bbeebd500655008682dade1John Reck
425860d155f866cc15a725e7ce03763280987f24901John Reckvoid CanvasContext::makeCurrent() {
426dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    // TODO: Figure out why this workaround is needed, see b/13913604
427dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    // In the meantime this matches the behavior of GLRenderer, so it is not a regression
428dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface);
429860d155f866cc15a725e7ce03763280987f24901John Reck}
430860d155f866cc15a725e7ce03763280987f24901John Reck
431f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reckvoid CanvasContext::prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters,
432860d155f866cc15a725e7ce03763280987f24901John Reck        TreeInfo& info) {
433f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot prepareDraw without a canvas!");
434860d155f866cc15a725e7ce03763280987f24901John Reck    makeCurrent();
435f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck
436f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    processLayerUpdates(layerUpdaters, info);
437f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    if (info.out.hasAnimations) {
438f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        // TODO: Uh... crap?
439f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    }
440f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    prepareTree(info);
441f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck}
442f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck
443f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reckvoid CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
444f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        TreeInfo& info) {
44519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    for (size_t i = 0; i < layerUpdaters->size(); i++) {
44619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
447860d155f866cc15a725e7ce03763280987f24901John Reck        bool success = update->apply(info);
448860d155f866cc15a725e7ce03763280987f24901John Reck        LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
44919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        if (update->backingLayer()->deferredUpdateScheduled) {
45019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck            mCanvas->pushLayerUpdate(update->backingLayer());
45119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        }
45219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    }
45319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
45419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
455e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckvoid CanvasContext::prepareTree(TreeInfo& info) {
456f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    mRenderThread.removeFrameCallback(this);
45718f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck
458f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
459e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    mRootRenderNode->prepareTree(info);
460e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
461a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    int runningBehind = 0;
462a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    // TODO: This query is moderately expensive, investigate adding some sort
463a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    // of fast-path based off when we last called eglSwapBuffers() as well as
464a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    // last vsync time. Or something.
465a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    mNativeWindow->query(mNativeWindow.get(),
466a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck            NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
467a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    info.out.canDrawThisFrame = !runningBehind;
468a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
469a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    if (info.out.hasAnimations || !info.out.canDrawThisFrame) {
470f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        if (info.out.hasFunctors) {
471f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck            info.out.requiresUiRedraw = true;
472f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        } else if (!info.out.requiresUiRedraw) {
473f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck            // If animationsNeedsRedraw is set don't bother posting for an RT anim
474f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck            // as we will just end up fighting the UI thread.
475f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck            mRenderThread.postFrameCallback(this);
476f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        }
477e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    }
478e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck}
479e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
480a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckvoid CanvasContext::notifyFramePending() {
481a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    ATRACE_CALL();
482a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    mRenderThread.pushBackFrameCallback(this);
483a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck}
484a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
485e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckvoid CanvasContext::draw(Rect* dirty) {
4864f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
4874f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "drawDisplayList called on a context with no canvas or surface!");
4884f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4894f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    EGLint width, height;
4904f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mGlobalContext->beginFrame(mEglSurface, &width, &height);
4914f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
4924f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        mCanvas->setViewport(width, height);
4934f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        dirty = NULL;
4944f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    } else if (!mDirtyRegionsEnabled || mHaveNewSurface) {
4954f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        dirty = NULL;
4964f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
4974f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4984f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    status_t status;
499e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    if (dirty && !dirty->isEmpty()) {
5004f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        status = mCanvas->prepareDirty(dirty->left, dirty->top,
5014f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                dirty->right, dirty->bottom, mOpaque);
5024f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    } else {
5034f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        status = mCanvas->prepare(mOpaque);
5044f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
5054f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
5064f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    Rect outBounds;
507e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    status |= mCanvas->drawDisplayList(mRootRenderNode.get(), outBounds);
5084f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
5094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // TODO: Draw debug info
5104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // TODO: Performance tracking
5114f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
5124f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas->finish();
5134f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
5144f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (status & DrawGlInfo::kStatusDrew) {
5154f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        swapBuffers();
51623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
51723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
51823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
519e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck// Called by choreographer to do an RT-driven animation
52018f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reckvoid CanvasContext::doFrame() {
521368cdd85268999997fb495cf90c4417221797de0John Reck    if (CC_UNLIKELY(!mCanvas || mEglSurface == EGL_NO_SURFACE)) {
522368cdd85268999997fb495cf90c4417221797de0John Reck        return;
523368cdd85268999997fb495cf90c4417221797de0John Reck    }
524368cdd85268999997fb495cf90c4417221797de0John Reck
525e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    ATRACE_CALL();
526e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
527e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    TreeInfo info;
528e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    info.evaluateAnimations = true;
529e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    info.performStagingPush = false;
530e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    info.prepareTextures = false;
531e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
532e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    prepareTree(info);
533a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    if (info.out.canDrawThisFrame) {
534a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        draw(NULL);
535a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    }
536e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck}
537e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
5380d1f634f4b5e1bb37aa51777efb6a68619488d01John Reckvoid CanvasContext::invokeFunctor(Functor* functor) {
539d3d8dafc2f61fb118c060720b52684c59303f3dbJohn Reck    ATRACE_CALL();
5400d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
5410d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    if (mGlobalContext->hasContext()) {
5420d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck        requireGlContext();
5430d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck        mode = DrawGlInfo::kModeProcess;
5440d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    }
545832b151465ed81c43e59891d5eebe62128b21fbbJohn Reck    (*functor)(mode, NULL);
5466f07a0dc875a9eac67312085a8e0133b9e2f4771John Reck
5476f07a0dc875a9eac67312085a8e0133b9e2f4771John Reck    if (mCanvas) {
5486f07a0dc875a9eac67312085a8e0133b9e2f4771John Reck        mCanvas->resume();
5496f07a0dc875a9eac67312085a8e0133b9e2f4771John Reck    }
55023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
55123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
55219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckbool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
55319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    requireGlContext();
554860d155f866cc15a725e7ce03763280987f24901John Reck    TreeInfo info;
555860d155f866cc15a725e7ce03763280987f24901John Reck    layer->apply(info);
55619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
55719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
55819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
559fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reckvoid CanvasContext::runWithGlContext(RenderTask* task) {
56019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    requireGlContext();
56119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    task->run();
56219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
56319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
5641949e7928eeec22cd3f74b5f763a4eb433238453John ReckLayer* CanvasContext::createRenderLayer(int width, int height) {
565f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    requireSurface();
5661949e7928eeec22cd3f74b5f763a4eb433238453John Reck    return LayerRenderer::createRenderLayer(width, height);
5671949e7928eeec22cd3f74b5f763a4eb433238453John Reck}
5681949e7928eeec22cd3f74b5f763a4eb433238453John Reck
5691949e7928eeec22cd3f74b5f763a4eb433238453John ReckLayer* CanvasContext::createTextureLayer() {
570f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    requireSurface();
5711949e7928eeec22cd3f74b5f763a4eb433238453John Reck    return LayerRenderer::createTextureLayer();
5721949e7928eeec22cd3f74b5f763a4eb433238453John Reck}
5731949e7928eeec22cd3f74b5f763a4eb433238453John Reck
57419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckvoid CanvasContext::requireGlContext() {
575fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    if (mEglSurface != EGL_NO_SURFACE) {
576dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck        makeCurrent();
577fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    } else {
578fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck        mGlobalContext->usePBufferSurface();
579fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    }
580fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck}
581fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck
58266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reckvoid CanvasContext::setTextureAtlas(const sp<GraphicBuffer>& buffer,
58366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck        int64_t* map, size_t mapSize) {
58466f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck    GlobalContext::get()->setTextureAtlas(buffer, map, mapSize);
58566f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck}
58666f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
58723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} /* namespace renderthread */
58823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} /* namespace uirenderer */
58923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} /* namespace android */
590