# Build the list of shared libraries
LOCAL_SHARED_LIBRARIES := \
+ libandroid \
libandroid_runtime \
libnativehelper \
libsqlite \
#if USE(ACCELERATED_COMPOSITING)
+#include "GaneshRenderer.h"
#include "GLUtils.h"
+#include "RasterRenderer.h"
#include "SkBitmap.h"
#include "SkBitmapRef.h"
#include "SkCanvas.h"
namespace WebCore {
+BaseRenderer::RendererType BaseRenderer::g_currentType = BaseRenderer::Raster;
+
+BaseRenderer* BaseRenderer::createRenderer()
+{
+ if (g_currentType == Raster)
+ return new RasterRenderer();
+ else if (g_currentType == Ganesh)
+ return new GaneshRenderer();
+ return NULL;
+}
+
+void BaseRenderer::swapRendererIfNeeded(BaseRenderer*& renderer)
+{
+ if (renderer->getType() == g_currentType)
+ return;
+
+ delete renderer;
+ renderer = createRenderer();
+}
+
void BaseRenderer::drawTileInfo(SkCanvas* canvas,
const TileRenderInfo& renderInfo, int pictureCount)
{
RendererType getType() { return m_type; }
+ static BaseRenderer* createRenderer();
+ static void swapRendererIfNeeded(BaseRenderer*& renderer);
+ static RendererType getCurrentRendererType() { return g_currentType; }
+ static void setCurrentRendererType(RendererType type) { g_currentType = type; }
+
protected:
virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0;
private:
RendererType m_type;
+ static RendererType g_currentType;
};
} // namespace WebCore
m_fullRepaint = new bool[m_maxBufferNumber];
for (int i = 0; i < m_maxBufferNumber; i++)
m_fullRepaint[i] = true;
+
+ m_renderer = BaseRenderer::createRenderer();
}
BaseTile::~BaseTile()
unsigned int pictureCount = 0;
+ // swap out the renderer if necessary
+ BaseRenderer::swapRendererIfNeeded(m_renderer);
+
// setup the common renderInfo fields;
TileRenderInfo renderInfo;
renderInfo.x = x;
#include "GaneshContext.h"
#include "GLUtils.h"
+#include "android/native_window.h"
+
#if USE(ACCELERATED_COMPOSITING)
#ifdef DEBUG
GaneshContext::GaneshContext()
: m_grContext(0)
- , m_baseTileDevice(0)
- , m_baseTileFbo(0)
+ , m_baseTileDeviceFBO(0)
+ , m_baseTileFBO(0)
, m_baseTileStencil(0)
+ , m_baseTileDeviceSurface(0)
+ , m_surfaceConfig(0)
+ , m_surfaceContext(EGL_NO_CONTEXT)
{
}
return m_grContext;
}
-SkDevice* GaneshContext::getDeviceForBaseTile(GLuint textureId)
+void GaneshContext::flush()
+{
+ if (m_grContext)
+ m_grContext->flush();
+}
+
+SkDevice* GaneshContext::getDeviceForBaseTile(const TileRenderInfo& renderInfo)
+{
+ SkDevice* device = 0;
+ if (renderInfo.textureInfo->getSharedTextureMode() == SurfaceTextureMode)
+ device = getDeviceForBaseTileSurface(renderInfo);
+ else if (renderInfo.textureInfo->getSharedTextureMode() == EglImageMode)
+ device = getDeviceForBaseTileFBO(renderInfo);
+
+ // TODO only need to reset if others are sharing our context
+ if (device)
+ getGrContext()->resetContext();
+
+ return device;
+}
+
+SkDevice* GaneshContext::getDeviceForBaseTileSurface(const TileRenderInfo& renderInfo)
+{
+ EGLDisplay display = eglGetCurrentDisplay();
+ GLUtils::checkEglError("eglGetCurrentDisplay");
+
+ if (!m_surfaceContext) {
+
+ EGLint numConfigs;
+ static const EGLint configAttribs[] = {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_STENCIL_SIZE, 8,
+ EGL_NONE
+ };
+
+ eglChooseConfig(display, configAttribs, &m_surfaceConfig, 1, &numConfigs);
+ GLUtils::checkEglError("eglChooseConfig");
+
+ static const EGLint contextAttribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ m_surfaceContext = eglCreateContext(display, m_surfaceConfig, NULL, contextAttribs);
+ GLUtils::checkEglError("eglCreateContext");
+ }
+
+ if (renderInfo.textureInfo->m_eglSurface == EGL_NO_SURFACE) {
+
+ const float tileWidth = renderInfo.tileSize.width();
+ const float tileHeight = renderInfo.tileSize.height();
+ ANativeWindow* anw = renderInfo.textureInfo->m_ANW.get();
+
+ int result = ANativeWindow_setBuffersGeometry(anw, (int)tileWidth,
+ (int)tileHeight, WINDOW_FORMAT_RGBA_8888);
+
+ renderInfo.textureInfo->m_width = tileWidth;
+ renderInfo.textureInfo->m_height = tileHeight;
+ renderInfo.textureInfo->m_eglSurface = eglCreateWindowSurface(display, m_surfaceConfig, anw, NULL);
+
+ GLUtils::checkEglError("eglCreateWindowSurface");
+ XLOG("eglCreateWindowSurface");
+ }
+
+ EGLBoolean returnValue = eglMakeCurrent(display, renderInfo.textureInfo->m_eglSurface, renderInfo.textureInfo->m_eglSurface, m_surfaceContext);
+ GLUtils::checkEglError("eglMakeCurrent", returnValue);
+ XLOG("eglMakeCurrent");
+
+ if (!m_baseTileDeviceSurface) {
+
+ GrPlatformSurfaceDesc surfaceDesc;
+ surfaceDesc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
+ surfaceDesc.fRenderTargetFlags = kNone_GrPlatformRenderTargetFlagBit;
+ surfaceDesc.fWidth = TilesManager::tileWidth();
+ surfaceDesc.fHeight = TilesManager::tileHeight();
+ surfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ surfaceDesc.fStencilBits = 8;
+ surfaceDesc.fPlatformRenderTarget = 0;
+
+ GrContext* grContext = getGrContext();
+ GrRenderTarget* renderTarget = (GrRenderTarget*) grContext->createPlatformSurface(surfaceDesc);
+
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ renderInfo.tileSize.width(),
+ renderInfo.tileSize.height());
+
+ m_baseTileDeviceSurface = new SkGpuDevice(grContext, bitmap, renderTarget);
+ renderTarget->unref();
+ XLOG("generated device %p", m_baseTileDeviceSurface);
+ }
+
+ GLUtils::checkGlError("getDeviceForBaseTile");
+ return m_baseTileDeviceSurface;
+}
+
+SkDevice* GaneshContext::getDeviceForBaseTileFBO(const TileRenderInfo& renderInfo)
{
- if (!m_baseTileFbo) {
- glGenFramebuffers(1, &m_baseTileFbo);
+ const GLuint textureId = renderInfo.textureInfo->m_textureId;
+ const float tileWidth = renderInfo.tileSize.width();
+ const float tileHeight = renderInfo.tileSize.height();
+
+ // bind to the current texture
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ // setup the texture if needed
+ if (renderInfo.textureInfo->m_width != tileWidth
+ || renderInfo.textureInfo->m_height != tileHeight) {
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tileWidth, tileHeight,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ renderInfo.textureInfo->m_width = tileWidth;
+ renderInfo.textureInfo->m_height = tileHeight;
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+
+ if (!m_baseTileFBO) {
+ glGenFramebuffers(1, &m_baseTileFBO);
XLOG("generated FBO");
}
XLOG("generated stencil");
}
- glBindFramebuffer(GL_FRAMEBUFFER, m_baseTileFbo);
+ // bind the FBO and attach the texture and stencil
+ glBindFramebuffer(GL_FRAMEBUFFER, m_baseTileFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_baseTileStencil);
- if (!m_baseTileDevice) {
+ if (!m_baseTileDeviceFBO) {
GrPlatformSurfaceDesc surfaceDesc;
surfaceDesc.fSurfaceType = kRenderTarget_GrPlatformSurfaceType;
surfaceDesc.fRenderTargetFlags = kNone_GrPlatformRenderTargetFlagBit;
surfaceDesc.fWidth = TilesManager::tileWidth();
- surfaceDesc.fHeight = TilesManager::tileWidth();
+ surfaceDesc.fHeight = TilesManager::tileHeight();
surfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
surfaceDesc.fStencilBits = 8;
- surfaceDesc.fPlatformRenderTarget = m_baseTileFbo;
+ surfaceDesc.fPlatformRenderTarget = m_baseTileFBO;
GrContext* grContext = getGrContext();
GrRenderTarget* renderTarget = (GrRenderTarget*) grContext->createPlatformSurface(surfaceDesc);
bitmap.setConfig(SkBitmap::kARGB_8888_Config,
TilesManager::tileWidth(), TilesManager::tileWidth());
- m_baseTileDevice = new SkGpuDevice(grContext, bitmap, renderTarget);
+ m_baseTileDeviceFBO = new SkGpuDevice(grContext, bitmap, renderTarget);
renderTarget->unref();
- XLOG("generated device %p", m_baseTileDevice);
+ XLOG("generated device %p", m_baseTileDeviceFBO);
}
GLUtils::checkGlError("getDeviceForBaseTile");
- return m_baseTileDevice;
+ return m_baseTileDeviceFBO;
}
-
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
#if USE(ACCELERATED_COMPOSITING)
+#include "BaseRenderer.h"
#include "GrContext.h"
#include "SkGpuDevice.h"
#include "TilesManager.h"
public:
static GaneshContext* instance();
- GrContext* getGrContext();
+ SkDevice* getDeviceForBaseTile(const TileRenderInfo& renderInfo);
- SkDevice* getDeviceForBaseTile(GLuint textureId);
+ void flush();
private:
GaneshContext();
+ GrContext* getGrContext();
+
+ // Creates a device for rendering into a SurfaceTexture via an EGLSurface
+ SkDevice* getDeviceForBaseTileSurface(const TileRenderInfo& renderInfo);
+ // Creates a device for rendering into a EGLImage via an FBO
+ SkDevice* getDeviceForBaseTileFBO(const TileRenderInfo& renderInfo);
+
GrContext* m_grContext;
- SkGpuDevice* m_baseTileDevice;
- GLuint m_baseTileFbo;
+
+ // FBO specific variables
+ SkGpuDevice* m_baseTileDeviceFBO;
+ GLuint m_baseTileFBO;
GLuint m_baseTileStencil;
+ // Surface specific variables
+ SkGpuDevice* m_baseTileDeviceSurface;
+ EGLConfig m_surfaceConfig;
+ EGLContext m_surfaceContext;
+
static GaneshContext* gInstance;
};
#include "SkGpuDevice.h"
#include "TilesManager.h"
-#include <wtf/text/CString.h>
#ifdef DEBUG
#include <cutils/log.h>
#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
#undef XLOG
#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GaneshRenderer", __VA_ARGS__)
TAG_UPDATE_TEXTURE,
};
-GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Raster)
+GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Ganesh)
{
#ifdef DEBUG_COUNT
ClassTracker::instance()->increment("GaneshRenderer");
if (renderInfo.measurePerf)
m_perfMon.start(TAG_CREATE_FBO);
- const float tileWidth = renderInfo.tileSize.width();
- const float tileHeight = renderInfo.tileSize.height();
-
- glBindTexture(GL_TEXTURE_2D, renderInfo.textureInfo->m_textureId);
-
- // setup the texture if needed
- if (renderInfo.textureInfo->m_width != tileWidth
- || renderInfo.textureInfo->m_height != tileHeight) {
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tileWidth, tileHeight,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- renderInfo.textureInfo->m_width = tileWidth;
- renderInfo.textureInfo->m_height = tileHeight;
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
GaneshContext* ganesh = GaneshContext::instance();
- // TODO only need to reset if others are sharing our context
- ganesh->getGrContext()->resetContext();
-
SkDevice* device = NULL;
- if (tileWidth == TilesManager::tileWidth() && tileHeight == TilesManager::tileHeight()) {
- device = ganesh->getDeviceForBaseTile(renderInfo.textureInfo->m_textureId);
+ if (renderInfo.tileSize.width() == TilesManager::tileWidth()
+ && renderInfo.tileSize.height() == TilesManager::tileHeight()) {
+ device = ganesh->getDeviceForBaseTile(renderInfo);
} else {
// TODO support arbitrary sizes for layers
XLOG("ERROR: expected (%d,%d) actual (%d,%d)",
TilesManager::tileWidth(), TilesManager::tileHeight(),
- tileWidth, tileHeight);
+ renderInfo.tileSize.width(), renderInfo.tileSize.height());
}
if (renderInfo.measurePerf) {
canvas->setDevice(device);
// invert canvas contents
- canvas->scale(SK_Scalar1, -SK_Scalar1);
- canvas->translate(0, -SkIntToScalar(renderInfo.tileSize.height()));
+ if (renderInfo.textureInfo->getSharedTextureMode() == EglImageMode) {
+ canvas->scale(SK_Scalar1, -SK_Scalar1);
+ canvas->translate(0, -renderInfo.tileSize.height());
+ }
}
void GaneshRenderer::setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas)
m_perfMon.start(TAG_UPDATE_TEXTURE);
}
- GaneshContext::instance()->getGrContext()->flush();
+ XLOG("rendered to tile (%d,%d)", renderInfo.x, renderInfo.y);
+
+ GaneshContext::instance()->flush();
- //TODO if texture is surfaceTexture then...
+ // In SurfaceTextureMode we must call swapBuffers to unlock and post the
+ // tile's ANativeWindow (i.e. SurfaceTexture) buffer
+ if (renderInfo.textureInfo->getSharedTextureMode() == SurfaceTextureMode) {
+ eglSwapBuffers(eglGetCurrentDisplay(), renderInfo.textureInfo->m_eglSurface);
+ }
if (renderInfo.measurePerf)
m_perfMon.stop(TAG_UPDATE_TEXTURE);
glGenTextures(1, &m_sourceTexture->m_textureId);
m_sourceTexture->m_surfaceTexture =
- new android::SurfaceTexture(m_sourceTexture->m_textureId);
+ new android::SurfaceTexture(m_sourceTexture->m_textureId, false);
m_sourceTexture->m_ANW =
new android::SurfaceTextureClient(m_sourceTexture->m_surfaceTexture);
-
- m_sourceTexture->m_surfaceTexture->setSynchronousMode(false);
}
}
m_height = 0;
m_internalFormat = 0;
m_sharedTextureMode = mode;
+ m_eglSurface = EGL_NO_SURFACE;
}
bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture)
#ifndef TextureInfo_h
#define TextureInfo_h
+#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <jni.h>
#include <ui/GraphicBuffer.h>
sp<android::SurfaceTexture> m_surfaceTexture;
sp<ANativeWindow> m_ANW;
+ // The EGLSurface wraps the m_ANW to enable direct OpenGL rendering (e.g. Ganesh)
+ EGLSurface m_eglSurface;
+
private:
SharedTextureMode m_sharedTextureMode;
};
TilesManager::instance()->setExpandedTileBounds(enabled);
}
+static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled)
+{
+ BaseRenderer::setCurrentRendererType(enabled ? BaseRenderer::Ganesh : BaseRenderer::Raster);
+}
+
static int nativeGetBackgroundColor(JNIEnv* env, jobject obj)
{
WebView* view = GET_NATIVE_VIEW(env, obj);
(void*) nativeScrollLayer },
{ "nativeSetExpandedTileBounds", "(Z)V",
(void*) nativeSetExpandedTileBounds },
+ { "nativeUseHardwareAccelSkia", "(Z)V",
+ (void*) nativeUseHardwareAccelSkia },
{ "nativeGetBackgroundColor", "()I",
(void*) nativeGetBackgroundColor },
{ "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)V",