Title: [124199] trunk/Source/WebKit/blackberry
Revision
124199
Author
commit-qu...@webkit.org
Date
2012-07-31 07:35:24 -0700 (Tue, 31 Jul 2012)

Log Message

[BlackBerry] Backing store output flickers when using WebPageCompositor
https://bugs.webkit.org/show_bug.cgi?id=90291

Patch by Arvid Nilsson <anils...@rim.com> on 2012-07-31
Reviewed by Antonio Gomes.

The backing store doesn't know when the API client swaps the buffers,
so it doesn't know when to signal the blit generation condition
variable. Fixed by using EGL fence sync instead, when available, so we
don't have to know.

Reviewed internally by Filip Spacek.

* Api/BackingStore.cpp:
(BlackBerry::WebKit::BackingStorePrivate::BackingStorePrivate):
(BlackBerry::WebKit::BackingStorePrivate::~BackingStorePrivate):
(BlackBerry::WebKit::BackingStorePrivate::render):
(BlackBerry::WebKit::BackingStorePrivate::blitContents):
(BlackBerry::WebKit::BackingStorePrivate::compositeContents):
* Api/BackingStore_p.h:
(BackingStorePrivate):
* WebKitSupport/BackingStoreTile.cpp:
(BlackBerry::WebKit::TileBuffer::TileBuffer):
* WebKitSupport/BackingStoreTile.h:
(BlackBerry::WebKit::TileBuffer::syncObject):
(BlackBerry::WebKit::TileBuffer::setSyncObject):
(TileBuffer):
* WebKitSupport/SurfacePool.cpp:
(WebKit):
(BlackBerry::WebKit::SurfacePool::SurfacePool):
(BlackBerry::WebKit::SurfacePool::initialize):
(BlackBerry::WebKit::SurfacePool::waitForBuffer):
(BlackBerry::WebKit::SurfacePool::notifyBuffersComposited):
* WebKitSupport/SurfacePool.h:
(SurfacePool):

Modified Paths

Diff

Modified: trunk/Source/WebKit/blackberry/Api/BackingStore.cpp (124198 => 124199)


--- trunk/Source/WebKit/blackberry/Api/BackingStore.cpp	2012-07-31 13:50:39 UTC (rev 124198)
+++ trunk/Source/WebKit/blackberry/Api/BackingStore.cpp	2012-07-31 14:35:24 UTC (rev 124199)
@@ -209,7 +209,6 @@
     , m_hasBlitJobs(false)
     , m_currentWindowBackBuffer(0)
     , m_preferredTileMatrixDimension(Vertical)
-    , m_blitGeneration(-1)
 #if USE(ACCELERATED_COMPOSITING)
     , m_needsDrawLayersOnCommit(false)
     , m_isDirectRenderingAnimationMessageScheduled(false)
@@ -226,14 +225,6 @@
     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
     pthread_mutex_init(&m_mutex, &attr);
     pthread_mutexattr_destroy(&attr);
-
-    pthread_mutex_init(&m_blitGenerationLock, 0);
-
-    pthread_condattr_t condattr;
-    pthread_condattr_init(&condattr);
-    pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
-    pthread_cond_init(&m_blitGenerationCond, &condattr);
-    pthread_condattr_destroy(&condattr);
 }
 
 BackingStorePrivate::~BackingStorePrivate()
@@ -246,8 +237,6 @@
     delete back;
     m_backState = 0;
 
-    pthread_cond_destroy(&m_blitGenerationCond);
-    pthread_mutex_destroy(&m_blitGenerationLock);
     pthread_mutex_destroy(&m_mutex);
 }
 
@@ -1141,26 +1130,11 @@
         BlackBerry::Platform::Graphics::Buffer* nativeBuffer
             = tile->backBuffer()->nativeBuffer();
 
