1 /*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Copyright (C) 2010 Mozilla Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "config.h"
29
30 #include "platform/graphics/GraphicsContext3D.h"
31 #include "platform/CheckedInt.h"
32 #include "platform/graphics/GraphicsContext.h"
33 #include "platform/graphics/ImageBuffer.h"
34 #include "platform/graphics/ImageObserver.h"
35 #include "platform/graphics/gpu/DrawingBuffer.h"
36 #include "platform/image-decoders/ImageDecoder.h"
37 #include "third_party/skia/include/gpu/GrContext.h"
38 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
39 #include "wtf/CPU.h"
40 #include "wtf/text/CString.h"
41 #include "wtf/text/StringHash.h"
42
43 #include "public/platform/Platform.h"
44 #include "public/platform/WebGraphicsContext3D.h"
45 #include "public/platform/WebGraphicsContext3DProvider.h"
46
47 namespace WebCore {
48
49 namespace {
50
getDrawingParameters(DrawingBuffer * drawingBuffer,blink::WebGraphicsContext3D * graphicsContext3D,Platform3DObject * frameBufferId,int * width,int * height)51 void getDrawingParameters(DrawingBuffer* drawingBuffer, blink::WebGraphicsContext3D* graphicsContext3D,
52 Platform3DObject* frameBufferId, int* width, int* height)
53 {
54 ASSERT(drawingBuffer);
55 *frameBufferId = drawingBuffer->framebuffer();
56 *width = drawingBuffer->size().width();
57 *height = drawingBuffer->size().height();
58 }
59
60 } // anonymous namespace
61
GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3D> webContext,bool preserveDrawingBuffer)62 GraphicsContext3D::GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3D> webContext, bool preserveDrawingBuffer)
63 : m_impl(webContext.get())
64 , m_ownedWebContext(webContext)
65 , m_initializedAvailableExtensions(false)
66 , m_layerComposited(false)
67 , m_preserveDrawingBuffer(preserveDrawingBuffer)
68 , m_packAlignment(4)
69 , m_resourceSafety(ResourceSafetyUnknown)
70 , m_grContext(0)
71 {
72 }
73
GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3DProvider> provider,bool preserveDrawingBuffer)74 GraphicsContext3D::GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3DProvider> provider, bool preserveDrawingBuffer)
75 : m_provider(provider)
76 , m_impl(m_provider->context3d())
77 , m_initializedAvailableExtensions(false)
78 , m_layerComposited(false)
79 , m_preserveDrawingBuffer(preserveDrawingBuffer)
80 , m_packAlignment(4)
81 , m_resourceSafety(ResourceSafetyUnknown)
82 , m_grContext(m_provider->grContext())
83 {
84 }
85
~GraphicsContext3D()86 GraphicsContext3D::~GraphicsContext3D()
87 {
88 setContextLostCallback(nullptr);
89 setErrorMessageCallback(nullptr);
90 }
91
92 // Macros to assist in delegating from GraphicsContext3D to
93 // WebGraphicsContext3D.
94
95 #define DELEGATE_TO_WEBCONTEXT(name) \
96 void GraphicsContext3D::name() \
97 { \
98 m_impl->name(); \
99 }
100
101 #define DELEGATE_TO_WEBCONTEXT_R(name, rt) \
102 rt GraphicsContext3D::name() \
103 { \
104 return m_impl->name(); \
105 }
106
107 #define DELEGATE_TO_WEBCONTEXT_1(name, t1) \
108 void GraphicsContext3D::name(t1 a1) \
109 { \
110 m_impl->name(a1); \
111 }
112
113 #define DELEGATE_TO_WEBCONTEXT_1R(name, t1, rt) \
114 rt GraphicsContext3D::name(t1 a1) \
115 { \
116 return m_impl->name(a1); \
117 }
118
119 #define DELEGATE_TO_WEBCONTEXT_2(name, t1, t2) \
120 void GraphicsContext3D::name(t1 a1, t2 a2) \
121 { \
122 m_impl->name(a1, a2); \
123 }
124
125 #define DELEGATE_TO_WEBCONTEXT_2R(name, t1, t2, rt) \
126 rt GraphicsContext3D::name(t1 a1, t2 a2) \
127 { \
128 return m_impl->name(a1, a2); \
129 }
130
131 #define DELEGATE_TO_WEBCONTEXT_3(name, t1, t2, t3) \
132 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
133 { \
134 m_impl->name(a1, a2, a3); \
135 }
136
137 #define DELEGATE_TO_WEBCONTEXT_3R(name, t1, t2, t3, rt) \
138 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
139 { \
140 return m_impl->name(a1, a2, a3); \
141 }
142
143 #define DELEGATE_TO_WEBCONTEXT_4(name, t1, t2, t3, t4) \
144 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
145 { \
146 m_impl->name(a1, a2, a3, a4); \
147 }
148
149 #define DELEGATE_TO_WEBCONTEXT_4R(name, t1, t2, t3, t4, rt) \
150 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
151 { \
152 return m_impl->name(a1, a2, a3, a4); \
153 }
154
155 #define DELEGATE_TO_WEBCONTEXT_5(name, t1, t2, t3, t4, t5) \
156 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
157 { \
158 m_impl->name(a1, a2, a3, a4, a5); \
159 }
160
161 #define DELEGATE_TO_WEBCONTEXT_6(name, t1, t2, t3, t4, t5, t6) \
162 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
163 { \
164 m_impl->name(a1, a2, a3, a4, a5, a6); \
165 }
166
167 #define DELEGATE_TO_WEBCONTEXT_6R(name, t1, t2, t3, t4, t5, t6, rt) \
168 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
169 { \
170 return m_impl->name(a1, a2, a3, a4, a5, a6); \
171 }
172
173 #define DELEGATE_TO_WEBCONTEXT_7(name, t1, t2, t3, t4, t5, t6, t7) \
174 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) \
175 { \
176 m_impl->name(a1, a2, a3, a4, a5, a6, a7); \
177 }
178
179 #define DELEGATE_TO_WEBCONTEXT_7R(name, t1, t2, t3, t4, t5, t6, t7, rt) \
180 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) \
181 { \
182 return m_impl->name(a1, a2, a3, a4, a5, a6, a7); \
183 }
184
185 #define DELEGATE_TO_WEBCONTEXT_8(name, t1, t2, t3, t4, t5, t6, t7, t8) \
186 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \
187 { \
188 m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8); \
189 }
190
191 #define DELEGATE_TO_WEBCONTEXT_9(name, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
192 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) \
193 { \
194 m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8, a9); \
195 }
196
197 #define DELEGATE_TO_WEBCONTEXT_9R(name, t1, t2, t3, t4, t5, t6, t7, t8, t9, rt) \
198 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) \
199 { \
200 return m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8, a9); \
201 }
202
203 class GraphicsContext3DContextLostCallbackAdapter : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
204 public:
GraphicsContext3DContextLostCallbackAdapter(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback)205 GraphicsContext3DContextLostCallbackAdapter(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback)
206 : m_contextLostCallback(callback) { }
~GraphicsContext3DContextLostCallbackAdapter()207 virtual ~GraphicsContext3DContextLostCallbackAdapter() { }
208
onContextLost()209 virtual void onContextLost()
210 {
211 if (m_contextLostCallback)
212 m_contextLostCallback->onContextLost();
213 }
214 private:
215 OwnPtr<GraphicsContext3D::ContextLostCallback> m_contextLostCallback;
216 };
217
218 class GraphicsContext3DErrorMessageCallbackAdapter : public blink::WebGraphicsContext3D::WebGraphicsErrorMessageCallback {
219 public:
GraphicsContext3DErrorMessageCallbackAdapter(PassOwnPtr<GraphicsContext3D::ErrorMessageCallback> callback)220 GraphicsContext3DErrorMessageCallbackAdapter(PassOwnPtr<GraphicsContext3D::ErrorMessageCallback> callback)
221 : m_errorMessageCallback(callback) { }
~GraphicsContext3DErrorMessageCallbackAdapter()222 virtual ~GraphicsContext3DErrorMessageCallbackAdapter() { }
223
onErrorMessage(const blink::WebString & message,blink::WGC3Dint id)224 virtual void onErrorMessage(const blink::WebString& message, blink::WGC3Dint id)
225 {
226 if (m_errorMessageCallback)
227 m_errorMessageCallback->onErrorMessage(message, id);
228 }
229 private:
230 OwnPtr<GraphicsContext3D::ErrorMessageCallback> m_errorMessageCallback;
231 };
232
setContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback)233 void GraphicsContext3D::setContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback)
234 {
235 if (m_ownedWebContext) {
236 m_contextLostCallbackAdapter = adoptPtr(new GraphicsContext3DContextLostCallbackAdapter(callback));
237 m_ownedWebContext->setContextLostCallback(m_contextLostCallbackAdapter.get());
238 }
239 }
240
setErrorMessageCallback(PassOwnPtr<GraphicsContext3D::ErrorMessageCallback> callback)241 void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<GraphicsContext3D::ErrorMessageCallback> callback)
242 {
243 if (m_ownedWebContext) {
244 m_errorMessageCallbackAdapter = adoptPtr(new GraphicsContext3DErrorMessageCallbackAdapter(callback));
245 m_ownedWebContext->setErrorMessageCallback(m_errorMessageCallbackAdapter.get());
246 }
247 }
248
create(GraphicsContext3D::Attributes attrs)249 PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs)
250 {
251 blink::WebGraphicsContext3D::Attributes webAttributes;
252 webAttributes.alpha = attrs.alpha;
253 webAttributes.depth = attrs.depth;
254 webAttributes.stencil = attrs.stencil;
255 webAttributes.antialias = attrs.antialias;
256 webAttributes.premultipliedAlpha = attrs.premultipliedAlpha;
257 webAttributes.noExtensions = attrs.noExtensions;
258 webAttributes.shareResources = attrs.shareResources;
259 webAttributes.preferDiscreteGPU = attrs.preferDiscreteGPU;
260 webAttributes.failIfMajorPerformanceCaveat = attrs.failIfMajorPerformanceCaveat;
261 webAttributes.topDocumentURL = attrs.topDocumentURL.string();
262
263 OwnPtr<blink::WebGraphicsContext3D> webContext = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(webAttributes));
264 if (!webContext)
265 return 0;
266
267 return GraphicsContext3D::createGraphicsContextFromWebContext(webContext.release(), attrs.preserveDrawingBuffer);
268 }
269
createGraphicsContextFromProvider(PassOwnPtr<blink::WebGraphicsContext3DProvider> provider,bool preserveDrawingBuffer)270 PassRefPtr<GraphicsContext3D> GraphicsContext3D::createGraphicsContextFromProvider(PassOwnPtr<blink::WebGraphicsContext3DProvider> provider, bool preserveDrawingBuffer)
271 {
272 RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(provider, preserveDrawingBuffer));
273 return context.release();
274 }
275
createGraphicsContextFromWebContext(PassOwnPtr<blink::WebGraphicsContext3D> webContext,bool preserveDrawingBuffer)276 PassRefPtr<GraphicsContext3D> GraphicsContext3D::createGraphicsContextFromWebContext(PassOwnPtr<blink::WebGraphicsContext3D> webContext, bool preserveDrawingBuffer)
277 {
278 RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(webContext, preserveDrawingBuffer));
279 return context.release();
280 }
281
grContext()282 GrContext* GraphicsContext3D::grContext()
283 {
284 return m_grContext;
285 }
286
DELEGATE_TO_WEBCONTEXT_R(makeContextCurrent,bool)287 DELEGATE_TO_WEBCONTEXT_R(makeContextCurrent, bool)
288 DELEGATE_TO_WEBCONTEXT_R(lastFlushID, uint32_t)
289
290 DELEGATE_TO_WEBCONTEXT_1(activeTexture, GC3Denum)
291 DELEGATE_TO_WEBCONTEXT_2(attachShader, Platform3DObject, Platform3DObject)
292
293 void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name)
294 {
295 m_impl->bindAttribLocation(program, index, name.utf8().data());
296 }
297
DELEGATE_TO_WEBCONTEXT_2(bindBuffer,GC3Denum,Platform3DObject)298 DELEGATE_TO_WEBCONTEXT_2(bindBuffer, GC3Denum, Platform3DObject)
299 DELEGATE_TO_WEBCONTEXT_2(bindFramebuffer, GC3Denum, Platform3DObject)
300 DELEGATE_TO_WEBCONTEXT_2(bindRenderbuffer, GC3Denum, Platform3DObject)
301 DELEGATE_TO_WEBCONTEXT_2(bindTexture, GC3Denum, Platform3DObject)
302 DELEGATE_TO_WEBCONTEXT_4(blendColor, GC3Dclampf, GC3Dclampf, GC3Dclampf, GC3Dclampf)
303 DELEGATE_TO_WEBCONTEXT_1(blendEquation, GC3Denum)
304 DELEGATE_TO_WEBCONTEXT_2(blendEquationSeparate, GC3Denum, GC3Denum)
305 DELEGATE_TO_WEBCONTEXT_2(blendFunc, GC3Denum, GC3Denum)
306 DELEGATE_TO_WEBCONTEXT_4(blendFuncSeparate, GC3Denum, GC3Denum, GC3Denum, GC3Denum)
307
308 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
309 {
310 bufferData(target, size, 0, usage);
311 }
312
DELEGATE_TO_WEBCONTEXT_4(bufferData,GC3Denum,GC3Dsizeiptr,const void *,GC3Denum)313 DELEGATE_TO_WEBCONTEXT_4(bufferData, GC3Denum, GC3Dsizeiptr, const void*, GC3Denum)
314 DELEGATE_TO_WEBCONTEXT_4(bufferSubData, GC3Denum, GC3Dintptr, GC3Dsizeiptr, const void*)
315
316 DELEGATE_TO_WEBCONTEXT_1R(checkFramebufferStatus, GC3Denum, GC3Denum)
317 DELEGATE_TO_WEBCONTEXT_1(clear, GC3Dbitfield)
318 DELEGATE_TO_WEBCONTEXT_4(clearColor, GC3Dclampf, GC3Dclampf, GC3Dclampf, GC3Dclampf)
319 DELEGATE_TO_WEBCONTEXT_1(clearDepth, GC3Dclampf)
320 DELEGATE_TO_WEBCONTEXT_1(clearStencil, GC3Dint)
321 DELEGATE_TO_WEBCONTEXT_4(colorMask, GC3Dboolean, GC3Dboolean, GC3Dboolean, GC3Dboolean)
322 DELEGATE_TO_WEBCONTEXT_1(compileShader, Platform3DObject)
323
324 DELEGATE_TO_WEBCONTEXT_8(compressedTexImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, const void*)
325 DELEGATE_TO_WEBCONTEXT_9(compressedTexSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Denum, GC3Dsizei, const void*)
326 DELEGATE_TO_WEBCONTEXT_8(copyTexImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dint)
327 DELEGATE_TO_WEBCONTEXT_8(copyTexSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
328 DELEGATE_TO_WEBCONTEXT_1(cullFace, GC3Denum)
329 DELEGATE_TO_WEBCONTEXT_1(depthFunc, GC3Denum)
330 DELEGATE_TO_WEBCONTEXT_1(depthMask, GC3Dboolean)
331 DELEGATE_TO_WEBCONTEXT_2(depthRange, GC3Dclampf, GC3Dclampf)
332 DELEGATE_TO_WEBCONTEXT_2(detachShader, Platform3DObject, Platform3DObject)
333 DELEGATE_TO_WEBCONTEXT_1(disable, GC3Denum)
334 DELEGATE_TO_WEBCONTEXT_1(disableVertexAttribArray, GC3Duint)
335 DELEGATE_TO_WEBCONTEXT_3(drawArrays, GC3Denum, GC3Dint, GC3Dsizei)
336 DELEGATE_TO_WEBCONTEXT_4(drawElements, GC3Denum, GC3Dsizei, GC3Denum, GC3Dintptr)
337
338 DELEGATE_TO_WEBCONTEXT_1(enable, GC3Denum)
339 DELEGATE_TO_WEBCONTEXT_1(enableVertexAttribArray, GC3Duint)
340 DELEGATE_TO_WEBCONTEXT(finish)
341 DELEGATE_TO_WEBCONTEXT(flush)
342 DELEGATE_TO_WEBCONTEXT_4(framebufferRenderbuffer, GC3Denum, GC3Denum, GC3Denum, Platform3DObject)
343 DELEGATE_TO_WEBCONTEXT_5(framebufferTexture2D, GC3Denum, GC3Denum, GC3Denum, Platform3DObject, GC3Dint)
344 DELEGATE_TO_WEBCONTEXT_1(frontFace, GC3Denum)
345 DELEGATE_TO_WEBCONTEXT_1(generateMipmap, GC3Denum)
346
347 bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
348 {
349 blink::WebGraphicsContext3D::ActiveInfo webInfo;
350 if (!m_impl->getActiveAttrib(program, index, webInfo))
351 return false;
352 info.name = webInfo.name;
353 info.type = webInfo.type;
354 info.size = webInfo.size;
355 return true;
356 }
357
getActiveUniform(Platform3DObject program,GC3Duint index,ActiveInfo & info)358 bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
359 {
360 blink::WebGraphicsContext3D::ActiveInfo webInfo;
361 if (!m_impl->getActiveUniform(program, index, webInfo))
362 return false;
363 info.name = webInfo.name;
364 info.type = webInfo.type;
365 info.size = webInfo.size;
366 return true;
367 }
368
DELEGATE_TO_WEBCONTEXT_4(getAttachedShaders,Platform3DObject,GC3Dsizei,GC3Dsizei *,Platform3DObject *)369 DELEGATE_TO_WEBCONTEXT_4(getAttachedShaders, Platform3DObject, GC3Dsizei, GC3Dsizei*, Platform3DObject*)
370
371 GC3Dint GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
372 {
373 return m_impl->getAttribLocation(program, name.utf8().data());
374 }
375
DELEGATE_TO_WEBCONTEXT_2(getBooleanv,GC3Denum,GC3Dboolean *)376 DELEGATE_TO_WEBCONTEXT_2(getBooleanv, GC3Denum, GC3Dboolean*)
377 DELEGATE_TO_WEBCONTEXT_3(getBufferParameteriv, GC3Denum, GC3Denum, GC3Dint*)
378
379 GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
380 {
381 blink::WebGraphicsContext3D::Attributes webAttributes = m_impl->getContextAttributes();
382 GraphicsContext3D::Attributes attributes;
383 attributes.alpha = webAttributes.alpha;
384 attributes.depth = webAttributes.depth;
385 attributes.stencil = webAttributes.stencil;
386 attributes.antialias = webAttributes.antialias;
387 attributes.premultipliedAlpha = webAttributes.premultipliedAlpha;
388 attributes.preserveDrawingBuffer = m_preserveDrawingBuffer;
389 attributes.preferDiscreteGPU = webAttributes.preferDiscreteGPU;
390 return attributes;
391 }
392
DELEGATE_TO_WEBCONTEXT_R(getError,GC3Denum)393 DELEGATE_TO_WEBCONTEXT_R(getError, GC3Denum)
394 DELEGATE_TO_WEBCONTEXT_2(getFloatv, GC3Denum, GC3Dfloat*)
395 DELEGATE_TO_WEBCONTEXT_4(getFramebufferAttachmentParameteriv, GC3Denum, GC3Denum, GC3Denum, GC3Dint*)
396 DELEGATE_TO_WEBCONTEXT_2(getIntegerv, GC3Denum, GC3Dint*)
397 DELEGATE_TO_WEBCONTEXT_3(getProgramiv, Platform3DObject, GC3Denum, GC3Dint*)
398 DELEGATE_TO_WEBCONTEXT_1R(getProgramInfoLog, Platform3DObject, String)
399 DELEGATE_TO_WEBCONTEXT_3(getRenderbufferParameteriv, GC3Denum, GC3Denum, GC3Dint*)
400 DELEGATE_TO_WEBCONTEXT_3(getShaderiv, Platform3DObject, GC3Denum, GC3Dint*)
401 DELEGATE_TO_WEBCONTEXT_1R(getShaderInfoLog, Platform3DObject, String)
402 DELEGATE_TO_WEBCONTEXT_4(getShaderPrecisionFormat, GC3Denum, GC3Denum, GC3Dint*, GC3Dint*)
403 DELEGATE_TO_WEBCONTEXT_1R(getShaderSource, Platform3DObject, String)
404 DELEGATE_TO_WEBCONTEXT_1R(getString, GC3Denum, String)
405 DELEGATE_TO_WEBCONTEXT_3(getTexParameterfv, GC3Denum, GC3Denum, GC3Dfloat*)
406 DELEGATE_TO_WEBCONTEXT_3(getTexParameteriv, GC3Denum, GC3Denum, GC3Dint*)
407 DELEGATE_TO_WEBCONTEXT_3(getUniformfv, Platform3DObject, GC3Dint, GC3Dfloat*)
408 DELEGATE_TO_WEBCONTEXT_3(getUniformiv, Platform3DObject, GC3Dint, GC3Dint*)
409
410 GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
411 {
412 return m_impl->getUniformLocation(program, name.utf8().data());
413 }
414
DELEGATE_TO_WEBCONTEXT_3(getVertexAttribfv,GC3Duint,GC3Denum,GC3Dfloat *)415 DELEGATE_TO_WEBCONTEXT_3(getVertexAttribfv, GC3Duint, GC3Denum, GC3Dfloat*)
416 DELEGATE_TO_WEBCONTEXT_3(getVertexAttribiv, GC3Duint, GC3Denum, GC3Dint*)
417 DELEGATE_TO_WEBCONTEXT_2R(getVertexAttribOffset, GC3Duint, GC3Denum, GC3Dsizeiptr)
418
419 DELEGATE_TO_WEBCONTEXT_2(hint, GC3Denum, GC3Denum)
420 DELEGATE_TO_WEBCONTEXT_1R(isBuffer, Platform3DObject, GC3Dboolean)
421 DELEGATE_TO_WEBCONTEXT_1R(isEnabled, GC3Denum, GC3Dboolean)
422 DELEGATE_TO_WEBCONTEXT_1R(isFramebuffer, Platform3DObject, GC3Dboolean)
423 DELEGATE_TO_WEBCONTEXT_1R(isProgram, Platform3DObject, GC3Dboolean)
424 DELEGATE_TO_WEBCONTEXT_1R(isRenderbuffer, Platform3DObject, GC3Dboolean)
425 DELEGATE_TO_WEBCONTEXT_1R(isShader, Platform3DObject, GC3Dboolean)
426 DELEGATE_TO_WEBCONTEXT_1R(isTexture, Platform3DObject, GC3Dboolean)
427 DELEGATE_TO_WEBCONTEXT_1(lineWidth, GC3Dfloat)
428 DELEGATE_TO_WEBCONTEXT_1(linkProgram, Platform3DObject)
429
430 void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
431 {
432 if (pname == GL_PACK_ALIGNMENT)
433 m_packAlignment = param;
434 m_impl->pixelStorei(pname, param);
435 }
436
DELEGATE_TO_WEBCONTEXT_2(polygonOffset,GC3Dfloat,GC3Dfloat)437 DELEGATE_TO_WEBCONTEXT_2(polygonOffset, GC3Dfloat, GC3Dfloat)
438
439 DELEGATE_TO_WEBCONTEXT_7(readPixels, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, void*)
440
441 DELEGATE_TO_WEBCONTEXT(releaseShaderCompiler)
442 DELEGATE_TO_WEBCONTEXT_4(renderbufferStorage, GC3Denum, GC3Denum, GC3Dsizei, GC3Dsizei)
443 DELEGATE_TO_WEBCONTEXT_2(sampleCoverage, GC3Dclampf, GC3Dboolean)
444 DELEGATE_TO_WEBCONTEXT_4(scissor, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
445
446 void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
447 {
448 m_impl->shaderSource(shader, string.utf8().data());
449 }
450
DELEGATE_TO_WEBCONTEXT_3(stencilFunc,GC3Denum,GC3Dint,GC3Duint)451 DELEGATE_TO_WEBCONTEXT_3(stencilFunc, GC3Denum, GC3Dint, GC3Duint)
452 DELEGATE_TO_WEBCONTEXT_4(stencilFuncSeparate, GC3Denum, GC3Denum, GC3Dint, GC3Duint)
453 DELEGATE_TO_WEBCONTEXT_1(stencilMask, GC3Duint)
454 DELEGATE_TO_WEBCONTEXT_2(stencilMaskSeparate, GC3Denum, GC3Duint)
455 DELEGATE_TO_WEBCONTEXT_3(stencilOp, GC3Denum, GC3Denum, GC3Denum)
456 DELEGATE_TO_WEBCONTEXT_4(stencilOpSeparate, GC3Denum, GC3Denum, GC3Denum, GC3Denum)
457
458 DELEGATE_TO_WEBCONTEXT_9(texImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dsizei, GC3Dsizei, GC3Dint, GC3Denum, GC3Denum, const void*)
459 DELEGATE_TO_WEBCONTEXT_3(texParameterf, GC3Denum, GC3Denum, GC3Dfloat)
460 DELEGATE_TO_WEBCONTEXT_3(texParameteri, GC3Denum, GC3Denum, GC3Dint)
461 DELEGATE_TO_WEBCONTEXT_9(texSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, const void*)
462
463 DELEGATE_TO_WEBCONTEXT_2(uniform1f, GC3Dint, GC3Dfloat)
464 DELEGATE_TO_WEBCONTEXT_3(uniform1fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
465 DELEGATE_TO_WEBCONTEXT_2(uniform1i, GC3Dint, GC3Dint)
466 DELEGATE_TO_WEBCONTEXT_3(uniform1iv, GC3Dint, GC3Dsizei, GC3Dint*)
467 DELEGATE_TO_WEBCONTEXT_3(uniform2f, GC3Dint, GC3Dfloat, GC3Dfloat)
468 DELEGATE_TO_WEBCONTEXT_3(uniform2fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
469 DELEGATE_TO_WEBCONTEXT_3(uniform2i, GC3Dint, GC3Dint, GC3Dint)
470 DELEGATE_TO_WEBCONTEXT_3(uniform2iv, GC3Dint, GC3Dsizei, GC3Dint*)
471 DELEGATE_TO_WEBCONTEXT_4(uniform3f, GC3Dint, GC3Dfloat, GC3Dfloat, GC3Dfloat)
472 DELEGATE_TO_WEBCONTEXT_3(uniform3fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
473 DELEGATE_TO_WEBCONTEXT_4(uniform3i, GC3Dint, GC3Dint, GC3Dint, GC3Dint)
474 DELEGATE_TO_WEBCONTEXT_3(uniform3iv, GC3Dint, GC3Dsizei, GC3Dint*)
475 DELEGATE_TO_WEBCONTEXT_5(uniform4f, GC3Dint, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat)
476 DELEGATE_TO_WEBCONTEXT_3(uniform4fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
477 DELEGATE_TO_WEBCONTEXT_5(uniform4i, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint)
478 DELEGATE_TO_WEBCONTEXT_3(uniform4iv, GC3Dint, GC3Dsizei, GC3Dint*)
479 DELEGATE_TO_WEBCONTEXT_4(uniformMatrix2fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
480 DELEGATE_TO_WEBCONTEXT_4(uniformMatrix3fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
481 DELEGATE_TO_WEBCONTEXT_4(uniformMatrix4fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
482
483 DELEGATE_TO_WEBCONTEXT_1(useProgram, Platform3DObject)
484 DELEGATE_TO_WEBCONTEXT_1(validateProgram, Platform3DObject)
485
486 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib1f, GC3Duint, GC3Dfloat)
487 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib1fv, GC3Duint, GC3Dfloat*)
488 DELEGATE_TO_WEBCONTEXT_3(vertexAttrib2f, GC3Duint, GC3Dfloat, GC3Dfloat)
489 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib2fv, GC3Duint, GC3Dfloat*)
490 DELEGATE_TO_WEBCONTEXT_4(vertexAttrib3f, GC3Duint, GC3Dfloat, GC3Dfloat, GC3Dfloat)
491 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib3fv, GC3Duint, GC3Dfloat*)
492 DELEGATE_TO_WEBCONTEXT_5(vertexAttrib4f, GC3Duint, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat)
493 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib4fv, GC3Duint, GC3Dfloat*)
494 DELEGATE_TO_WEBCONTEXT_6(vertexAttribPointer, GC3Duint, GC3Dint, GC3Denum, GC3Dboolean, GC3Dsizei, GC3Dintptr)
495
496 DELEGATE_TO_WEBCONTEXT_4(viewport, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
497
498 void GraphicsContext3D::markContextChanged()
499 {
500 m_layerComposited = false;
501 }
502
layerComposited() const503 bool GraphicsContext3D::layerComposited() const
504 {
505 return m_layerComposited;
506 }
507
markLayerComposited()508 void GraphicsContext3D::markLayerComposited()
509 {
510 m_layerComposited = true;
511 }
512
paintRenderingResultsToCanvas(ImageBuffer * imageBuffer,DrawingBuffer * drawingBuffer)513 void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, DrawingBuffer* drawingBuffer)
514 {
515 Platform3DObject framebufferId;
516 int width, height;
517 getDrawingParameters(drawingBuffer, m_impl, &framebufferId, &width, &height);
518 paintFramebufferToCanvas(framebufferId, width, height, !getContextAttributes().premultipliedAlpha, imageBuffer);
519 }
520
paintRenderingResultsToImageData(DrawingBuffer * drawingBuffer,int & width,int & height)521 PassRefPtr<Uint8ClampedArray> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer* drawingBuffer, int& width, int& height)
522 {
523 if (getContextAttributes().premultipliedAlpha)
524 return 0;
525
526 Platform3DObject framebufferId;
527 getDrawingParameters(drawingBuffer, m_impl, &framebufferId, &width, &height);
528
529 Checked<int, RecordOverflow> dataSize = 4;
530 dataSize *= width;
531 dataSize *= height;
532 if (dataSize.hasOverflowed())
533 return 0;
534
535 RefPtr<Uint8ClampedArray> pixels = Uint8ClampedArray::createUninitialized(width * height * 4);
536
537 m_impl->bindFramebuffer(GL_FRAMEBUFFER, framebufferId);
538 readBackFramebuffer(pixels->data(), width, height, ReadbackRGBA, AlphaDoNothing);
539 flipVertically(pixels->data(), width, height);
540
541 return pixels.release();
542 }
543
readBackFramebuffer(unsigned char * pixels,int width,int height,ReadbackOrder readbackOrder,AlphaOp op)544 void GraphicsContext3D::readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder readbackOrder, AlphaOp op)
545 {
546 if (m_packAlignment > 4)
547 m_impl->pixelStorei(GL_PACK_ALIGNMENT, 1);
548 m_impl->readPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
549 if (m_packAlignment > 4)
550 m_impl->pixelStorei(GL_PACK_ALIGNMENT, m_packAlignment);
551
552 size_t bufferSize = 4 * width * height;
553
554 if (readbackOrder == ReadbackSkia) {
555 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
556 // Swizzle red and blue channels to match SkBitmap's byte ordering.
557 // TODO(kbr): expose GL_BGRA as extension.
558 for (size_t i = 0; i < bufferSize; i += 4) {
559 std::swap(pixels[i], pixels[i + 2]);
560 }
561 #endif
562 }
563
564 if (op == AlphaDoPremultiply) {
565 for (size_t i = 0; i < bufferSize; i += 4) {
566 pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
567 pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
568 pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
569 }
570 } else if (op != AlphaDoNothing) {
571 ASSERT_NOT_REACHED();
572 }
573 }
574
DELEGATE_TO_WEBCONTEXT_R(createBuffer,Platform3DObject)575 DELEGATE_TO_WEBCONTEXT_R(createBuffer, Platform3DObject)
576 DELEGATE_TO_WEBCONTEXT_R(createFramebuffer, Platform3DObject)
577 DELEGATE_TO_WEBCONTEXT_R(createProgram, Platform3DObject)
578 DELEGATE_TO_WEBCONTEXT_R(createRenderbuffer, Platform3DObject)
579 DELEGATE_TO_WEBCONTEXT_1R(createShader, GC3Denum, Platform3DObject)
580 DELEGATE_TO_WEBCONTEXT_R(createTexture, Platform3DObject)
581
582 DELEGATE_TO_WEBCONTEXT_1(deleteBuffer, Platform3DObject)
583 DELEGATE_TO_WEBCONTEXT_1(deleteFramebuffer, Platform3DObject)
584 DELEGATE_TO_WEBCONTEXT_1(deleteProgram, Platform3DObject)
585 DELEGATE_TO_WEBCONTEXT_1(deleteRenderbuffer, Platform3DObject)
586 DELEGATE_TO_WEBCONTEXT_1(deleteShader, Platform3DObject)
587 DELEGATE_TO_WEBCONTEXT_1(deleteTexture, Platform3DObject)
588
589 DELEGATE_TO_WEBCONTEXT_1(synthesizeGLError, GC3Denum)
590
591 Extensions3D* GraphicsContext3D::extensions()
592 {
593 if (!m_extensions)
594 m_extensions = adoptPtr(new Extensions3D(this));
595 return m_extensions.get();
596 }
597
texImage2DResourceSafe(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height,GC3Dint border,GC3Denum format,GC3Denum type,GC3Dint unpackAlignment)598 bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment)
599 {
600 ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8);
601 texImage2D(target, level, internalformat, width, height, border, format, type, 0);
602 return true;
603 }
604
computeFormatAndTypeParameters(GC3Denum format,GC3Denum type,unsigned int * componentsPerPixel,unsigned int * bytesPerComponent)605 bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format,
606 GC3Denum type,
607 unsigned int* componentsPerPixel,
608 unsigned int* bytesPerComponent)
609 {
610 switch (format) {
611 case GL_ALPHA:
612 case GL_LUMINANCE:
613 case GL_DEPTH_COMPONENT:
614 case GL_DEPTH_STENCIL_OES:
615 *componentsPerPixel = 1;
616 break;
617 case GL_LUMINANCE_ALPHA:
618 *componentsPerPixel = 2;
619 break;
620 case GL_RGB:
621 *componentsPerPixel = 3;
622 break;
623 case GL_RGBA:
624 case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
625 *componentsPerPixel = 4;
626 break;
627 default:
628 return false;
629 }
630 switch (type) {
631 case GL_UNSIGNED_BYTE:
632 *bytesPerComponent = sizeof(GC3Dubyte);
633 break;
634 case GL_UNSIGNED_SHORT:
635 *bytesPerComponent = sizeof(GC3Dushort);
636 break;
637 case GL_UNSIGNED_SHORT_5_6_5:
638 case GL_UNSIGNED_SHORT_4_4_4_4:
639 case GL_UNSIGNED_SHORT_5_5_5_1:
640 *componentsPerPixel = 1;
641 *bytesPerComponent = sizeof(GC3Dushort);
642 break;
643 case GL_UNSIGNED_INT_24_8_OES:
644 case GL_UNSIGNED_INT:
645 *bytesPerComponent = sizeof(GC3Duint);
646 break;
647 case GL_FLOAT: // OES_texture_float
648 *bytesPerComponent = sizeof(GC3Dfloat);
649 break;
650 case GL_HALF_FLOAT_OES: // OES_texture_half_float
651 *bytesPerComponent = sizeof(GC3Dhalffloat);
652 break;
653 default:
654 return false;
655 }
656 return true;
657 }
658
computeImageSizeInBytes(GC3Denum format,GC3Denum type,GC3Dsizei width,GC3Dsizei height,GC3Dint alignment,unsigned int * imageSizeInBytes,unsigned int * paddingInBytes)659 GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment,
660 unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
661 {
662 ASSERT(imageSizeInBytes);
663 ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8);
664 if (width < 0 || height < 0)
665 return GL_INVALID_VALUE;
666 unsigned int bytesPerComponent, componentsPerPixel;
667 if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel))
668 return GL_INVALID_ENUM;
669 if (!width || !height) {
670 *imageSizeInBytes = 0;
671 if (paddingInBytes)
672 *paddingInBytes = 0;
673 return GL_NO_ERROR;
674 }
675 CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel);
676 checkedValue *= width;
677 if (!checkedValue.isValid())
678 return GL_INVALID_VALUE;
679 unsigned int validRowSize = checkedValue.value();
680 unsigned int padding = 0;
681 unsigned int residual = validRowSize % alignment;
682 if (residual) {
683 padding = alignment - residual;
684 checkedValue += padding;
685 }
686 // Last row needs no padding.
687 checkedValue *= (height - 1);
688 checkedValue += validRowSize;
689 if (!checkedValue.isValid())
690 return GL_INVALID_VALUE;
691 *imageSizeInBytes = checkedValue.value();
692 if (paddingInBytes)
693 *paddingInBytes = padding;
694 return GL_NO_ERROR;
695 }
696
ImageExtractor(Image * image,ImageHtmlDomSource imageHtmlDomSource,bool premultiplyAlpha,bool ignoreGammaAndColorProfile)697 GraphicsContext3D::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
698 {
699 m_image = image;
700 m_imageHtmlDomSource = imageHtmlDomSource;
701 m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile);
702 }
703
~ImageExtractor()704 GraphicsContext3D::ImageExtractor::~ImageExtractor()
705 {
706 if (m_skiaImage)
707 m_skiaImage->bitmap().unlockPixels();
708 }
709
extractImage(bool premultiplyAlpha,bool ignoreGammaAndColorProfile)710 bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
711 {
712 if (!m_image)
713 return false;
714 m_skiaImage = m_image->nativeImageForCurrentFrame();
715 m_alphaOp = AlphaDoNothing;
716 bool hasAlpha = m_skiaImage ? !m_skiaImage->bitmap().isOpaque() : true;
717 if ((!m_skiaImage || ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && m_image->data()) {
718 // Attempt to get raw unpremultiplied image data.
719 OwnPtr<ImageDecoder> decoder(ImageDecoder::create(
720 *(m_image->data()), ImageSource::AlphaNotPremultiplied,
721 ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied));
722 if (!decoder)
723 return false;
724 decoder->setData(m_image->data(), true);
725 if (!decoder->frameCount())
726 return false;
727 ImageFrame* frame = decoder->frameBufferAtIndex(0);
728 if (!frame || frame->status() != ImageFrame::FrameComplete)
729 return false;
730 hasAlpha = frame->hasAlpha();
731 m_nativeImage = frame->asNewNativeImage();
732 if (!m_nativeImage.get() || !m_nativeImage->isDataComplete() || !m_nativeImage->bitmap().width() || !m_nativeImage->bitmap().height())
733 return false;
734 SkBitmap::Config skiaConfig = m_nativeImage->bitmap().config();
735 if (skiaConfig != SkBitmap::kARGB_8888_Config)
736 return false;
737 m_skiaImage = m_nativeImage.get();
738 if (hasAlpha && premultiplyAlpha)
739 m_alphaOp = AlphaDoPremultiply;
740 } else if (!premultiplyAlpha && hasAlpha) {
741 // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value for each pixel is 0xFF
742 // which is true at present and may be changed in the future and needs adjustment accordingly.
743 // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port,
744 // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false.
745 if (m_imageHtmlDomSource != HtmlDomVideo)
746 m_alphaOp = AlphaDoUnmultiply;
747 }
748 if (!m_skiaImage)
749 return false;
750
751 m_imageSourceFormat = SK_B32_SHIFT ? DataFormatRGBA8 : DataFormatBGRA8;
752 m_imageWidth = m_skiaImage->bitmap().width();
753 m_imageHeight = m_skiaImage->bitmap().height();
754 if (!m_imageWidth || !m_imageHeight)
755 return false;
756 m_imageSourceUnpackAlignment = 0;
757 m_skiaImage->bitmap().lockPixels();
758 m_imagePixelData = m_skiaImage->bitmap().getPixels();
759 return true;
760 }
761
getClearBitsByFormat(GC3Denum format)762 unsigned GraphicsContext3D::getClearBitsByFormat(GC3Denum format)
763 {
764 switch (format) {
765 case GL_ALPHA:
766 case GL_LUMINANCE:
767 case GL_LUMINANCE_ALPHA:
768 case GL_RGB:
769 case GL_RGB565:
770 case GL_RGBA:
771 case GL_RGBA4:
772 case GL_RGB5_A1:
773 return GL_COLOR_BUFFER_BIT;
774 case GL_DEPTH_COMPONENT16:
775 case GL_DEPTH_COMPONENT:
776 return GL_DEPTH_BUFFER_BIT;
777 case GL_STENCIL_INDEX8:
778 return GL_STENCIL_BUFFER_BIT;
779 case GL_DEPTH_STENCIL_OES:
780 return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
781 default:
782 return 0;
783 }
784 }
785
getChannelBitsByFormat(GC3Denum format)786 unsigned GraphicsContext3D::getChannelBitsByFormat(GC3Denum format)
787 {
788 switch (format) {
789 case GL_ALPHA:
790 return ChannelAlpha;
791 case GL_LUMINANCE:
792 return ChannelRGB;
793 case GL_LUMINANCE_ALPHA:
794 return ChannelRGBA;
795 case GL_RGB:
796 case GL_RGB565:
797 return ChannelRGB;
798 case GL_RGBA:
799 case GL_RGBA4:
800 case GL_RGB5_A1:
801 return ChannelRGBA;
802 case GL_DEPTH_COMPONENT16:
803 case GL_DEPTH_COMPONENT:
804 return ChannelDepth;
805 case GL_STENCIL_INDEX8:
806 return ChannelStencil;
807 case GL_DEPTH_STENCIL_OES:
808 return ChannelDepth | ChannelStencil;
809 default:
810 return 0;
811 }
812 }
813
paintFramebufferToCanvas(int framebuffer,int width,int height,bool premultiplyAlpha,ImageBuffer * imageBuffer)814 void GraphicsContext3D::paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer* imageBuffer)
815 {
816 unsigned char* pixels = 0;
817
818 const SkBitmap& canvasBitmap = imageBuffer->bitmap();
819 const SkBitmap* readbackBitmap = 0;
820 ASSERT(canvasBitmap.config() == SkBitmap::kARGB_8888_Config);
821 if (canvasBitmap.width() == width && canvasBitmap.height() == height) {
822 // This is the fastest and most common case. We read back
823 // directly into the canvas's backing store.
824 readbackBitmap = &canvasBitmap;
825 m_resizingBitmap.reset();
826 } else {
827 // We need to allocate a temporary bitmap for reading back the
828 // pixel data. We will then use Skia to rescale this bitmap to
829 // the size of the canvas's backing store.
830 if (m_resizingBitmap.width() != width || m_resizingBitmap.height() != height) {
831 m_resizingBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
832 if (!m_resizingBitmap.allocPixels())
833 return;
834 }
835 readbackBitmap = &m_resizingBitmap;
836 }
837
838 // Read back the frame buffer.
839 SkAutoLockPixels bitmapLock(*readbackBitmap);
840 pixels = static_cast<unsigned char*>(readbackBitmap->getPixels());
841
842 m_impl->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
843 readBackFramebuffer(pixels, width, height, ReadbackSkia, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing);
844 flipVertically(pixels, width, height);
845
846 readbackBitmap->notifyPixelsChanged();
847 if (m_resizingBitmap.readyToDraw()) {
848 // We need to draw the resizing bitmap into the canvas's backing store.
849 SkCanvas canvas(canvasBitmap);
850 SkRect dst;
851 dst.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(canvasBitmap.width()), SkIntToScalar(canvasBitmap.height()));
852 canvas.drawBitmapRect(m_resizingBitmap, 0, dst);
853 }
854 }
855
856 namespace {
857
splitStringHelper(const String & str,HashSet<String> & set)858 void splitStringHelper(const String& str, HashSet<String>& set)
859 {
860 Vector<String> substrings;
861 str.split(" ", substrings);
862 for (size_t i = 0; i < substrings.size(); ++i)
863 set.add(substrings[i]);
864 }
865
mapExtensionName(const String & name)866 String mapExtensionName(const String& name)
867 {
868 if (name == "GL_ANGLE_framebuffer_blit"
869 || name == "GL_ANGLE_framebuffer_multisample")
870 return "GL_CHROMIUM_framebuffer_multisample";
871 return name;
872 }
873
874 } // anonymous namespace
875
initializeExtensions()876 void GraphicsContext3D::initializeExtensions()
877 {
878 if (m_initializedAvailableExtensions)
879 return;
880
881 m_initializedAvailableExtensions = true;
882 bool success = m_impl->makeContextCurrent();
883 ASSERT(success);
884 if (!success)
885 return;
886
887 String extensionsString = m_impl->getString(GL_EXTENSIONS);
888 splitStringHelper(extensionsString, m_enabledExtensions);
889
890 String requestableExtensionsString = m_impl->getRequestableExtensionsCHROMIUM();
891 splitStringHelper(requestableExtensionsString, m_requestableExtensions);
892 }
893
894
supportsExtension(const String & name)895 bool GraphicsContext3D::supportsExtension(const String& name)
896 {
897 initializeExtensions();
898 String mappedName = mapExtensionName(name);
899 return m_enabledExtensions.contains(mappedName) || m_requestableExtensions.contains(mappedName);
900 }
901
ensureExtensionEnabled(const String & name)902 bool GraphicsContext3D::ensureExtensionEnabled(const String& name)
903 {
904 initializeExtensions();
905
906 String mappedName = mapExtensionName(name);
907 if (m_enabledExtensions.contains(mappedName))
908 return true;
909
910 if (m_requestableExtensions.contains(mappedName)) {
911 m_impl->requestExtensionCHROMIUM(mappedName.ascii().data());
912 m_enabledExtensions.clear();
913 m_requestableExtensions.clear();
914 m_initializedAvailableExtensions = false;
915 }
916
917 initializeExtensions();
918 fprintf(stderr, "m_enabledExtensions.contains(%s) == %d\n", mappedName.ascii().data(), m_enabledExtensions.contains(mappedName));
919 return m_enabledExtensions.contains(mappedName);
920 }
921
isExtensionEnabled(const String & name)922 bool GraphicsContext3D::isExtensionEnabled(const String& name)
923 {
924 initializeExtensions();
925 String mappedName = mapExtensionName(name);
926 return m_enabledExtensions.contains(mappedName);
927 }
928
flipVertically(uint8_t * framebuffer,int width,int height)929 void GraphicsContext3D::flipVertically(uint8_t* framebuffer, int width, int height)
930 {
931 m_scanline.resize(width * 4);
932 uint8* scanline = &m_scanline[0];
933 unsigned rowBytes = width * 4;
934 unsigned count = height / 2;
935 for (unsigned i = 0; i < count; i++) {
936 uint8* rowA = framebuffer + i * rowBytes;
937 uint8* rowB = framebuffer + (height - i - 1) * rowBytes;
938 memcpy(scanline, rowB, rowBytes);
939 memcpy(rowB, rowA, rowBytes);
940 memcpy(rowA, scanline, rowBytes);
941 }
942 }
943
944 } // namespace WebCore
945