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;
};
}
}