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