CanvasContext.cpp revision f7d9c1dc84671d4e99657ef071d275700d85bb11
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
3423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
354f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#ifdef USE_OPENGL_RENDERER
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#endif
394f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4023b797ab5151eb2474f3bdd679f2f07bfd723042John Recknamespace android {
4123b797ab5151eb2474f3bdd679f2f07bfd723042John Recknamespace uirenderer {
4223b797ab5151eb2474f3bdd679f2f07bfd723042John Recknamespace renderthread {
4323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
4423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#define ERROR_CASE(x) case x: return #x;
4523b797ab5151eb2474f3bdd679f2f07bfd723042John Reckstatic const char* egl_error_str(EGLint error) {
4623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    switch (error) {
4723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_SUCCESS)
4823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_NOT_INITIALIZED)
4923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_ACCESS)
5023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_ALLOC)
5123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_ATTRIBUTE)
5223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_CONFIG)
5323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_CONTEXT)
5423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
5523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_DISPLAY)
5623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_MATCH)
5723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
5823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
5923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_PARAMETER)
6023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_BAD_SURFACE)
6123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ERROR_CASE(EGL_CONTEXT_LOST)
6223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    default:
6323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        return "Unknown error";
6423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
6523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
6623b797ab5151eb2474f3bdd679f2f07bfd723042John Reckstatic const char* egl_error_str() {
6723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return egl_error_str(eglGetError());
6823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
6923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
7023b797ab5151eb2474f3bdd679f2f07bfd723042John Reckstatic bool load_dirty_regions_property() {
7123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    char buf[PROPERTY_VALUE_MAX];
7223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true");
7323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return !strncasecmp("true", buf, len);
7423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
7523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
7623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck// This class contains the shared global EGL objects, such as EGLDisplay
7723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck// and EGLConfig, which are re-used by CanvasContext
7823b797ab5151eb2474f3bdd679f2f07bfd723042John Reckclass GlobalContext {
7923b797ab5151eb2474f3bdd679f2f07bfd723042John Reckpublic:
8023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    static GlobalContext* get();
8123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
824f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // Returns true on success, false on failure
834f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void initialize();
8423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
850d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    bool hasContext();
860d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck
874f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void usePBufferSurface();
8823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLSurface createSurface(EGLNativeWindowType window);
8923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    void destroySurface(EGLSurface surface);
9023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
9123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    void destroy();
9223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
9323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
944f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void 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
10023b797ab5151eb2474f3bdd679f2f07bfd723042John Reckprivate:
10123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    GlobalContext();
10223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    // GlobalContext is never destroyed, method is purposely not implemented
10323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    ~GlobalContext();
10423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1054f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void loadConfig();
1064f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void createContext();
1074f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    void initAtlas();
10823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
10923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    static GlobalContext* sContext;
11023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
11123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLDisplay mEglDisplay;
11223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLConfig mEglConfig;
11323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLContext mEglContext;
11423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLSurface mPBufferSurface;
11523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
11623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    const bool mRequestDirtyRegions;
11723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    bool mCanSetDirtyRegions;
11823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
11923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLSurface mCurrentSurface;
12023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck};
12123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
12223b797ab5151eb2474f3bdd679f2f07bfd723042John ReckGlobalContext* GlobalContext::sContext = 0;
12323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
12423b797ab5151eb2474f3bdd679f2f07bfd723042John ReckGlobalContext* GlobalContext::get() {
12523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!sContext) {
12623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        sContext = new GlobalContext();
12723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
12823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return sContext;
12923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
13023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
13123b797ab5151eb2474f3bdd679f2f07bfd723042John ReckGlobalContext::GlobalContext()
13223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        : mEglDisplay(EGL_NO_DISPLAY)
13323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mEglConfig(0)
13423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mEglContext(EGL_NO_CONTEXT)
13523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mPBufferSurface(EGL_NO_SURFACE)
13623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mRequestDirtyRegions(load_dirty_regions_property())
13723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        , mCurrentSurface(EGL_NO_SURFACE) {
13823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mCanSetDirtyRegions = mRequestDirtyRegions;
13923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false");
14023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
14123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1424f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::initialize() {
1430d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    if (hasContext()) return;
14423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
14523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1464f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
1474f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
14823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
14923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint major, minor;
1504f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
1514f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
15223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1534f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
15423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1554f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    loadConfig();
1564f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    createContext();
1574f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    usePBufferSurface();
1584f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    Caches::getInstance().init();
1594f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    initAtlas();
16023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
16123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1620d1f634f4b5e1bb37aa51777efb6a68619488d01John Reckbool GlobalContext::hasContext() {
1630d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    return mEglDisplay != EGL_NO_DISPLAY;
1640d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck}
1650d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck
1664f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::loadConfig() {
16723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
16823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint attribs[] = {
16923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
17023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_RED_SIZE, 8,
17123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_GREEN_SIZE, 8,
17223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_BLUE_SIZE, 8,
17323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_ALPHA_SIZE, 8,
17423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_DEPTH_SIZE, 0,
17523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_CONFIG_CAVEAT, EGL_NONE,
17623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_STENCIL_SIZE, Stencil::getStencilSize(),
17723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
17823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            EGL_NONE
17923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    };
18023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
18123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint num_configs = 1;
18223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
18323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            || num_configs != 1) {
18423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        // Failed to get a valid config
18523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        if (mCanSetDirtyRegions) {
18623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
18723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            // Try again without dirty regions enabled
18823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            mCanSetDirtyRegions = false;
18923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            loadConfig();
19023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        } else {
1914f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
19223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        }
19323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
19423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
19523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1964f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::createContext() {
19723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE };
19823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
1994f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
2004f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        "Failed to create context, error = %s", egl_error_str());
2014f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2024f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
2034f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::initAtlas() {
2044f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // TODO implement
2054f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // For now just run without an atlas
20623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
20723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
2084f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::usePBufferSurface() {
2094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
2104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "usePBufferSurface() called on uninitialized GlobalContext!");
21123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
21223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mPBufferSurface == EGL_NO_SURFACE) {
21323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
21423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
21523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
2164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    makeCurrent(mPBufferSurface);
21723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
21823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
21923b797ab5151eb2474f3bdd679f2f07bfd723042John ReckEGLSurface GlobalContext::createSurface(EGLNativeWindowType window) {
22023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    initialize();
22123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL);
22223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
22323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
22423b797ab5151eb2474f3bdd679f2f07bfd723042John Reckvoid GlobalContext::destroySurface(EGLSurface surface) {
22523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (isCurrent(surface)) {
22623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        makeCurrent(EGL_NO_SURFACE);
22723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
22823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!eglDestroySurface(mEglDisplay, surface)) {
22923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
23023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
23123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
23223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
23323b797ab5151eb2474f3bdd679f2f07bfd723042John Reckvoid GlobalContext::destroy() {
23423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mEglDisplay == EGL_NO_DISPLAY) return;
23523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
23623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    usePBufferSurface();
23723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (Caches::hasInstance()) {
23823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        Caches::getInstance().terminate();
23923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
24023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
24123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglDestroyContext(mEglDisplay, mEglContext);
24223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglDestroySurface(mEglDisplay, mPBufferSurface);
24323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
24423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglTerminate(mEglDisplay);
24523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    eglReleaseThread();
24623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
24723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mEglDisplay = EGL_NO_DISPLAY;
24823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mEglContext = EGL_NO_CONTEXT;
24923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mPBufferSurface = EGL_NO_SURFACE;
25023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mCurrentSurface = EGL_NO_SURFACE;
25123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
25223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
2534f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::makeCurrent(EGLSurface surface) {
2544f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (isCurrent(surface)) return;
25523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
25623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (surface == EGL_NO_SURFACE) {
25723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        // If we are setting EGL_NO_SURFACE we don't care about any of the potential
25823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        // return errors, which would only happen if mEglDisplay had already been
25923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        // destroyed in which case the current context is already NO_CONTEXT
26023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
26123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
2624f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
2634f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                (void*)surface, egl_error_str());
26423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
26523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mCurrentSurface = surface;
26623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
26723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
2684f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
2694f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
2704f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "Tried to beginFrame on EGL_NO_SURFACE!");
2714f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    makeCurrent(surface);
2724f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (width) {
2734f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width);
27423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
2754f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (height) {
2764f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
2774f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
2784f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    eglBeginFrame(mEglDisplay, surface);
2794f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2804f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
2814f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid GlobalContext::swapBuffers(EGLSurface surface) {
2824f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    eglSwapBuffers(mEglDisplay, surface);
2834f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    EGLint err = eglGetError();
2844f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // TODO: Check whether we need to special case EGL_CONTEXT_LOST
2854f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS,
2864f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "Encountered EGL error %d %s during rendering", err, egl_error_str(err));
28723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
28823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
28923b797ab5151eb2474f3bdd679f2f07bfd723042John Reckbool GlobalContext::enableDirtyRegions(EGLSurface surface) {
29023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!mRequestDirtyRegions) return false;
29123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
29223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mCanSetDirtyRegions) {
29323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
29423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
29523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck                    (void*) surface, egl_error_str());
29623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            return false;
29723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        }
29823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        return true;
29923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
30023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    // Perhaps it is already enabled?
30123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    EGLint value;
30223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) {
30323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
30423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck                (void*) surface, egl_error_str());
30523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        return false;
30623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
30723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    return value == EGL_BUFFER_PRESERVED;
30823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
30923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
3104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John ReckCanvasContext::CanvasContext(bool translucent)
3114f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        : mRenderThread(RenderThread::getInstance())
3124f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mEglSurface(EGL_NO_SURFACE)
3134f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mDirtyRegionsEnabled(false)
3144f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mOpaque(!translucent)
3154f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mCanvas(0)
3164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mHaveNewSurface(false)
3174f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mInvokeFunctorsPending(false)
3184f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        , mInvokeFunctorsTask(this) {
31923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    mGlobalContext = GlobalContext::get();
32023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
32123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
32223b797ab5151eb2474f3bdd679f2f07bfd723042John ReckCanvasContext::~CanvasContext() {
3234f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    removeFunctorsTask();
3244f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    destroyCanvas();
3254f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3264f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3274f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::destroyCanvas() {
3284f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (mCanvas) {
3294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        delete mCanvas;
3304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        mCanvas = 0;
3314f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
33223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    setSurface(NULL);
33323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
33423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
3354f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::setSurface(EGLNativeWindowType window) {
33623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mEglSurface != EGL_NO_SURFACE) {
33723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mGlobalContext->destroySurface(mEglSurface);
33823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mEglSurface = EGL_NO_SURFACE;
33923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
34023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
34123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (window) {
34223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mEglSurface = mGlobalContext->createSurface(window);
3434f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
3444f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                "Failed to create EGLSurface for window %p, eglErr = %s",
3454f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                (void*) window, egl_error_str());
34623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
34723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
34823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    if (mEglSurface != EGL_NO_SURFACE) {
34923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface);
350f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        mGlobalContext->makeCurrent(mEglSurface);
3514f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        mHaveNewSurface = true;
3524f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
3534f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3544f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3554f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::swapBuffers() {
3564f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mGlobalContext->swapBuffers(mEglSurface);
3574f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mHaveNewSurface = false;
3584f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3594f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
360f7d9c1dc84671d4e99657ef071d275700d85bb11John Reckvoid CanvasContext::requireSurface() {
361f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
362f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck            "requireSurface() called but no surface set!");
3634f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mGlobalContext->makeCurrent(mEglSurface);
3644f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3654f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3664f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckbool CanvasContext::initialize(EGLNativeWindowType window) {
3674f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (mCanvas) return false;
3684f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    setSurface(window);
3694f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas = new OpenGLRenderer();
3704f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas->initProperties();
3714f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    return true;
3724f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3734f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3744f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::updateSurface(EGLNativeWindowType window) {
3754f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    setSurface(window);
376f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck}
377f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck
378f7d9c1dc84671d4e99657ef071d275700d85bb11John Reckvoid CanvasContext::pauseSurface(EGLNativeWindowType window) {
379f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    // TODO: For now we just need a fence, in the future suspend any animations
380f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    // and such to prevent from trying to render into this surface
3814f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3824f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
3834f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::setup(int width, int height) {
3844f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (!mCanvas) return;
3854f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas->setViewport(width, height);
3864f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
3874f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
388e18264b079481a244b30e3f71012c53bbd861f92John Reckvoid CanvasContext::setDisplayListData(RenderNode* displayList, DisplayListData* newData) {
38944fd8d24f761f82d21e9b00932648a1b6bf91449John Reck    displayList->setData(newData);
39044fd8d24f761f82d21e9b00932648a1b6bf91449John Reck}
39144fd8d24f761f82d21e9b00932648a1b6bf91449John Reck
39219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckvoid CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) {
39319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    mGlobalContext->makeCurrent(mEglSurface);
39419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    for (size_t i = 0; i < layerUpdaters->size(); i++) {
39519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
39619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        LOG_ALWAYS_FATAL_IF(!update->apply(), "Failed to update layer!");
39719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        if (update->backingLayer()->deferredUpdateScheduled) {
39819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck            mCanvas->pushLayerUpdate(update->backingLayer());
39919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        }
40019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    }
40119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
40219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
403e18264b079481a244b30e3f71012c53bbd861f92John Reckvoid CanvasContext::drawDisplayList(RenderNode* displayList, Rect* dirty) {
4044f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
4054f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck            "drawDisplayList called on a context with no canvas or surface!");
4064f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4074f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    EGLint width, height;
4084f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mGlobalContext->beginFrame(mEglSurface, &width, &height);
4094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
4104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        mCanvas->setViewport(width, height);
4114f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        dirty = NULL;
4124f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    } else if (!mDirtyRegionsEnabled || mHaveNewSurface) {
4134f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        dirty = NULL;
4144f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
4154f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    status_t status;
4174f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (dirty) {
4184f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        status = mCanvas->prepareDirty(dirty->left, dirty->top,
4194f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                dirty->right, dirty->bottom, mOpaque);
4204f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    } else {
4214f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        status = mCanvas->prepare(mOpaque);
4224f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
4234f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4244f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    Rect outBounds;
4254f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    status |= mCanvas->drawDisplayList(displayList, outBounds);
4264f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4274f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // TODO: Draw debug info
4284f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    // TODO: Performance tracking
4294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas->finish();
4314f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4324f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (status & DrawGlInfo::kStatusDrew) {
4334f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        swapBuffers();
43423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
43523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
43623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
4374f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid InvokeFunctorsTask::run() {
4384f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mContext->invokeFunctors();
43923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
44023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
4414f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::attachFunctor(Functor* functor) {
4424f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (!mCanvas) return;
4434f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4444f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas->attachFunctor(functor);
4454f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    removeFunctorsTask();
4464f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    queueFunctorsTask(0);
44723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
44823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
4494f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::detachFunctor(Functor* functor) {
4504f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (!mCanvas) return;
4514f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4524f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mCanvas->detachFunctor(functor);
4534f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4544f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4550d1f634f4b5e1bb37aa51777efb6a68619488d01John Reckvoid CanvasContext::invokeFunctor(Functor* functor) {
4560d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
4570d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    if (mGlobalContext->hasContext()) {
4580d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck        requireGlContext();
4590d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck        mode = DrawGlInfo::kModeProcess;
4600d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    }
4610d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    (*functor)(mode, NULL);
4620d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck}
4630d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck
4644f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::invokeFunctors() {
4654f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mInvokeFunctorsPending = false;
4664f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4674f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (!mCanvas) return;
4684f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
469f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    requireSurface();
4704f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    Rect dirty;
471750ca6dbdb259aea0ca5b77380a9303e586ef3eaJohn Reck    mCanvas->invokeFunctors(dirty);
4724f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4734f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4744f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::removeFunctorsTask() {
4754f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (!mInvokeFunctorsPending) return;
4764f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
47716efa9a330fcf10a09cc9564e9d319c6f4be2ae1John Reck    mInvokeFunctorsPending = false;
4784f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mRenderThread.remove(&mInvokeFunctorsTask);
4794f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
4804f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4814f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid CanvasContext::queueFunctorsTask(int delayMs) {
4824f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    if (mInvokeFunctorsPending) return;
4834f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
4844f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mInvokeFunctorsPending = true;
4854f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    mRenderThread.queueDelayed(&mInvokeFunctorsTask, delayMs);
48623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
48723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
48819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckbool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
48919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    requireGlContext();
49019b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    layer->apply();
49119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
49219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
49319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
494fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reckvoid CanvasContext::runWithGlContext(RenderTask* task) {
49519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    requireGlContext();
49619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    task->run();
49719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
49819b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
4991949e7928eeec22cd3f74b5f763a4eb433238453John ReckLayer* CanvasContext::createRenderLayer(int width, int height) {
500f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    requireSurface();
5011949e7928eeec22cd3f74b5f763a4eb433238453John Reck    return LayerRenderer::createRenderLayer(width, height);
5021949e7928eeec22cd3f74b5f763a4eb433238453John Reck}
5031949e7928eeec22cd3f74b5f763a4eb433238453John Reck
5041949e7928eeec22cd3f74b5f763a4eb433238453John ReckLayer* CanvasContext::createTextureLayer() {
505f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    requireSurface();
5061949e7928eeec22cd3f74b5f763a4eb433238453John Reck    return LayerRenderer::createTextureLayer();
5071949e7928eeec22cd3f74b5f763a4eb433238453John Reck}
5081949e7928eeec22cd3f74b5f763a4eb433238453John Reck
50919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckvoid CanvasContext::requireGlContext() {
510fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    if (mEglSurface != EGL_NO_SURFACE) {
511fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck        mGlobalContext->makeCurrent(mEglSurface);
512fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    } else {
513fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck        mGlobalContext->usePBufferSurface();
514fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck    }
515fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck}
516fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck
51723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} /* namespace renderthread */
51823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} /* namespace uirenderer */
51923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck} /* namespace android */
520