From 09e2a82405b732bf9e07c359fd6624417e848566 Mon Sep 17 00:00:00 2001 From: Rajulu Ponnada Date: Thu, 12 Jul 2012 16:37:49 -0700 Subject: [PATCH] hardware/qcom/display: tile rendering with fbo boundaries support for application tiling with fbo boundaries Change-Id: I1f4abb5a386847c965518b58cb13966defcf7670 --- Android.mk | 2 + libtilerenderer/Android.mk | 11 +- libtilerenderer/tilerenderer.cpp | 401 +++++++++++++++++++++++++++---- libtilerenderer/tilerenderer.h | 129 +++++++++- 4 files changed, 484 insertions(+), 59 deletions(-) diff --git a/Android.mk b/Android.mk index 3eacd9e..0b5f9ee 100644 --- a/Android.mk +++ b/Android.mk @@ -6,4 +6,6 @@ display-hals := libgralloc libgenlock libcopybit liblight display-hals += libhwcomposer liboverlay libqdutils endif +display-hals += libtilerenderer + include $(call all-named-subdir-makefiles,$(display-hals)) diff --git a/libtilerenderer/Android.mk b/libtilerenderer/Android.mk index af8f25f..9cffff6 100644 --- a/libtilerenderer/Android.mk +++ b/libtilerenderer/Android.mk @@ -5,18 +5,17 @@ include $(CLEAR_VARS) ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_MODULE := libtilerenderer LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES +LOCAL_CFLAGS += -DQCOM_APP_TILE_RENDER + LOCAL_C_INCLUDES := \ frameworks/base/include/utils \ frameworks/base/libs/hwui \ - external/skia/include/core \ - external/skia/include/effects \ - external/skia/include/images \ - external/skia/src/ports \ - external/skia/include/utils \ hardware/libhardware/include/hardware \ frameworks/base/opengl/include/GLES2 -LOCAL_SHARED_LIBRARIES := $(common_libs) libGLESv2 libhwui +LOCAL_SHARED_LIBRARIES := $(common_libs) libGLESv2 + LOCAL_SRC_FILES := tilerenderer.cpp include $(BUILD_SHARED_LIBRARY) endif diff --git a/libtilerenderer/tilerenderer.cpp b/libtilerenderer/tilerenderer.cpp index 4ed6895..7ecd055 100644 --- a/libtilerenderer/tilerenderer.cpp +++ b/libtilerenderer/tilerenderer.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 The Android Open Source Project - * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011 Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,82 +15,389 @@ * limitations under the License. */ +#define LOG_TAG "TileRenderer" + #include #include #include -#include #include "tilerenderer.h" +#define DEBUG_TILE_RENDERER 0 + namespace android { ANDROID_SINGLETON_STATIC_INSTANCE(uirenderer::TileRenderer) ; namespace uirenderer { +#if DEBUG_TILE_RENDERER + #define TILE_RENDERER_LOGD(...) ALOGD(__VA_ARGS__) +#else + #define TILE_RENDERER_LOGD(...) +#endif + +TileCacheMgr::TileCache::TileCache(void) { +} + +TileCacheMgr::TileCache::TileCache(int fbo) { + mFbo = fbo; + mLeft = 0; + mTop = 0; + mRight = 0; + mBottom = 0; + mWidth = 0; + mHeight = 0; +} + +TileCacheMgr::TileCache::TileCache(int fbo, int left, int top, int right, + int bottom, int width, int height) { + mFbo = fbo; + mLeft = left; + mTop = top; + mRight = right; + mBottom = bottom; + mWidth = width; + mHeight = height; +} + +TileCacheMgr::TileCache::~TileCache(void) {} + +TileCacheMgr::TileCache::TileCache(const TileCacheMgr::TileCache& src) { + copy(src); +} + +const TileCacheMgr::TileCache& TileCacheMgr::TileCache::operator=(const TileCacheMgr::TileCache& src) { + if (this != &src) + copy(src); + return *this; +} + +void TileCacheMgr::TileCache::copy(const TileCacheMgr::TileCache& src) { + mFbo = src.mFbo; + mLeft = src.mLeft; + mTop = src.mTop; + mRight = src.mRight; + mBottom = src.mBottom; + mWidth = src.mWidth; + mHeight = src.mHeight; +} + +void TileCacheMgr::TileCache::setValue(int left, int top, int right, + int bottom, int width, int height) { + mLeft = left; + mTop = top; + mRight = right; + mBottom = bottom; + mWidth = width; + mHeight = height; +} + +void TileCacheMgr::TileCache::getValue(int &left, int &top, int &right, + int &bottom, int &width, int &height) const { + left = mLeft; + top= mTop; + right = mRight; + bottom = mBottom; + width = mWidth; + height = mHeight; +} + +TileCacheMgr::TileCacheMgr() { + mIsExtTilingStarted = false; + pthread_mutex_init(&mLock, NULL); +} + +TileCacheMgr::~TileCacheMgr() { + pthread_mutex_destroy(&mLock); +} + +void TileCacheMgr::set(int left, int top, int right, + int bottom, int width, int height) { + pthread_mutex_lock(&mLock); + mIsExtTilingStarted = true; + pthread_mutex_unlock(&mLock); + TILE_RENDERER_LOGD("TileCacheMgr::set(ltrbwh) " + "fbo=-1 l=%d r=%d\n", left, right); + set(-1, left, top, right, bottom, width, height); +} + +void TileCacheMgr::set(int fbo) { + int index = -1; + int left = 0, top = 0, right = 0, bottom = 0; + int width = 0, height = 0; + TILE_RENDERER_LOGD("TileCacheMgr::set(fbo) " + "mIsExtTilingStarted=%d size=%d fbo=%d\n", + mIsExtTilingStarted, mTileCache.size(), fbo); + if (mIsExtTilingStarted) { + get(-1, left, top, right, bottom, width, height); + pthread_mutex_lock(&mLock); + mIsExtTilingStarted = false; + TileCache entry(fbo, left, top, right, bottom, width, height); + mTileCache.add(entry); + pthread_mutex_unlock(&mLock); + } +} + +void TileCacheMgr::set(int fbo, int left, int top, int right, + int bottom, int width, int height) { + int index = -1; + TileCache entry(fbo, left, top, right, bottom, width, height); + TILE_RENDERER_LOGD("TileCacheMgr::set(fbo,ltrbwh) size=%d " + "fbo=%d l=%d r=%d\n", + mTileCache.size(), fbo, left, right); + pthread_mutex_lock(&mLock); + index = mTileCache.indexOf(entry); + if (index < 0) { + TILE_RENDERER_LOGD("set::index not found, add fbo=%d\n", fbo); + mTileCache.add(entry); + } + else if (left || top || right || bottom){ + TILE_RENDERER_LOGD("set::index found, edit fbo=%d\n", fbo); + mTileCache.editItemAt(index).setValue(left, top, right, + bottom, width, height); + } + pthread_mutex_unlock(&mLock); +} + +void TileCacheMgr::get(int fbo, int &left, int &top, int &right, + int &bottom, int &width, int &height) { + TileCache entry(fbo); + pthread_mutex_lock(&mLock); + int index = mTileCache.indexOf(entry); + if (index >= 0) { + mTileCache.itemAt(index).getValue(left, top, right, + bottom, width, height); + mTileCache.removeAt(index); + TILE_RENDERER_LOGD("TileCacheMgr::get fbo=%d l=%d t=%d r=%d b=%d\n", + fbo, left, top, right, bottom); + } + pthread_mutex_unlock(&mLock); +} + +void TileCacheMgr::peek(int fbo, int &left, int &top, int &right, + int &bottom, int &width, int &height) { + TileCache entry(fbo); + pthread_mutex_lock(&mLock); + int index = mTileCache.indexOf(entry); + if (index >= 0) { + mTileCache.itemAt(index).getValue(left, top, right, + bottom, width, height); + TILE_RENDERER_LOGD("TileCacheMgr::peek fbo=%d l=%d t=%d r=%d b=%d\n", + fbo, left, top, right, bottom); + } + pthread_mutex_unlock(&mLock); +} + +void TileCacheMgr::clear(int fbo) { + TILE_RENDERER_LOGD("TileCacheMgr::clear %d\n", fbo); + pthread_mutex_lock(&mLock); + if (fbo == -1) { + mIsExtTilingStarted = false; + } + else if (fbo >= 0) { + TileCache entry(fbo); + int index = mTileCache.indexOf(entry); + mTileCache.removeAt(index); + } + else if (fbo < 0) { + mTileCache.clear(); + } + pthread_mutex_unlock(&mLock); +} + TileRenderer::TileRenderer() { + pthread_mutex_init(&mLock, NULL); mIsTiled = false; + mIsReady = false; } TileRenderer::~TileRenderer() { + pthread_mutex_destroy(&mLock); } -void TileRenderer::startTileRendering(OpenGLRenderer* renderer, - int left, int top, - int right, int bottom) { - int width = 0; - int height = 0; - GLenum status = GL_NO_ERROR; +void TileRenderer::startTileRendering(int left, int top, + int right, int bottom, + int width, int height) { +#ifdef QCOM_APP_TILE_RENDER + bool preserve = false; - if (renderer != NULL) { - renderer->getViewport(width, height); + if (isTiled() || + (verifyAndAdjustRect(left, top, right, bottom, width, height, preserve) < 0)) + return; + + setReady(true); + + TILE_RENDERER_LOGD("startTileRendering l=%d, t=%d, r=%d, b=%d w=%d h=%d", + left, top, right, bottom, width, height); + mTileCacheMgr.set(left, top, right, bottom, width, height); + if (startTilingInternal(left, top, right, bottom, width, height, preserve) >= 0) { + setTiled(true); } +#endif +} + +void TileRenderer::endTileRendering() { +#ifdef QCOM_APP_TILE_RENDER + if (!isTiled()) { + return; + } + endTilingInternal(); + mTileCacheMgr.clear(-1); + TILE_RENDERER_LOGD("endTileRendering"); + setTiled(false); + setReady(false); +#endif +} + +void TileRenderer::startTiling(int fbo, int left, int top, + int right, int bottom, + int width, int height, bool preserve) { +#ifdef QCOM_APP_TILE_RENDER + if (!isReady() || isTiled()) + return; + + mTileCacheMgr.set(fbo, left, top, right, bottom, width, height); + mTileCacheMgr.peek(fbo, left, top, right, bottom, width, height); + if (verifyAndAdjustRect(left, top, right, bottom, width, height, preserve) < 0) + return; + TILE_RENDERER_LOGD("TileRenderer::startTiling l=%d," + "t=%d, r=%d, b=%d fbo=%d", + left, top, right, bottom, fbo); + startTilingInternal(left, top, right, bottom, + width, height, preserve); +#endif + return; +} + +void TileRenderer::startTiling(int fbo, bool preserve) { +#ifdef QCOM_APP_TILE_RENDER + int left, top; + int right, bottom; + int width, height; + + if (!isReady() || isTiled()) + return; + + mTileCacheMgr.peek(fbo, left, top, right, bottom, width, height); + if (verifyAndAdjustRect(left, top, right, bottom, width, height, preserve) < 0) + return; + TILE_RENDERER_LOGD("TileRenderer::startTiling fbo=%d preserve=%d", + fbo, preserve); + startTilingInternal(left, top, right, bottom, + width, height, preserve); +#endif + return; +} + +void TileRenderer::endTiling(int fbo, bool bClear) { +#ifdef QCOM_APP_TILE_RENDER + if (!isTiled()) { + return; + } + TILE_RENDERER_LOGD("TileRenderer::end fbo=%d", fbo); + if (fbo >= 0) { + mTileCacheMgr.set(fbo); + } + + if (bClear) { + mTileCacheMgr.clear(fbo); + } + + endTilingInternal(); +#endif +} + +void TileRenderer::clearCache(int fbo) { +#ifdef QCOM_APP_TILE_RENDER + mTileCacheMgr.clear(fbo); +#endif +} + +int TileRenderer::startTilingInternal(int left, int top, + int right, int bottom, + int width, int height, + bool preserve) { + int ret = -1; + GLenum status = GL_NO_ERROR; + int l = left, t = (height - bottom); + int w = (right - left), h = (bottom - top); + unsigned int preservemask = GL_NONE; + int rendertarget = FRAMEBUFFER_FBO; + + if (l < 0 || t < 0) { + l = (l < 0) ? 0 : l; + t = (t < 0) ? 0 : t; + preserve = true; + } + + if (w > width || h > height) { + w = (w > width) ? width : w; + h = (h > height) ? height : h; + preserve = true; + } + + //clear off all errors before tiling, if any + while ((status = glGetError()) != GL_NO_ERROR) { + ALOGE("glStartTilingQCOM: 0x%x", status); + } + + if (preserve) + preservemask = GL_COLOR_BUFFER_BIT0_QCOM; + + preservemask = preservemask << rendertarget; + + TILE_RENDERER_LOGD("startTilingInternal rendertarget=%d, " + "preservemask = 0x%x", + rendertarget, preservemask); + + glStartTilingQCOM(l, t, w, h, preservemask); + + status = glGetError(); + if (status == GL_NO_ERROR) { + TILE_RENDERER_LOGD("startTilingInternal l=%d, t=%d, r=%d," + "b=%d, w=%d, h=%d", + left, top, right, bottom, width, height); + setTiled(true); + ret = 0; + } else + ALOGE("glStartTilingQCOM: 0x%x", status); + return ret; +} + +int TileRenderer::endTilingInternal() { + unsigned int preservemask = GL_COLOR_BUFFER_BIT0_QCOM; + int rendertarget = FRAMEBUFFER_FBO; + TILE_RENDERER_LOGD("endTilingInternal"); + preservemask = preservemask << rendertarget; + TILE_RENDERER_LOGD("endTilingInternal rendertarget=%d," + "preservemask = 0x%x", + rendertarget, preservemask); + glEndTilingQCOM(preservemask); + GLenum status = GL_NO_ERROR; + while ((status = glGetError()) != GL_NO_ERROR) { + ALOGE("glEndTilingQCOM: 0x%x", status); + } + setTiled(false); + return 0; +} + +int TileRenderer::verifyAndAdjustRect(int &left, int &top, int &right, + int &bottom, int width, int height, + bool &preserve) { + int ret = 0; if (!left && !right && !top && !bottom) { left = 0; top = 0; right = width; bottom = height; + preserve = true; } if (!left && !right && !top && !bottom) { //can't do tile rendering ALOGE("can't tile render; drity region, width, height not available"); - return; + ret = -1; } - - int l = left, t = (height - bottom), w = (right - left), h = (bottom - top), preserve = 0; - - if (l < 0 || t < 0) { - l = (l < 0) ? 0 : l; - t = (t < 0) ? 0 : t; - preserve = 1; - } - - if (w > width || h > height) { - w = (w > width) ? width : w; - h = (h > height) ? height : h; - preserve = 1; - } - - //clear off all errors before tiling, if any - while ((status = glGetError()) != GL_NO_ERROR); - - if (preserve) - glStartTilingQCOM(l, t, w, h, GL_COLOR_BUFFER_BIT0_QCOM); - else - glStartTilingQCOM(l, t, w, h, GL_NONE); - - status = glGetError(); - if (status == GL_NO_ERROR) - mIsTiled = true; -} - -void TileRenderer::endTileRendering(OpenGLRenderer*) { - if (!mIsTiled) { - return; - } - glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); - mIsTiled = false; - GLenum status = GL_NO_ERROR; - while ((status = glGetError()) != GL_NO_ERROR); + return ret; } }; // namespace uirenderer diff --git a/libtilerenderer/tilerenderer.h b/libtilerenderer/tilerenderer.h index 7f8d608..307bdfe 100644 --- a/libtilerenderer/tilerenderer.h +++ b/libtilerenderer/tilerenderer.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 The Android Open Source Project - * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,22 +18,139 @@ #define ANDROID_TILE_RENDERER_H #include +#include namespace android { namespace uirenderer { -class OpenGLRenderer; +#define FRAMEBUFFER_FBO 0 + +#define TILERENDERING_EXT_START android::uirenderer::TileRenderer::getInstance().startTileRendering +#define TILERENDERING_EXT_END android::uirenderer::TileRenderer::getInstance().endTileRendering +#define TILERENDERING_START android::uirenderer::TileRenderer::getInstance().startTiling +#define TILERENDERING_END android::uirenderer::TileRenderer::getInstance().endTiling +#define TILERENDERING_CLEARCACHE android::uirenderer::TileRenderer::getInstance().clearCache + +class TileCacheMgr { +public: + TileCacheMgr(); + ~TileCacheMgr(); + + void set(int left, int top, int right, + int bottom, int width, int height); + void set(int fbo, int left, int top, int right, + int bottom, int width, int height); + void set(int fbo); + void get(int fbo, int & left, int & top, int & right, + int & bottom, int & width, int & height); + void peek(int fbo, int & left, int & top, int & right, + int & bottom, int & width, int & height); + void clear(int fbo = -2); + +private: + class TileCache { + public: + TileCache(void); + TileCache(int fbo); + TileCache(int fbo, int left, int top, int right, + int bottom, int width, int height); + ~TileCache(void); + TileCache(const TileCache & src); + const TileCache& operator = (const TileCache & src); + void copy(const TileCache & src); + bool operator < (const TileCache & rhs) const + { + return mFbo < rhs.mFbo; + } + bool operator == (const TileCache & rhs) const + { + return mFbo == rhs.mFbo; + } + + void setFbo(int fbo) + { + mFbo = fbo; + } + + void setValue(int left, int top, int right, + int bottom, int width, int height); + void getValue(int & left, int & top, int & right, + int & bottom, int & width, int & height) const; + + private: + int mFbo; + int mLeft; + int mTop; + int mRight; + int mBottom; + int mWidth; + int mHeight; + }; + + SortedVector < TileCache > mTileCache; + bool mIsExtTilingStarted; + pthread_mutex_t mLock; +}; class TileRenderer: public Singleton { - public: +public: TileRenderer(); ~TileRenderer(); - void startTileRendering(OpenGLRenderer* renderer, int left, int top, int right, int bottom); - void endTileRendering(OpenGLRenderer*); + void startTileRendering(int left, int top, int right, + int bottom, int width, int height); + void startTiling(int fbo, int left = 0, int top = 0, int right = 0, + int bottom = 0, int width = 0, int height = 0, + bool preserve = false); + void startTiling(int fbo, bool preserve); + void endTileRendering(); + void endTiling(int fbo, bool bClear = false); + void clearCache(int fbo); +private: + int startTilingInternal(int left, int top, int right, + int bottom, int width, int height, + bool preserve = false); + int endTilingInternal(); + int verifyAndAdjustRect(int & left, int & top, int & right, + int & bottom, int width, int height, + bool & preserve); + bool isReady() + { + bool ret = false; + pthread_mutex_lock(&mLock); + ret = mIsReady; + pthread_mutex_unlock(&mLock); + return ret; + } - private: + void setReady(bool flag) + { + pthread_mutex_lock(&mLock); + mIsReady = flag; + pthread_mutex_unlock(&mLock); + } + + bool isTiled() + { + bool ret = false; + pthread_mutex_lock(&mLock); + ret = mIsTiled; + pthread_mutex_unlock(&mLock); + return ret; + } + + void setTiled(bool flag) + { + pthread_mutex_lock(&mLock); + mIsTiled = flag; + pthread_mutex_unlock(&mLock); + } + +private: + TileCacheMgr mTileCacheMgr; bool mIsTiled; + bool mIsReady; + pthread_mutex_t mLock; }; }; // namespace uirenderer