-        // This code is only needed for EGLImage code path, and only effective if we are swapping the render target.
-        // This combination is only true if there's a GLES2Usage window.
-        // FIXME: Use an EGL fence instead, PR152132
-        Window* window = m_webPage->client()->window();
-        if (window && window->windowUsage() == Window::GLES2Usage) {
-            pthread_mutex_lock(&m_blitGenerationLock);
-            while (m_blitGeneration == tile->backBuffer()->blitGeneration()) {
-                int err = pthread_cond_timedwait(&m_blitGenerationCond, &m_blitGenerationLock, &m_currentBlitEnd);
-                if (err == ETIMEDOUT) {
-                    ++m_blitGeneration;
-                    break;
-                }
-                if (err) {
-                    BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical,
-                                              "cond_timedwait failed (%s)", strerror(err));
-                    break;
-                }
-            }
-            pthread_mutex_unlock(&m_blitGenerationLock);
-        }
+        // TODO: This code is only needed for EGLImage code path, but preferrably BackingStore
+        // should not know that, and the synchronization should be in BlackBerry::Platform::Graphics
+        // if possible.
+        if (isOpenGLCompositing())
+            SurfacePool::globalSurfacePool()->waitForBuffer(tile->backBuffer());
 
         // Modify the buffer only after we've waited for the buffer to become available above.
 
@@ -1561,6 +1535,12 @@
         }
     }
 
+    // TODO: This code is only needed for EGLImage code path, but preferrably BackingStore
+    // should not know that, and the synchronization should be in BlackBerry::Platform::Graphics
+    // if possible.
+    if (isOpenGLCompositing())
+        SurfacePool::globalSurfacePool()->notifyBuffersComposited(blittedTiles);
+
 #if USE(ACCELERATED_COMPOSITING)
     if (WebPageCompositorPrivate* compositor = m_webPage->d->compositor()) {
         WebCore::FloatRect contentsRect = m_webPage->d->mapFromTransformedFloatRect(WebCore::FloatRect(WebCore::IntRect(contents)));
@@ -1628,28 +1608,6 @@
 #endif
 
     invalidateWindow(dstRect);
-
-    // This code is only needed for EGLImage code path, and only effective if we are swapping the render target.
-    // This combination is only true if there's a GLES2Usage window.
-    // FIXME: Use an EGL fence instead
-    Window* window = m_webPage->client()->window();
-    if (window && window->windowUsage() == Window::GLES2Usage && !blittedTiles.isEmpty()) {
-        pthread_mutex_lock(&m_blitGenerationLock);
-
-        ++m_blitGeneration;
-        for (unsigned int i = 0; i < blittedTiles.size(); ++i)
-            blittedTiles[i]->setBlitGeneration(m_blitGeneration);
-
-        clock_gettime(CLOCK_MONOTONIC, &m_currentBlitEnd);
-        m_currentBlitEnd.tv_nsec += 30 * 1000 * 1000;
-        if (m_currentBlitEnd.tv_nsec >= 1000000000L) {
-            m_currentBlitEnd.tv_sec  += 1;
-            m_currentBlitEnd.tv_nsec -= 1000000000L;
-        }
-
-        pthread_mutex_unlock(&m_blitGenerationLock);
-        pthread_cond_signal(&m_blitGenerationCond);
-    }
 }
 
 #if USE(ACCELERATED_COMPOSITING)
@@ -1669,6 +1627,7 @@
 
     BackingStoreGeometry* currentState = frontState();
     TileMap currentMap = currentState->tileMap();
+    Vector<TileBuffer*> compositedTiles;
 
     Platform::IntRectRegion transformedContentsRegion = transformedContents;
     Platform::IntRectRegion backingStoreRegion = currentState->backingStoreRect();
@@ -1708,7 +1667,7 @@
             layerRenderer->drawCheckerboardPattern(transform, m_webPage->d->mapFromTransformedFloatRect(Platform::FloatRect(dirtyRect)));
         else {
             layerRenderer->compositeBuffer(transform, m_webPage->d->mapFromTransformedFloatRect(Platform::FloatRect(wholeRect)), tileBuffer->nativeBuffer(), contentsOpaque, 1.0f);
-
+            compositedTiles.append(tileBuffer);
             // Intersect the rendered region.
             Platform::IntRectRegion notRenderedRegion = Platform::IntRectRegion::subtractRegions(dirtyTileRect, tileBuffer->renderedRegion());
             IntRectList notRenderedRects = notRenderedRegion.rects();
@@ -1716,6 +1675,8 @@
                 layerRenderer->drawCheckerboardPattern(transform, m_webPage->d->mapFromTransformedFloatRect(Platform::FloatRect(notRenderedRects.at(i))));
         }
     }
