OSDN Git Service

Merge "Add features to support Ganesh in the Android browser"
authorDerek Sollenberger <djsollen@google.com>
Fri, 29 Jul 2011 19:34:24 +0000 (12:34 -0700)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Fri, 29 Jul 2011 19:34:24 +0000 (12:34 -0700)
Android.mk
Source/WebCore/platform/graphics/android/BaseRenderer.cpp
Source/WebCore/platform/graphics/android/BaseRenderer.h
Source/WebCore/platform/graphics/android/BaseTile.cpp
Source/WebCore/platform/graphics/android/GaneshContext.cpp
Source/WebCore/platform/graphics/android/GaneshContext.h
Source/WebCore/platform/graphics/android/GaneshRenderer.cpp
Source/WebCore/platform/graphics/android/SharedTexture.cpp
Source/WebCore/platform/graphics/android/TextureInfo.cpp
Source/WebCore/platform/graphics/android/TextureInfo.h
Source/WebKit/android/nav/WebView.cpp

index c6d8a01..623a35f 100644 (file)
@@ -362,6 +362,7 @@ LOCAL_LDLIBS += -lpthread -ldl
 
 # Build the list of shared libraries
 LOCAL_SHARED_LIBRARIES := \
+       libandroid \
        libandroid_runtime \
        libnativehelper \
        libsqlite \
index 4fde188..ea6c8ec 100644 (file)
@@ -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"
 
 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)
 {
index 0ee9ebd..7780db1 100644 (file)
@@ -80,6 +80,11 @@ public:
 
     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;
@@ -96,6 +101,7 @@ protected:
 
 private:
     RendererType m_type;
+    static RendererType g_currentType;
 };
 
 } // namespace WebCore
index 4cbcf7c..6ab2cd2 100644 (file)
@@ -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()
@@ -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;
index b316e5a..6118aef 100644 (file)
@@ -28,6 +28,8 @@
 #include "GaneshContext.h"
 #include "GLUtils.h"
 
+#include "android/native_window.h"
+
 #if USE(ACCELERATED_COMPOSITING)
 
 #ifdef DEBUG
@@ -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)
 {
 }
 
@@ -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");
     }
 
@@ -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);
@@ -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)
index 9d90b96..12ea92d 100644 (file)
@@ -28,6 +28,7 @@
 
 #if USE(ACCELERATED_COMPOSITING)
 
+#include "BaseRenderer.h"
 #include "GrContext.h"
 #include "SkGpuDevice.h"
 #include "TilesManager.h"
@@ -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;
 };
 
index fcb0675..8f4d0b3 100644 (file)
 #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__)
@@ -63,7 +63,7 @@ static const String TAGS[] = {
     TAG_UPDATE_TEXTURE,
 };
 
-GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Raster)
+GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Ganesh)
 {
 #ifdef DEBUG_COUNT
     ClassTracker::instance()->increment("GaneshRenderer");
@@ -82,37 +82,17 @@ void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can
     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) {
@@ -124,8 +104,10 @@ void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can
     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)
@@ -145,9 +127,15 @@ void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanva
         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);
index 4f52107..a7d43b5 100644 (file)
@@ -60,11 +60,9 @@ SharedTexture::SharedTexture(SharedTextureMode mode)
         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);
     }
 }
 
index 849e6fc..5db1711 100644 (file)
@@ -42,6 +42,7 @@ TextureInfo::TextureInfo(SharedTextureMode mode)
     m_height = 0;
     m_internalFormat = 0;
     m_sharedTextureMode = mode;
+    m_eglSurface = EGL_NO_SURFACE;
 }
 
 bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture)
index 252d288..c1cb1cd 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef TextureInfo_h
 #define TextureInfo_h
 
+#include <EGL/egl.h>
 #include <GLES2/gl2.h>
 #include <jni.h>
 #include <ui/GraphicBuffer.h>
@@ -70,6 +71,9 @@ public:
     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;
 };
index 77ac2ae..69d1ee8 100644 (file)
@@ -2606,6 +2606,11 @@ static void nativeSetExpandedTileBounds(JNIEnv*, jobject, jboolean enabled)
     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);
@@ -2815,6 +2820,8 @@ static JNINativeMethod gJavaWebViewMethods[] = {
         (void*) nativeScrollLayer },
     { "nativeSetExpandedTileBounds", "(Z)V",
         (void*) nativeSetExpandedTileBounds },
+    { "nativeUseHardwareAccelSkia", "(Z)V",
+        (void*) nativeUseHardwareAccelSkia },
     { "nativeGetBackgroundColor", "()I",
         (void*) nativeGetBackgroundColor },
     { "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)V",