Update tile partially
authorEunsol Park <eunsol47.park@samsung.com>
Fri, 26 Apr 2013 07:52:54 +0000 (16:52 +0900)
committerGerrit Code Review <gerrit2@kim11>
Fri, 26 Apr 2013 08:33:41 +0000 (17:33 +0900)
    [Title] Update tile partially
    [Issue#] N/A
    [Problem] BrowserMark2 CSS 2D Transform test result is behind competitors.
    [Cause] Painting takes too long due to whole tile update.
    [Solution] Copy painted tile to empty tile and paint only dirty area.

Change-Id: I472a9933e47a0d9dd6000ff5b01462a42126d315

Source/WebKit2/WebProcess/WebPage/efl/tizen/PlatformSurfacePoolTizen.cpp
Source/WebKit2/WebProcess/WebPage/efl/tizen/PlatformSurfacePoolTizen.h
Source/WebKit2/WebProcess/WebPage/efl/tizen/TiledBackingStoreRemoteTileTizen.cpp
Source/WebKit2/WebProcess/WebPage/efl/tizen/TiledBackingStoreRemoteTileTizen.h

index 7051b51..c6ce2a4 100644 (file)
@@ -132,6 +132,14 @@ SharedPlatformSurfaceTizen* PlatformSurfacePoolTizen::acquirePlatformSurface(con
     return 0;
 }
 
+SharedPlatformSurfaceTizen* PlatformSurfacePoolTizen::acquirePlatformSurfaceByID(int platformSurfaceId)
+{
+    PlatformSurfaceMap::iterator foundSurface = m_platformSurfaces.find(platformSurfaceId);
+    if (foundSurface == m_platformSurfaces.end())
+        return 0;
+    return foundSurface->second->m_SharedPlatformSurfaceTizen.get();
+}
+
 void PlatformSurfacePoolTizen::freePlatformSurfaceByTileID(int tileID)
 {
     int platformSurfaceId = 0;
index 2d37190..b5ba35e 100644 (file)
@@ -50,6 +50,7 @@ public :
     PlatformSurfacePoolTizen();
     ~PlatformSurfacePoolTizen();
     SharedPlatformSurfaceTizen* acquirePlatformSurface(const WebCore::IntSize&, int tileID);
+    SharedPlatformSurfaceTizen* acquirePlatformSurfaceByID(int platformSurfaceId);
     void freePlatformSurface(int platformSurfaceId);
     void freePlatformSurfaceByTileID(int tileID);
     void removePlatformSurface(int platformSurfaceId);
index 27fcb5f..bf5505d 100644 (file)
@@ -49,6 +49,13 @@ TiledBackingStoreRemoteTileTizen::TiledBackingStoreRemoteTileTizen(TiledBackingS
 {
 }
 
+static inline bool needUpdateBackBufferPartially(const IntRect& entireRect, const IntRect& dirtyRect)
+{
+    if (entireRect.size() != dirtyRect.size())
+        return true;
+    return false;
+}
+
 Vector<IntRect> TiledBackingStoreRemoteTileTizen::updateBackBuffer()
 {
     if (!isDirty())
@@ -63,7 +70,7 @@ Vector<IntRect> TiledBackingStoreRemoteTileTizen::updateBackBuffer()
         needToCreateTile = true;
     }
 
-    if (!m_tiledBackingStoreRemoteTileBufferTizen->drawPlatformSurface(m_tiledBackingStore->tileSize(), m_rect, m_ID))
+    if (!m_tiledBackingStoreRemoteTileBufferTizen->drawPlatformSurface(m_tiledBackingStore->tileSize(), m_dirtyRect, m_ID))
         return Vector<IntRect>();
 
     updateInfo.updateRect = m_rect;
@@ -105,7 +112,72 @@ void TiledBackingStoreRemoteTileTizen::review()
     m_client->createTile(m_ID, updateInfo, m_rect);
 }
 
-bool TiledBackingStoreRemoteTileBufferTizen::drawPlatformSurface(const IntSize& size, const IntRect& dirty, int tileID)
+void TiledBackingStoreRemoteTileBufferTizen::copyDirtyRect(unsigned char* dst, unsigned char* src, const IntRect& wholeRect, const IntRect& dirtyRect)
+{
+    unsigned int offset = 4 * wholeRect.width() * (dirtyRect.y() - wholeRect.y()) + 4 * (dirtyRect.x() - wholeRect.x());
+
+    //FIXME : Now, handling row datas directly performs better than using Cairo APIs.
+    //This will be replaced to Cairo APIs if using Cairo APIs perform better.
+
+    for (int i = 0; i < dirtyRect.height(); i++) {
+        memcpy(dst + offset, src + (4 * i * dirtyRect.width()), 4 * dirtyRect.width());
+        offset += 4* wholeRect.width();
+    }
+}
+
+bool TiledBackingStoreRemoteTileBufferTizen::copyPreviousFrame(unsigned char* dst, int platformSurfaceID, const IntRect& wholeRect, const IntRect& clipRect)
+{
+    SharedPlatformSurfaceTizen* backupSurface;
+    unsigned int offset;
+    unsigned char* src;
+
+    PlatformSurfacePoolTizen* platformSurfacePool = WebProcess::shared().platformSurfacePool();
+    if(!platformSurfacePool)
+        return false;
+
+    backupSurface = platformSurfacePool->acquirePlatformSurfaceByID(platformSurfaceID);
+    if (!backupSurface)
+        return false;
+
+    if (!backupSurface->lockSurface())
+        return false;
+
+    if (!backupSurface->querySurface((int*)&src)) {
+        backupSurface->unlockSurface();
+        return false;
+    }
+
+    //FIXME : Now, handling row datas directly performs better than using Cairo APIs.
+    //This will be replaced to Cairo APIs if using Cairo APIs perform better.
+
+    // upper side
+    if (clipRect.y() -wholeRect.y() > 0)
+        memcpy(dst, src, 4 * wholeRect.width() * (clipRect.y() -wholeRect.y()));
+
+    if (wholeRect.width() - clipRect.width() > 0) {
+        offset = 4 * (clipRect.y() - wholeRect.y()) * wholeRect.width();
+        for (int i = 0; i < clipRect.height(); i++) {
+            // left side
+            if (clipRect.x() - wholeRect.x() > 0)
+                memcpy(dst + offset, src + offset, 4 * (clipRect.x() - wholeRect.x()));
+
+            // right side
+            if (wholeRect.maxX() - clipRect.maxX() > 0)
+                memcpy(dst + offset + 4 * (clipRect.maxX() - wholeRect.x()),
+                src + offset + 4 * (clipRect.maxX() - wholeRect.x()), 4 * (wholeRect.maxX() - clipRect.maxX()));
+            offset += 4 * wholeRect.width();
+        }
+    }
+    // lower side
+    if (wholeRect.maxY() - clipRect.maxY() > 0) {
+        offset = 4 * wholeRect.width() * (clipRect.maxY() - wholeRect.y());
+        memcpy(dst + offset, src + offset, 4 * wholeRect.width() * (wholeRect.maxY() - clipRect.maxY()));
+    }
+    backupSurface->unlockSurface();
+    return true;
+}
+
+bool TiledBackingStoreRemoteTileBufferTizen::drawPlatformSurface(const IntSize& size, const IntRect& dirtyRect, int tileID)
 {
     PlatformSurfacePoolTizen* platformSurfacePool = WebProcess::shared().platformSurfacePool();
     if(!platformSurfacePool)
@@ -119,16 +191,42 @@ bool TiledBackingStoreRemoteTileBufferTizen::drawPlatformSurface(const IntSize&
         platformSurfacePool->freePlatformSurface(sharedPlatformSurface->id());
         return false;
     }
-    if (!sharedPlatformSurface->querySurface((int*)&m_eglImgData)) {
+
+    unsigned char* dstBuffer;
+    unsigned char* dirtyBuffer;
+    RefPtr<cairo_surface_t> dstSurface, dirtySurface;
+    RefPtr<cairo_t> dstBitmapContext, dirtyBitmapContext;
+    OwnPtr<WebCore::GraphicsContext> graphicsContext;
+    IntRect paintRect = m_rect;
+    bool canPartiallyUpdate = false;
+
+    if (!sharedPlatformSurface->querySurface((int*)&dstBuffer)) {
         sharedPlatformSurface->unlockSurface();
         platformSurfacePool->freePlatformSurface(sharedPlatformSurface->id());
         return false;
     }
-    RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data(static_cast<unsigned char*>(m_eglImgData), CAIRO_FORMAT_ARGB32,
+
+    dstSurface = adoptRef(cairo_image_surface_create_for_data(dstBuffer, CAIRO_FORMAT_ARGB32,
         sharedPlatformSurface->size().width(), sharedPlatformSurface->size().height(), 4 * sharedPlatformSurface->size().width()));
-    RefPtr<cairo_t> bitmapContext = adoptRef(cairo_create(surface.get()));
 
-    OwnPtr<WebCore::GraphicsContext> graphicsContext = adoptPtr(new GraphicsContext(bitmapContext.get()));
+    if (m_platformSurfaceID > 0 && needUpdateBackBufferPartially(m_rect, dirtyRect)
+        && copyPreviousFrame(dstBuffer, m_platformSurfaceID, IntRect(m_rect.location(), sharedPlatformSurface->size()), dirtyRect)) {
+        paintRect = dirtyRect;
+        canPartiallyUpdate = true;
+    }
+
+    if (canPartiallyUpdate) {
+        dirtyBuffer = (unsigned char*) malloc(4 * dirtyRect.width() * dirtyRect.height());
+        dirtySurface = adoptRef(cairo_image_surface_create_for_data(dirtyBuffer, CAIRO_FORMAT_ARGB32, dirtyRect.width(), dirtyRect.height(), 4 * dirtyRect.width()));
+        dirtyBitmapContext = adoptRef(cairo_create(dirtySurface.get()));
+        graphicsContext = adoptPtr(new GraphicsContext(dirtyBitmapContext.get()));
+        graphicsContext->clearRect(WebCore::FloatRect(WebCore::FloatPoint(0, 0), dirtyRect.size()));
+    } else {
+        dstBitmapContext = adoptRef(cairo_create(dstSurface.get()));
+        graphicsContext = adoptPtr(new GraphicsContext(dstBitmapContext.get()));
+        graphicsContext->clearRect(WebCore::FloatRect(WebCore::FloatPoint(0, 0), sharedPlatformSurface->size()));
+    }
+
 #if ENABLE(TIZEN_WEBKIT2_DEBUG_BORDERS)
     double startTime = 0;
     double endTime = 0;
@@ -137,7 +235,6 @@ bool TiledBackingStoreRemoteTileBufferTizen::drawPlatformSurface(const IntSize&
         startTime = currentTime();
     }
 #endif
-    graphicsContext->clearRect(WebCore::FloatRect(WebCore::FloatPoint(0, 0), sharedPlatformSurface->size()));
 
 #if ENABLE(TIZEN_RECORDING_SURFACE_SET)
     if (m_tiledBackingStore->client()->recordingSurfaceSetEnableGet()) {
@@ -145,9 +242,17 @@ bool TiledBackingStoreRemoteTileBufferTizen::drawPlatformSurface(const IntSize&
     } else
 #endif
     {
-        graphicsContext->translate(-m_rect.x(), -m_rect.y());
+        graphicsContext->translate(-paintRect.x(), -paintRect.y());
         graphicsContext->scale(FloatSize(m_tiledBackingStore->contentsScale(), m_tiledBackingStore->contentsScale()));
-        m_tiledBackingStore->client()->tiledBackingStorePaint(graphicsContext.get(), m_tiledBackingStore->mapToContents(dirty));
+        m_tiledBackingStore->client()->tiledBackingStorePaint(graphicsContext.get(), m_tiledBackingStore->mapToContents(paintRect));
+    }
+
+    if (canPartiallyUpdate) {
+        copyDirtyRect(dstBuffer, dirtyBuffer, IntRect(m_rect.location(), sharedPlatformSurface->size()), dirtyRect);
+        dstBitmapContext = adoptRef(cairo_create(dstSurface.get()));
+        free(dirtyBuffer);
+        dirtySurface.release();
+        dirtyBitmapContext.release();
     }
 
     m_platformSurfaceID = sharedPlatformSurface->id();
@@ -161,14 +266,17 @@ bool TiledBackingStoreRemoteTileBufferTizen::drawPlatformSurface(const IntSize&
         char tileInfo[256];
         int fontSize = 15;
         snprintf(tileInfo, 256, "[%d] %.1fms (%d,%d / %dX%d)", m_platformSurfaceID, (endTime - startTime) * 1000, m_rect.x(), m_rect.y(), m_platformSurfaceSize.width(), m_platformSurfaceSize.height());
-        cairo_set_source_rgb(bitmapContext.get(), 0.0, 0.0, 1.0);
-        cairo_select_font_face(bitmapContext.get(), "", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
-        cairo_set_font_size(bitmapContext.get(), fontSize);
-        cairo_move_to(bitmapContext.get(), 0, fontSize);
-        cairo_show_text(bitmapContext.get(), tileInfo);
+        cairo_set_source_rgb(dstBitmapContext.get(), 0.0, 0.0, 1.0);
+        cairo_select_font_face(dstBitmapContext.get(), "", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+        cairo_set_font_size(dstBitmapContext.get(), fontSize);
+        cairo_move_to(dstBitmapContext.get(), 0, fontSize);
+        cairo_show_text(dstBitmapContext.get(), tileInfo);
     }
 #endif
-     if (!sharedPlatformSurface->unlockSurface())
+    dstBitmapContext.release();
+    graphicsContext.release();
+
+    if (!sharedPlatformSurface->unlockSurface())
         return false;
     return true;
 }
index c039949..62c4652 100644 (file)
@@ -40,7 +40,6 @@ class TiledBackingStoreRemoteTileBufferTizen {
 public:
     TiledBackingStoreRemoteTileBufferTizen(TiledBackingStoreRemoteTileClient* client, WebCore::TiledBackingStore* tiledBackingStore, IntRect rect)
         : m_platformSurfaceID(0)
-        , m_eglImgData(0)
         , m_client(client)
         , m_tiledBackingStore(tiledBackingStore)
         , m_rect(rect) { };
@@ -49,9 +48,10 @@ public:
     void resize(const WebCore::IntSize& size) { m_rect.setSize(size); }
     IntSize platformSurfaceSize() { return m_platformSurfaceSize; }
 private:
+    void copyDirtyRect(unsigned char* dst, unsigned char* src, const IntRect& wholeRect, const IntRect& dirtyRect);
+    bool copyPreviousFrame(unsigned char* dst, int platformSurfaceID, const IntRect& wholeRect, const IntRect& clipRect);
     int m_platformSurfaceID;
     IntSize m_platformSurfaceSize;
-    unsigned char* m_eglImgData;
     TiledBackingStoreRemoteTileClient* m_client;
     WebCore::TiledBackingStore* m_tiledBackingStore;
     IntRect m_rect;
@@ -72,7 +72,6 @@ public:
 
 private:
     TiledBackingStoreRemoteTileTizen(TiledBackingStoreRemoteTileClient*, WebCore::TiledBackingStore*, const Coordinate&);
-
     OwnPtr<TiledBackingStoreRemoteTileBufferTizen> m_tiledBackingStoreRemoteTileBufferTizen;
 };