+
+    SurfacePool::globalSurfacePool()->notifyBuffersComposited(compositedTiles);
 }
 #endif
 

Modified: trunk/Source/WebKit/blackberry/Api/BackingStore_p.h (124198 => 124199)


--- trunk/Source/WebKit/blackberry/Api/BackingStore_p.h	2012-07-31 13:50:39 UTC (rev 124198)
+++ trunk/Source/WebKit/blackberry/Api/BackingStore_p.h	2012-07-31 14:35:24 UTC (rev 124199)
@@ -369,11 +369,6 @@
 
     pthread_mutex_t m_mutex;
 
-    int m_blitGeneration;
-    pthread_mutex_t m_blitGenerationLock;
-    pthread_cond_t m_blitGenerationCond;
-    struct timespec m_currentBlitEnd;
-
 #if USE(ACCELERATED_COMPOSITING)
     mutable bool m_needsDrawLayersOnCommit; // Not thread safe, WebKit thread only
     bool m_isDirectRenderingAnimationMessageScheduled;

Modified: trunk/Source/WebKit/blackberry/ChangeLog (124198 => 124199)


--- trunk/Source/WebKit/blackberry/ChangeLog	2012-07-31 13:50:39 UTC (rev 124198)
+++ trunk/Source/WebKit/blackberry/ChangeLog	2012-07-31 14:35:24 UTC (rev 124199)
@@ -1,3 +1,40 @@
+2012-07-31  Arvid Nilsson  <anils...@rim.com>
+
+        [BlackBerry] Backing store output flickers when using WebPageCompositor
+        https://bugs.webkit.org/show_bug.cgi?id=90291
+
+        Reviewed by Antonio Gomes.
+
+        The backing store doesn't know when the API client swaps the buffers,
+        so it doesn't know when to signal the blit generation condition
+        variable. Fixed by using EGL fence sync instead, when available, so we
+        don't have to know.
+
+        Reviewed internally by Filip Spacek.
+
+        * Api/BackingStore.cpp:
+        (BlackBerry::WebKit::BackingStorePrivate::BackingStorePrivate):
+        (BlackBerry::WebKit::BackingStorePrivate::~BackingStorePrivate):
+        (BlackBerry::WebKit::BackingStorePrivate::render):
+        (BlackBerry::WebKit::BackingStorePrivate::blitContents):
+        (BlackBerry::WebKit::BackingStorePrivate::compositeContents):
+        * Api/BackingStore_p.h:
+        (BackingStorePrivate):
+        * WebKitSupport/BackingStoreTile.cpp:
+        (BlackBerry::WebKit::TileBuffer::TileBuffer):
+        * WebKitSupport/BackingStoreTile.h:
+        (BlackBerry::WebKit::TileBuffer::syncObject):
+        (BlackBerry::WebKit::TileBuffer::setSyncObject):
+        (TileBuffer):
+        * WebKitSupport/SurfacePool.cpp:
+        (WebKit):
+        (BlackBerry::WebKit::SurfacePool::SurfacePool):
+        (BlackBerry::WebKit::SurfacePool::initialize):
+        (BlackBerry::WebKit::SurfacePool::waitForBuffer):
+        (BlackBerry::WebKit::SurfacePool::notifyBuffersComposited):
+        * WebKitSupport/SurfacePool.h:
+        (SurfacePool):
+
 2012-07-30  Yoshifumi Inoue  <yo...@chromium.org>
 
         [Forms] Get rid of Element::isReadOnlyFormControl other than CSS related

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.cpp (124198 => 124199)


--- trunk/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.cpp	2012-07-31 13:50:39 UTC (rev 124198)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.cpp	2012-07-31 14:35:24 UTC (rev 124199)
@@ -29,8 +29,8 @@
 
 TileBuffer::TileBuffer(const Platform::IntSize& size)
     : m_size(size)
+    , m_syncObject(0)
     , m_buffer(0)
