5e3c82f1f33ad52925066896c9c214a33bf8b305
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / TextureMapperPlatformLayerProxy.cpp
1 /*
2  * Copyright (C) 2015 Igalia S.L.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "TextureMapperPlatformLayerProxy.h"
28
29 #if USE(COORDINATED_GRAPHICS_THREADED)
30
31 #include "BitmapTextureGL.h"
32 #include "TextureMapperGL.h"
33 #include "TextureMapperLayer.h"
34 #include "TextureMapperPlatformLayerBuffer.h"
35
36 const double s_releaseUnusedSecondsTolerance = 1;
37 const double s_releaseUnusedBuffersTimerInterval = 0.5;
38
39 namespace WebCore {
40
41 TextureMapperPlatformLayerProxy::TextureMapperPlatformLayerProxy()
42     : m_compositor(nullptr)
43     , m_targetLayer(nullptr)
44     , m_releaseUnusedBuffersTimer(RunLoop::current(), this, &TextureMapperPlatformLayerProxy::releaseUnusedBuffersTimerFired)
45 {
46 }
47
48 TextureMapperPlatformLayerProxy::~TextureMapperPlatformLayerProxy()
49 {
50     LockHolder locker(m_lock);
51     if (m_targetLayer)
52         m_targetLayer->setContentsLayer(nullptr);
53 }
54
55 void TextureMapperPlatformLayerProxy::activateOnCompositingThread(Compositor* compositor, TextureMapperLayer* targetLayer)
56 {
57 #ifndef NDEBUG
58     m_compositorThreadID = m_compositorThreadID ? m_compositorThreadID : WTF::currentThread();
59 #endif
60     ASSERT(m_compositorThreadID == WTF::currentThread());
61     ASSERT(compositor);
62     ASSERT(targetLayer);
63     LockHolder locker(m_lock);
64     m_compositor = compositor;
65     m_targetLayer = targetLayer;
66     if (m_targetLayer && m_currentBuffer)
67         m_targetLayer->setContentsLayer(m_currentBuffer.get());
68
69     m_compositorThreadUpdateTimer = std::make_unique<RunLoop::Timer<TextureMapperPlatformLayerProxy>>(RunLoop::current(), this, &TextureMapperPlatformLayerProxy::compositorThreadUpdateTimerFired);
70 }
71
72 void TextureMapperPlatformLayerProxy::invalidate()
73 {
74     ASSERT(m_compositorThreadID == WTF::currentThread());
75     LockHolder locker(m_lock);
76     m_compositor = nullptr;
77     m_targetLayer = nullptr;
78 }
79
80 bool TextureMapperPlatformLayerProxy::isActive()
81 {
82     ASSERT(m_lock.isHeld());
83     return !!m_targetLayer && !!m_compositor;
84 }
85
86 void TextureMapperPlatformLayerProxy::pushNextBuffer(std::unique_ptr<TextureMapperPlatformLayerBuffer> newBuffer)
87 {
88     ASSERT(m_lock.isHeld());
89     m_pendingBuffer = WTFMove(newBuffer);
90
91     if (m_compositor)
92         m_compositor->onNewBufferAvailable();
93 }
94
95 std::unique_ptr<TextureMapperPlatformLayerBuffer> TextureMapperPlatformLayerProxy::getAvailableBuffer(const IntSize& size, GC3Dint internalFormat)
96 {
97     ASSERT(m_lock.isHeld());
98     std::unique_ptr<TextureMapperPlatformLayerBuffer> availableBuffer;
99
100     auto buffers = WTFMove(m_usedBuffers);
101     for (auto& buffer : buffers) {
102         if (!buffer)
103             continue;
104
105         if (!availableBuffer && buffer->canReuseWithoutReset(size, internalFormat)) {
106             availableBuffer = WTFMove(buffer);
107             availableBuffer->markUsed();
108             continue;
109         }
110         m_usedBuffers.append(WTFMove(buffer));
111     }
112
113     if (!m_usedBuffers.isEmpty())
114         scheduleReleaseUnusedBuffers();
115     return availableBuffer;
116 }
117
118 void TextureMapperPlatformLayerProxy::scheduleReleaseUnusedBuffers()
119 {
120     if (!m_releaseUnusedBuffersTimer.isActive())
121         m_releaseUnusedBuffersTimer.startOneShot(s_releaseUnusedBuffersTimerInterval);
122 }
123
124 void TextureMapperPlatformLayerProxy::releaseUnusedBuffersTimerFired()
125 {
126     LockHolder locker(m_lock);
127     if (m_usedBuffers.isEmpty())
128         return;
129
130     auto buffers = WTFMove(m_usedBuffers);
131     double minUsedTime = monotonicallyIncreasingTime() - s_releaseUnusedSecondsTolerance;
132
133     for (auto& buffer : buffers) {
134         if (buffer && buffer->lastUsedTime() >= minUsedTime)
135             m_usedBuffers.append(WTFMove(buffer));
136     }
137 }
138
139 void TextureMapperPlatformLayerProxy::swapBuffer()
140 {
141     ASSERT(m_compositorThreadID == WTF::currentThread());
142     std::unique_ptr<TextureMapperPlatformLayerBuffer> prevBuffer;
143
144     {
145         LockHolder locker(m_lock);
146         if (!m_targetLayer || !m_pendingBuffer)
147             return;
148
149         prevBuffer = WTFMove(m_currentBuffer);
150
151         m_currentBuffer = WTFMove(m_pendingBuffer);
152         m_targetLayer->setContentsLayer(m_currentBuffer.get());
153     }
154
155     if (prevBuffer && prevBuffer->hasManagedTexture())
156         m_usedBuffers.append(WTFMove(prevBuffer));
157 }
158
159 bool TextureMapperPlatformLayerProxy::scheduleUpdateOnCompositorThread(std::function<void()>&& updateFunction)
160 {
161     LockHolder locker(m_lock);
162     if (!m_compositorThreadUpdateTimer)
163         return false;
164
165     m_compositorThreadUpdateFunction = WTFMove(updateFunction);
166     m_compositorThreadUpdateTimer->startOneShot(0);
167     return true;
168 }
169
170 void TextureMapperPlatformLayerProxy::compositorThreadUpdateTimerFired()
171 {
172     std::function<void()> updateFunction;
173     {
174         LockHolder locker(m_lock);
175         if (!m_compositorThreadUpdateFunction)
176             return;
177         updateFunction = WTFMove(m_compositorThreadUpdateFunction);
178     }
179
180     updateFunction();
181 }
182
183 } // namespace WebCore
184
185 #endif // USE(COORDINATED_GRAPHICS_THREADED)