Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[BlackBerry] SurfacePool::waitForBuffer() sometimes waits for deleted…

… EGLSyncKHR object


https://bugs.webkit.org/show_bug.cgi?id=94208

Patch by Arvid Nilsson <anilsson@rim.com> on 2012-08-16
Reviewed by Rob Buis.

SurfacePool::notifyBuffersComposited() adds a tile's previous
sync object to the garbage list before replacing it with a new one.
However, it failed to thoroughly clear all tiles that were referencing
the old sync object.

Thus it could happen that if a set of tiles A was composited, then
another set of tiles B was composited, only the intersection of A and B
was cleared of the soon-to-be-deleted sync object, and the subtraction
A - B would reference an invalid sync object in case the BackingStore
decided to render to one of the tiles in A - B before they were
composited again.

Fixed by storing each individual sync object in only one place so we
don't have to rummage through all tiles and remove stale references to
sync objects that are about to be destroyed.

A new reference counted Fence class is added for this purpose, to store
a sync object. Tiles refer to Fence instances instead of holding a sync
object directly. Since Fence is reference counted, several tiles can
refer to the same Fence instance, and clearing its sync object will
instantly remove it from the grasp of all tiles that depend on that
Fence.

Since there's no point in waiting for the same Fence twice, the only
operation provided on Fence is takePlatformSync() which returns the
sync object and clears the Fence of its sync object.

Reviewed internally by Filip Spacek.

PR 193610

* WebKitSupport/BackingStoreTile.cpp:
(BlackBerry::WebKit::TileBuffer::TileBuffer):
* WebKitSupport/BackingStoreTile.h:
(BlackBerry):
(Fence):
(BlackBerry::Fence::create):
(BlackBerry::Fence::takePlatformSync):
(BlackBerry::Fence::Fence):
(BlackBerry::WebKit::TileBuffer::fence):
(BlackBerry::WebKit::TileBuffer::setFence):
(TileBuffer):
* WebKitSupport/SurfacePool.cpp:
(BlackBerry::WebKit::SurfacePool::waitForBuffer):
(BlackBerry::WebKit::SurfacePool::notifyBuffersComposited):
* WebKitSupport/SurfacePool.h:
(SurfacePool):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@125795 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information...
commit eb8f3cf2cafe1d3fad3b081317b173e59173deb1 1 parent 7c1b96c
authored August 16, 2012
55  Source/WebKit/blackberry/ChangeLog
... ...
@@ -1,3 +1,58 @@
  1
+2012-08-16  Arvid Nilsson  <anilsson@rim.com>
  2
+
  3
+        [BlackBerry] SurfacePool::waitForBuffer() sometimes waits for deleted EGLSyncKHR object
  4
+        https://bugs.webkit.org/show_bug.cgi?id=94208
  5
+
  6
+        Reviewed by Rob Buis.
  7
+
  8
+        SurfacePool::notifyBuffersComposited() adds a tile's previous
  9
+        sync object to the garbage list before replacing it with a new one.
  10
+        However, it failed to thoroughly clear all tiles that were referencing
  11
+        the old sync object.
  12
+
  13
+        Thus it could happen that if a set of tiles A was composited, then
  14
+        another set of tiles B was composited, only the intersection of A and B
  15
+        was cleared of the soon-to-be-deleted sync object, and the subtraction
  16
+        A - B would reference an invalid sync object in case the BackingStore
  17
+        decided to render to one of the tiles in A - B before they were
  18
+        composited again.
  19
+
  20
+        Fixed by storing each individual sync object in only one place so we
  21
+        don't have to rummage through all tiles and remove stale references to
  22
+        sync objects that are about to be destroyed.
  23
+
  24
+        A new reference counted Fence class is added for this purpose, to store
  25
+        a sync object. Tiles refer to Fence instances instead of holding a sync
  26
+        object directly. Since Fence is reference counted, several tiles can
  27
+        refer to the same Fence instance, and clearing its sync object will
  28
+        instantly remove it from the grasp of all tiles that depend on that
  29
+        Fence.
  30
+
  31
+        Since there's no point in waiting for the same Fence twice, the only
  32
+        operation provided on Fence is takePlatformSync() which returns the
  33
+        sync object and clears the Fence of its sync object.
  34
+
  35
+        Reviewed internally by Filip Spacek.
  36
+
  37
+        PR 193610
  38
+
  39
+        * WebKitSupport/BackingStoreTile.cpp:
  40
+        (BlackBerry::WebKit::TileBuffer::TileBuffer):
  41
