Skip to content

Commit

Permalink
Add features to support Ganesh in the Android browser
Browse files Browse the repository at this point in the history
1) Added a runtime switch between Raster and Ganesh
2) Added support for using SurfaceTextures with Ganesh

bug: 5013645
Change-Id: I2efebf1bc9befb0c7f6f66109d80818f9d0775b3
  • Loading branch information
drWulf committed Jul 28, 2011
1 parent 14a561b commit c7e5783
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 50 deletions.
1 change: 1 addition & 0 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ LOCAL_LDLIBS += -lpthread -ldl

# Build the list of shared libraries
LOCAL_SHARED_LIBRARIES := \
libandroid \
libandroid_runtime \
libnativehelper \
libsqlite \
Expand Down
22 changes: 22 additions & 0 deletions Source/WebCore/platform/graphics/android/BaseRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@

#if USE(ACCELERATED_COMPOSITING)

#include "GaneshRenderer.h"
#include "GLUtils.h"
#include "RasterRenderer.h"
#include "SkBitmap.h"
#include "SkBitmapRef.h"
#include "SkCanvas.h"
Expand All @@ -56,6 +58,26 @@

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)
{
Expand Down
6 changes: 6 additions & 0 deletions Source/WebCore/platform/graphics/android/BaseRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ class BaseRenderer {

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;
Expand All @@ -96,6 +101,7 @@ class BaseRenderer {

private:
RendererType m_type;
static RendererType g_currentType;
};

} // namespace WebCore
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/platform/graphics/android/BaseTile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ BaseTile::BaseTile(bool isLayerTile)
m_fullRepaint = new bool[m_maxBufferNumber];
for (int i = 0; i < m_maxBufferNumber; i++)
m_fullRepaint[i] = true;

m_renderer = BaseRenderer::createRenderer();
}

BaseTile::~BaseTile()
Expand Down Expand Up @@ -306,6 +308,9 @@ void BaseTile::paintBitmap()

unsigned int pictureCount = 0;

// swap out the renderer if necessary
BaseRenderer::swapRendererIfNeeded(m_renderer);

// setup the common renderInfo fields;
TileRenderInfo renderInfo;
renderInfo.x = x;
Expand Down
151 changes: 138 additions & 13 deletions Source/WebCore/platform/graphics/android/GaneshContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "GaneshContext.h"
#include "GLUtils.h"

#include "android/native_window.h"

#if USE(ACCELERATED_COMPOSITING)

#ifdef DEBUG
Expand All @@ -49,9 +51,12 @@ namespace WebCore {

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)
{
}

Expand All @@ -72,10 +77,130 @@ GrContext* GaneshContext::getGrContext()
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");
}

Expand All @@ -90,20 +215,21 @@ SkDevice* GaneshContext::getDeviceForBaseTile(GLuint textureId)
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);
Expand All @@ -112,17 +238,16 @@ SkDevice* GaneshContext::getDeviceForBaseTile(GLuint textureId)
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)
23 changes: 19 additions & 4 deletions Source/WebCore/platform/graphics/android/GaneshContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#if USE(ACCELERATED_COMPOSITING)

#include "BaseRenderer.h"
#include "GrContext.h"
#include "SkGpuDevice.h"
#include "TilesManager.h"
Expand All @@ -38,19 +39,33 @@ class GaneshContext {
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;
};

Expand Down
Loading

0 comments on commit c7e5783

Please sign in to comment.