-    , m_blitGeneration(0)
 {
 }
 

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.h (124198 => 124199)


--- trunk/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.h	2012-07-31 13:50:39 UTC (rev 124198)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.h	2012-07-31 14:35:24 UTC (rev 124199)
@@ -47,14 +47,14 @@
 
         Platform::Graphics::Buffer* nativeBuffer() const;
 
-        void setBlitGeneration(int g) const { m_blitGeneration = g; }
-        int blitGeneration() const { return m_blitGeneration; }
+        void* syncObject() const { return m_syncObject; }
+        void setSyncObject(void* syncObject) { m_syncObject = syncObject; }
 
     private:
         Platform::IntSize m_size;
         Platform::IntRectRegion m_renderedRegion;
+        void* m_syncObject;
         mutable Platform::Graphics::Buffer* m_buffer;
-        mutable int m_blitGeneration;
 };
 
 

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/SurfacePool.cpp (124198 => 124199)


--- trunk/Source/WebKit/blackberry/WebKitSupport/SurfacePool.cpp	2012-07-31 13:50:39 UTC (rev 124198)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/SurfacePool.cpp	2012-07-31 14:35:24 UTC (rev 124199)
@@ -25,16 +25,29 @@
 #include "BackingStoreCompositingSurface.h"
 #endif
 
+#include <BlackBerryPlatformGraphics.h>
 #include <BlackBerryPlatformLog.h>
 #include <BlackBerryPlatformMisc.h>
 #include <BlackBerryPlatformScreen.h>
 #include <BlackBerryPlatformSettings.h>
+#include <BlackBerryPlatformThreading.h>
+#include <errno.h>
 
+#if BLACKBERRY_PLATFORM_GRAPHICS_EGL
+#include <EGL/eglext.h>
+#endif
+
 #define SHARED_PIXMAP_GROUP "webkit_backingstore_group"
 
 namespace BlackBerry {
 namespace WebKit {
 
+#if BLACKBERRY_PLATFORM_GRAPHICS_EGL
+static PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR;
+static PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
+static PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR;
+#endif
+
 #if USE(ACCELERATED_COMPOSITING) && ENABLE_COMPOSITING_SURFACE
 static PassRefPtr<BackingStoreCompositingSurface> createCompositingSurface()
 {
@@ -60,6 +73,7 @@
     , m_backBuffer(0)
     , m_initialized(false)
     , m_buffersSuspended(false)
+    , m_hasFenceExtension(false)
 {
 }
 
@@ -95,6 +109,21 @@
 
     for (size_t i = 0; i < numberOfTiles; ++i)
         m_tilePool.append(BackingStoreTile::create(tileSize, BackingStoreTile::DoubleBuffered));
+
+#if BLACKBERRY_PLATFORM_GRAPHICS_EGL
+    const char* extensions = eglQueryString(Platform::Graphics::eglDisplay(), EGL_EXTENSIONS);
+    if (strstr(extensions, "EGL_KHR_fence_sync")) {
+        // We assume GL_OES_EGL_sync is present, but we don't check for it because
+        // no GL context is current at this point.
+        // TODO: check for it
+        eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC) eglGetProcAddress("eglCreateSyncKHR");
+        eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress("eglDestroySyncKHR");
+        eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC) eglGetProcAddress("eglClientWaitSyncKHR");
+        m_hasFenceExtension = eglCreateSyncKHR && eglDestroySyncKHR && eglClientWaitSyncKHR;
+    }
+#endif
+
+    pthread_mutex_init(&m_mutex, 0);
 }
 
 PlatformGraphicsContext* SurfacePool::createPlatformGraphicsContext(BlackBerry::Platform::Graphics::Drawable* drawable) const
@@ -199,5 +228,71 @@
     }
 }
 