+        * WebKitSupport/BackingStoreTile.h:
  42
+        (BlackBerry):
  43
+        (Fence):
  44
+        (BlackBerry::Fence::create):
  45
+        (BlackBerry::Fence::takePlatformSync):
  46
+        (BlackBerry::Fence::Fence):
  47
+        (BlackBerry::WebKit::TileBuffer::fence):
  48
+        (BlackBerry::WebKit::TileBuffer::setFence):
  49
+        (TileBuffer):
  50
+        * WebKitSupport/SurfacePool.cpp:
  51
+        (BlackBerry::WebKit::SurfacePool::waitForBuffer):
  52
+        (BlackBerry::WebKit::SurfacePool::notifyBuffersComposited):
  53
+        * WebKitSupport/SurfacePool.h:
  54
+        (SurfacePool):
  55
+
1 56
 2012-08-16  Rob Buis  <rbuis@rim.com>
2 57
 
3 58
         [BlackBerry] Suppress non DRT JS Console output.
2  Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.cpp
@@ -29,7 +29,7 @@ namespace WebKit {
29 29
 
30 30
 TileBuffer::TileBuffer(const Platform::IntSize& size)
31 31
     : m_size(size)
32  
-    , m_syncObject(0)
  32
+    , m_fence(Fence::create())
33 33
     , m_buffer(0)
34 34
 {
35 35
 }
40  Source/WebKit/blackberry/WebKitSupport/BackingStoreTile.h
@@ -21,6 +21,9 @@
21 21
 
22 22
 #include "BlackBerryPlatformIntRectRegion.h"
23 23
 #include "BlackBerryPlatformPrimitives.h"
  24
+#include <wtf/PassRefPtr.h>
  25
+#include <wtf/RefCounted.h>
  26
+#include <wtf/RefPtr.h>
24 27
 
25 28
 namespace BlackBerry {
26 29
 namespace Platform {
@@ -29,6 +32,37 @@ struct Buffer;
29 32
 }
30 33
 }
31 34
 
  35
+// Represents a fence that has been inserted into the command stream. You can wait on the corresponding platform sync
  36
+// object to make sure that previous commands have been completed.
  37
+// There is no reason to wait twice on the same platform sync object, so the only mechanism provided to access the sync
  38
+// object will also clear it to prevent anyone from waiting again.
  39
+// Fence is only refcounted on the compositing thread, so RefCounted will suffice, we don't need ThreadSafeRefCounted.
  40
+class Fence : public RefCounted<Fence> {
  41
+public:
  42
+    static PassRefPtr<Fence> create(void* platformSync = 0)
  43
+    {
  44
+        return adoptRef(new Fence(platformSync));
  45
+    }
  46
+
  47
+    // Returns 0 if this fence is stale (someone already waited on it)
  48
+    // Otherwise returns the platform sync object and clears the sync
  49
+    // object so no-one waits again.
  50
+    void* takePlatformSync()
  51
+    {
  52
+        void* tmp = m_platformSync;
  53
+        m_platformSync = 0;
  54
+        return tmp;
  55
+    }
  56
+
  57
+private:
  58
+    Fence(void* platformSync)
  59
+        : m_platformSync(platformSync)
  60
+    {
  61
+    }
  62
+
  63
+    void* m_platformSync;
  64
+};
  65
+
32 66
 namespace WebKit {
33 67
 class TileBuffer {
34 68
     public:
@@ -47,13 +81,13 @@ class TileBuffer {
47 81
 
48 82
         Platform::Graphics::Buffer* nativeBuffer() const;
49 83
 
50  
-        void* syncObject() const { return m_syncObject; }
51  
-        void setSyncObject(void* syncObject) { m_syncObject = syncObject; }
  84
+        Fence* fence() const { return m_fence.get(); }
  85
+        void setFence(PassRefPtr<Fence> fence) { m_fence = fence; }
52 86
 
53 87
     private:
54 88
         Platform::IntSize m_size;
55 89
         Platform::IntRectRegion m_renderedRegion;
56  
-        void* m_syncObject;
  90
+        RefPtr<Fence> m_fence;
57 91
         mutable Platform::Graphics::Buffer* m_buffer;
58 92
 };
59 93
 
41  Source/WebKit/blackberry/WebKitSupport/SurfacePool.cpp
@@ -234,31 +234,24 @@ void SurfacePool::waitForBuffer(TileBuffer* tileBuffer)
234 234
         return;
235 235
 
236 236
 #if BLACKBERRY_PLATFORM_GRAPHICS_EGL
237  
-    EGLSyncKHR syncObject;
  237
+    EGLSyncKHR platformSync;
238 238
 
239 239
     {
240 240
         Platform::MutexLocker locker(&m_mutex);
241  
-        syncObject = tileBuffer->syncObject();
242  
-        if (!syncObject)
243  
-            return;
244  
-
245  
-        // Stale references to this sync object may remain with other tiles, don't wait for it again.
246  
-        for (unsigned int i = 0; i < m_tilePool.size(); ++i) {
247  
-            TileBuffer* tileBuffer = m_tilePool[i]->frontBuffer();
248  
-            if (tileBuffer->syncObject() == syncObject)
249  
-                tileBuffer->setSyncObject(0);
250  
-        }
251  
-        if (backBuffer()->syncObject() == syncObject)
252  
-            backBuffer()->setSyncObject(0);
  241
+        platformSync = tileBuffer->fence()->takePlatformSync();
253 242
     }
254 243
 
255  
-    eglClientWaitSyncKHR(Platform::Graphics::eglDisplay(), syncObject, 0, 100000000LL);
  244
+    if (!platformSync)
  245
+        return;
  246
+
  247
+    if (!eglClientWaitSyncKHR(Platform::Graphics::eglDisplay(), platformSync, 0, 100000000LL))
  248
+        Platform::logAlways(Platform::LogLevelWarn, "Failed to wait for EGLSyncKHR object!\n");
256 249
 
257 250
     // Instead of assuming eglDestroySyncKHR is thread safe, we add it to
258 251
     // a garbage list for later collection on the thread that created it.
259 252
     {
260 253
         Platform::MutexLocker locker(&m_mutex);
261  
-        m_syncObjectsToDestroy.insert(syncObject);
  254
+        m_garbage.insert(platformSync);
262 255
     }
263 256
 #endif
264 257
 }
@@ -275,21 +268,23 @@ void SurfacePool::notifyBuffersComposited(const Vector<TileBuffer*>& tileBuffers
275 268
 
276 269
     // The EGL_KHR_fence_sync spec is nice enough to specify that the sync object
277 270
     // is not actually deleted until everyone has stopped using it.
278  
-    for (std::set<void*>::const_iterator it = m_syncObjectsToDestroy.begin(); it != m_syncObjectsToDestroy.end(); ++it)
  271
+    for (std::set<void*>::const_iterator it = m_garbage.begin(); it != m_garbage.end(); ++it)
279 272
         eglDestroySyncKHR(display, *it);
280  
-    m_syncObjectsToDestroy.clear();
  273
+    m_garbage.clear();
281 274
 
282  
-    // If we didn't blit anything, we don't need to create a new sync object.
  275
+    // If we didn't blit anything, we don't need to create a new fence.
283 276
     if (tileBuffers.isEmpty())
284 277
         return;
285 278
 
286  
-    EGLSyncKHR syncObject = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, 0);
287  
-
  279
+    // Create a new fence and assign to the tiles that were blit. Invalidate any previous
  280
+    // fence that may be active among these tiles and add its sync object to the garbage set
  281
+    // for later destruction to make sure it doesn't leak.
  282
+    RefPtr<Fence> fence = Fence::create(eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, 0));
288 283
     for (unsigned int i = 0; i < tileBuffers.size(); ++i) {
289  
-        if (EGLSyncKHR previousSyncObject = tileBuffers[i]->syncObject())
290  
-            m_syncObjectsToDestroy.insert(previousSyncObject);
  284
+        if (EGLSyncKHR platformSync = tileBuffers[i]->fence()->takePlatformSync())
  285
+            m_garbage.insert(platformSync);
291 286
 
292  
-        tileBuffers[i]->setSyncObject(syncObject);
  287
+        tileBuffers[i]->setFence(fence);
293 288
     }
294 289
 #endif
295 290
 }
2  Source/WebKit/blackberry/WebKitSupport/SurfacePool.h
@@ -99,7 +99,7 @@ class SurfacePool {
99 99
     bool m_initialized; // SurfacePool has been set up, with or without buffers.
100 100
     bool m_buffersSuspended; // Buffer objects exist, but pixel memory has been freed.
101 101
 
102  
-    std::set<void*> m_syncObjectsToDestroy;
  102
+    std::set<void*> m_garbage;
103 103
     bool m_hasFenceExtension;
104 104
     mutable pthread_mutex_t m_mutex;
105 105
 };

0 notes on commit eb8f3cf

Please sign in to comment.
Something went wrong with that request. Please try again.