a0bd37cc8d5ae83a083b91dcd711b991997f0d70
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCResourceProvider.cpp
1 /*
2  * Copyright (C) 2012, Google Inc. All rights reserved.
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'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCResourceProvider.h"
28
29 #include "Extensions3DChromium.h"
30 #include "IntRect.h"
31 #include "LayerRendererChromium.h" // For the GLC() macro
32 #include "LayerTextureSubImage.h"
33 #include "cc/CCProxy.h"
34 #include <public/WebGraphicsContext3D.h>
35
36 using WebKit::WebGraphicsContext3D;
37
38 namespace WebCore {
39
40 static GC3Denum textureToStorageFormat(GC3Denum textureFormat)
41 {
42     GC3Denum storageFormat = Extensions3D::RGBA8_OES;
43     switch (textureFormat) {
44     case GraphicsContext3D::RGBA:
45         break;
46     case Extensions3D::BGRA_EXT:
47         storageFormat = Extensions3DChromium::BGRA8_EXT;
48         break;
49     default:
50         ASSERT_NOT_REACHED();
51         break;
52     }
53
54     return storageFormat;
55 }
56
57 static bool isTextureFormatSupportedForStorage(GC3Denum format)
58 {
59     return (format == GraphicsContext3D::RGBA || format == Extensions3D::BGRA_EXT);
60 }
61
62 PassOwnPtr<CCResourceProvider> CCResourceProvider::create(CCGraphicsContext* context)
63 {
64     OwnPtr<CCResourceProvider> resourceProvider(adoptPtr(new CCResourceProvider(context)));
65     if (!resourceProvider->initialize())
66         return nullptr;
67     return resourceProvider.release();
68 }
69
70 CCResourceProvider::~CCResourceProvider()
71 {
72 }
73
74 WebGraphicsContext3D* CCResourceProvider::graphicsContext3D()
75 {
76     ASSERT(CCProxy::isImplThread());
77     return m_context->context3D();
78 }
79
80 bool CCResourceProvider::inUseByConsumer(ResourceId id)
81 {
82     ASSERT(CCProxy::isImplThread());
83     ResourceMap::iterator it = m_resources.find(id);
84     ASSERT(it != m_resources.end());
85     return !!it->second.lockForReadCount;
86 }
87
88 CCResourceProvider::ResourceId CCResourceProvider::createResource(int pool, const IntSize& size, GC3Denum format, TextureUsageHint hint)
89 {
90     ASSERT(CCProxy::isImplThread());
91     unsigned textureId = 0;
92     WebGraphicsContext3D* context3d = m_context->context3D();
93     if (!context3d) {
94         // FIXME: Implement this path for software compositing.
95         return 0;
96     }
97     GLC(context3d, textureId = context3d->createTexture());
98     GLC(context3d, context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
99     GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
100     GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
101     GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
102     GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
103
104     if (m_useTextureUsageHint && hint == TextureUsageFramebuffer)
105         GLC(context3d, context3d->texParameteri(GraphicsContext3D::TEXTURE_2D, Extensions3DChromium::GL_TEXTURE_USAGE_ANGLE, Extensions3DChromium::GL_FRAMEBUFFER_ATTACHMENT_ANGLE));
106     if (m_useTextureStorageExt && isTextureFormatSupportedForStorage(format)) {
107         GC3Denum storageFormat = textureToStorageFormat(format);
108         GLC(context3d, context3d->texStorage2DEXT(GraphicsContext3D::TEXTURE_2D, 1, storageFormat, size.width(), size.height()));
109     } else
110         GLC(context3d, context3d->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE, 0));
111     ResourceId id = m_nextId++;
112     Resource resource = {textureId, pool, 0, false, false, size, format};
113     m_resources.add(id, resource);
114     return id;
115 }
116
117 CCResourceProvider::ResourceId CCResourceProvider::createResourceFromExternalTexture(unsigned textureId)
118 {
119     ASSERT(CCProxy::isImplThread());
120     ResourceId id = m_nextId++;
121     Resource resource = {textureId, 0, 0, false, true, IntSize(), 0};
122     m_resources.add(id, resource);
123     return id;
124 }
125
126 void CCResourceProvider::deleteResource(ResourceId id)
127 {
128     ASSERT(CCProxy::isImplThread());
129     WebGraphicsContext3D* context3d = m_context->context3D();
130     if (!context3d) {
131         // FIXME: Implement this path for software compositing.
132         return;
133     }
134     ResourceMap::iterator it = m_resources.find(id);
135     ASSERT(it != m_resources.end() && !it->second.lockedForWrite && !it->second.lockForReadCount);
136     if (!it->second.external)
137         GLC(context3d, context3d->deleteTexture(it->second.glId));
138     m_resources.remove(it);
139 }
140
141 void CCResourceProvider::deleteOwnedResources(int pool)
142 {
143     ASSERT(CCProxy::isImplThread());
144     Vector<ResourceId> toDelete;
145     for (ResourceMap::iterator it = m_resources.begin(); it != m_resources.end(); ++it) {
146         if (it->second.pool == pool && !it->second.external)
147             toDelete.append(it->first);
148     }
149     for (Vector<ResourceId>::iterator it = toDelete.begin(); it != toDelete.end(); ++it)
150         deleteResource(*it);
151 }
152
153 void CCResourceProvider::upload(ResourceId id, const uint8_t* image, const IntRect& imageRect, const IntRect& sourceRect, const IntRect& destRect)
154 {
155     ASSERT(CCProxy::isImplThread());
156     ASSERT(m_texSubImage.get());
157     WebGraphicsContext3D* context3d = m_context->context3D();
158     if (!context3d) {
159         // FIXME: Implement this path for software compositing.
160         return;
161     }
162     ResourceMap::iterator it = m_resources.find(id);
163     ASSERT(it != m_resources.end() && !it->second.lockedForWrite && !it->second.lockForReadCount && !it->second.external);
164
165     context3d->bindTexture(GraphicsContext3D::TEXTURE_2D, it->second.glId);
166     m_texSubImage->upload(image, imageRect, sourceRect, destRect, it->second.format, context3d);
167 }
168
169 unsigned CCResourceProvider::lockForWrite(ResourceId id)
170 {
171     ASSERT(CCProxy::isImplThread());
172     ResourceMap::iterator it = m_resources.find(id);
173     ASSERT(it != m_resources.end() && !it->second.lockedForWrite && !it->second.lockForReadCount && !it->second.external);
174     it->second.lockedForWrite = true;
175     return it->second.glId;
176 }
177
178 void CCResourceProvider::unlockForWrite(ResourceId id)
179 {
180     ASSERT(CCProxy::isImplThread());
181     ResourceMap::iterator it = m_resources.find(id);
182     ASSERT(it != m_resources.end() && it->second.lockedForWrite && !it->second.external);
183     it->second.lockedForWrite = false;
184 }
185
186 void CCResourceProvider::flush()
187 {
188     ASSERT(CCProxy::isImplThread());
189     WebGraphicsContext3D* context3d = m_context->context3D();
190     if (!context3d) {
191         // FIXME: Implement this path for software compositing.
192         return;
193     }
194     context3d->flush();
195 }
196
197 bool CCResourceProvider::shallowFlushIfSupported()
198 {
199     ASSERT(CCProxy::isImplThread());
200     WebGraphicsContext3D* context3d = m_context->context3D();
201     if (!context3d) {
202         // FIXME: Implement this path for software compositing.
203         return false;
204     }
205
206     if (m_useShallowFlush)
207         context3d->shallowFlushCHROMIUM();
208     return m_useShallowFlush;
209 }
210
211 unsigned CCResourceProvider::lockForRead(ResourceId id)
212 {
213     ASSERT(CCProxy::isImplThread());
214     ResourceMap::iterator it = m_resources.find(id);
215     ASSERT(it != m_resources.end() && !it->second.lockedForWrite);
216     ++(it->second.lockForReadCount);
217     return it->second.glId;
218 }
219
220 void CCResourceProvider::unlockForRead(ResourceId id)
221 {
222     ASSERT(CCProxy::isImplThread());
223     ResourceMap::iterator it = m_resources.find(id);
224     ASSERT(it != m_resources.end() && it->second.lockForReadCount > 0);
225     --(it->second.lockForReadCount);
226 }
227
228 CCResourceProvider::CCResourceProvider(CCGraphicsContext* context)
229     : m_context(context)
230     , m_nextId(1)
231     , m_useTextureStorageExt(false)
232     , m_useTextureUsageHint(false)
233     , m_useShallowFlush(false)
234     , m_maxTextureSize(0)
235 {
236 }
237
238 bool CCResourceProvider::initialize()
239 {
240     ASSERT(CCProxy::isImplThread());
241     WebGraphicsContext3D* context3d = m_context->context3D();
242     if (!context3d || !context3d->makeContextCurrent()) {
243         // FIXME: Implement this path for software compositing.
244         return false;
245     }
246     WebKit::WebString extensionsWebString = context3d->getString(GraphicsContext3D::EXTENSIONS);
247     String extensionsString(extensionsWebString.data(), extensionsWebString.length());
248     Vector<String> extensions;
249     extensionsString.split(' ', extensions);
250     bool useMapSub = false;
251     for (size_t i = 0; i < extensions.size(); ++i) {
252         if (extensions[i] == "GL_EXT_texture_storage")
253             m_useTextureStorageExt = true;
254         else if (extensions[i] == "GL_ANGLE_texture_usage")
255             m_useTextureUsageHint = true;
256         else if (extensions[i] == "GL_CHROMIUM_map_sub")
257             useMapSub = true;
258         else if (extensions[i] == "GL_CHROMIUM_shallow_flush")
259             m_useShallowFlush = true;
260     }
261
262     m_texSubImage = adoptPtr(new LayerTextureSubImage(useMapSub));
263     GLC(context3d, context3d->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize));
264     return true;
265 }
266
267 }