+void SurfacePool::waitForBuffer(TileBuffer* tileBuffer)
+{
+    if (!m_hasFenceExtension)
+        return;
+
+#if BLACKBERRY_PLATFORM_GRAPHICS_EGL
+    EGLSyncKHR syncObject;
+
+    {
+        Platform::MutexLocker locker(&m_mutex);
+        syncObject = tileBuffer->syncObject();
+        if (!syncObject)
+            return;
+
+        // Stale references to this sync object may remain with other tiles, don't wait for it again.
+        for (unsigned int i = 0; i < m_tilePool.size(); ++i) {
+            TileBuffer* tileBuffer = m_tilePool[i]->frontBuffer();
+            if (tileBuffer->syncObject() == syncObject)
+                tileBuffer->setSyncObject(0);
+        }
+        if (backBuffer()->syncObject() == syncObject)
+            backBuffer()->setSyncObject(0);
+    }
+
+    eglClientWaitSyncKHR(Platform::Graphics::eglDisplay(), syncObject, 0, 100000000LL);
+
+    // Instead of assuming eglDestroySyncKHR is thread safe, we add it to
+    // a garbage list for later collection on the thread that created it.
+    {
+        Platform::MutexLocker locker(&m_mutex);
+        m_syncObjectsToDestroy.insert(syncObject);
+    }
+#endif
 }
+
+void SurfacePool::notifyBuffersComposited(const Vector<TileBuffer*>& tileBuffers)
+{
+    if (!m_hasFenceExtension)
+        return;
+
+#if BLACKBERRY_PLATFORM_GRAPHICS_EGL
+    Platform::MutexLocker locker(&m_mutex);
+
+    EGLDisplay display = Platform::Graphics::eglDisplay();
+
+    // The EGL_KHR_fence_sync spec is nice enough to specify that the sync object
+    // is not actually deleted until everyone has stopped using it.
+    for (std::set<void*>::const_iterator it = m_syncObjectsToDestroy.begin(); it != m_syncObjectsToDestroy.end(); ++it)
+        eglDestroySyncKHR(display, *it);
+    m_syncObjectsToDestroy.clear();
+
+    // If we didn't blit anything, we don't need to create a new sync object.
+    if (tileBuffers.isEmpty())
+        return;
+
+    EGLSyncKHR syncObject = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, 0);
+
+    for (unsigned int i = 0; i < tileBuffers.size(); ++i) {
+        if (EGLSyncKHR previousSyncObject = tileBuffers[i]->syncObject())
+            m_syncObjectsToDestroy.insert(previousSyncObject);
+
+        tileBuffers[i]->setSyncObject(syncObject);
+    }
+#endif
 }
+
+}
+}

Modified: trunk/Source/WebKit/blackberry/WebKitSupport/SurfacePool.h (124198 => 124199)


--- trunk/Source/WebKit/blackberry/WebKitSupport/SurfacePool.h	2012-07-31 13:50:39 UTC (rev 124198)
+++ trunk/Source/WebKit/blackberry/WebKitSupport/SurfacePool.h	2012-07-31 14:35:24 UTC (rev 124199)
@@ -25,6 +25,8 @@
 
 #include <BlackBerryPlatformGraphics.h>
 #include <BlackBerryPlatformPrimitives.h>
+#include <pthread.h>
+#include <set>
 #include <wtf/Vector.h>
 
 #define ENABLE_COMPOSITING_SURFACE 1
@@ -71,6 +73,16 @@
     void releaseBuffers();
     void createBuffers();
 
+    // EGLImage synchronization between WebKit and compositing threads
+    // TODO: Figure out how to improve the BlackBerry::Platform::Graphics with API that can encapsulate
+    // this kind of synchronisation mechanism.
+
+    // WebKit thread must waitForBuffer() before rendering to EGLImage
+    void waitForBuffer(TileBuffer*);
+
+    // Compositing thread must notify the SurfacePool when EGLImages are composited
+    void notifyBuffersComposited(const Vector<TileBuffer*>& buffers);
+
 private:
     // This is necessary so BackingStoreTile can atomically swap buffers with m_backBuffer.
     friend class BackingStoreTile;
@@ -86,6 +98,10 @@
     unsigned m_backBuffer;
     bool m_initialized; // SurfacePool has been set up, with or without buffers.
     bool m_buffersSuspended; // Buffer objects exist, but pixel memory has been freed.
+
+    std::set<void*> m_syncObjectsToDestroy;
+    bool m_hasFenceExtension;
+    mutable pthread_mutex_t m_mutex;
 };
 }
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to