1/*
2 * Copyright (C) 2010, 2016 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 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 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#if ENABLE(GRAPHICS_CONTEXT_3D)
31
32#include "GraphicsContext3D.h"
33
34#include "Extensions3D.h"
35#include "FormatConverter.h"
36#include "Image.h"
37#include "ImageData.h"
38#include "ImageObserver.h"
39#include <wtf/UniqueArray.h>
40
41namespace WebCore {
42
43namespace {
44
45GraphicsContext3D::DataFormat getDataFormat(GC3Denum destinationFormat, GC3Denum destinationType)
46{
47 GraphicsContext3D::DataFormat dstFormat = GraphicsContext3D::DataFormatRGBA8;
48 switch (destinationType) {
49 case GraphicsContext3D::UNSIGNED_BYTE:
50 switch (destinationFormat) {
51 case GraphicsContext3D::RGB:
52 dstFormat = GraphicsContext3D::DataFormatRGB8;
53 break;
54 case GraphicsContext3D::RGBA:
55 dstFormat = GraphicsContext3D::DataFormatRGBA8;
56 break;
57 case GraphicsContext3D::ALPHA:
58 dstFormat = GraphicsContext3D::DataFormatA8;
59 break;
60 case GraphicsContext3D::LUMINANCE:
61 dstFormat = GraphicsContext3D::DataFormatR8;
62 break;
63 case GraphicsContext3D::LUMINANCE_ALPHA:
64 dstFormat = GraphicsContext3D::DataFormatRA8;
65 break;
66 case GraphicsContext3D::SRGB:
67 dstFormat = GraphicsContext3D::DataFormatRGB8;
68 break;
69 case GraphicsContext3D::SRGB_ALPHA:
70 dstFormat = GraphicsContext3D::DataFormatRGBA8;
71 break;
72 default:
73 ASSERT_NOT_REACHED();
74 }
75 break;
76 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
77 dstFormat = GraphicsContext3D::DataFormatRGBA4444;
78 break;
79 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
80 dstFormat = GraphicsContext3D::DataFormatRGBA5551;
81 break;
82 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
83 dstFormat = GraphicsContext3D::DataFormatRGB565;
84 break;
85 case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
86 switch (destinationFormat) {
87 case GraphicsContext3D::RGB:
88 dstFormat = GraphicsContext3D::DataFormatRGB16F;
89 break;
90 case GraphicsContext3D::RGBA:
91 dstFormat = GraphicsContext3D::DataFormatRGBA16F;
92 break;
93 case GraphicsContext3D::ALPHA:
94 dstFormat = GraphicsContext3D::DataFormatA16F;
95 break;
96 case GraphicsContext3D::LUMINANCE:
97 dstFormat = GraphicsContext3D::DataFormatR16F;
98 break;
99 case GraphicsContext3D::LUMINANCE_ALPHA:
100 dstFormat = GraphicsContext3D::DataFormatRA16F;
101 break;
102 case GraphicsContext3D::SRGB:
103 dstFormat = GraphicsContext3D::DataFormatRGB16F;
104 break;
105 case GraphicsContext3D::SRGB_ALPHA:
106 dstFormat = GraphicsContext3D::DataFormatRGBA16F;
107 break;
108 default:
109 ASSERT_NOT_REACHED();
110 }
111 break;
112 case GraphicsContext3D::FLOAT: // OES_texture_float
113 switch (destinationFormat) {
114 case GraphicsContext3D::RGB:
115 dstFormat = GraphicsContext3D::DataFormatRGB32F;
116 break;
117 case GraphicsContext3D::RGBA:
118 dstFormat = GraphicsContext3D::DataFormatRGBA32F;
119 break;
120 case GraphicsContext3D::ALPHA:
121 dstFormat = GraphicsContext3D::DataFormatA32F;
122 break;
123 case GraphicsContext3D::LUMINANCE:
124 dstFormat = GraphicsContext3D::DataFormatR32F;
125 break;
126 case GraphicsContext3D::LUMINANCE_ALPHA:
127 dstFormat = GraphicsContext3D::DataFormatRA32F;
128 break;
129 case GraphicsContext3D::SRGB:
130 dstFormat = GraphicsContext3D::DataFormatRGB32F;
131 break;
132 case GraphicsContext3D::SRGB_ALPHA:
133 dstFormat = GraphicsContext3D::DataFormatRGBA32F;
134 break;
135 default:
136 ASSERT_NOT_REACHED();
137 }
138 break;
139 default:
140 ASSERT_NOT_REACHED();
141 }
142 return dstFormat;
143}
144
145} // anonymous namespace
146
147bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment)
148{
149 ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8);
150 UniqueArray<unsigned char> zero;
151 if (width > 0 && height > 0) {
152 unsigned int size;
153 GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, nullptr);
154 if (error != GraphicsContext3D::NO_ERROR) {
155 synthesizeGLError(error);
156 return false;
157 }
158 zero = makeUniqueArray<unsigned char>(size);
159 if (!zero) {
160 synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
161 return false;
162 }
163 memset(zero.get(), 0, size);
164 }
165 return texImage2D(target, level, internalformat, width, height, border, format, type, zero.get());
166}
167
168bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format, GC3Denum type, unsigned int* componentsPerPixel, unsigned int* bytesPerComponent)
169{
170 switch (format) {
171 case GraphicsContext3D::RED:
172 case GraphicsContext3D::RED_INTEGER:
173 case GraphicsContext3D::ALPHA:
174 case GraphicsContext3D::LUMINANCE:
175 case GraphicsContext3D::DEPTH_COMPONENT:
176 case GraphicsContext3D::DEPTH_STENCIL:
177 *componentsPerPixel = 1;
178 break;
179 case GraphicsContext3D::RG:
180 case GraphicsContext3D::RG_INTEGER:
181 case GraphicsContext3D::LUMINANCE_ALPHA:
182 *componentsPerPixel = 2;
183 break;
184 case GraphicsContext3D::RGB:
185 case GraphicsContext3D::RGB_INTEGER:
186 case Extensions3D::SRGB_EXT:
187 *componentsPerPixel = 3;
188 break;
189 case GraphicsContext3D::RGBA:
190 case GraphicsContext3D::RGBA_INTEGER:
191 case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
192 case Extensions3D::SRGB_ALPHA_EXT:
193 *componentsPerPixel = 4;
194 break;
195 default:
196 return false;
197 }
198
199 switch (type) {
200 case GraphicsContext3D::UNSIGNED_BYTE:
201 *bytesPerComponent = sizeof(GC3Dubyte);
202 break;
203 case GraphicsContext3D::BYTE:
204 *bytesPerComponent = sizeof(GC3Dbyte);
205 break;
206 case GraphicsContext3D::UNSIGNED_SHORT:
207 *bytesPerComponent = sizeof(GC3Dushort);
208 break;
209 case GraphicsContext3D::SHORT:
210 *bytesPerComponent = sizeof(GC3Dshort);
211 break;
212 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
213 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
214 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
215 *componentsPerPixel = 1;
216 *bytesPerComponent = sizeof(GC3Dushort);
217 break;
218 case GraphicsContext3D::UNSIGNED_INT_24_8:
219 case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
220 case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
221 case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV:
222 *componentsPerPixel = 1;
223 *bytesPerComponent = sizeof(GC3Duint);
224 break;
225 case GraphicsContext3D::UNSIGNED_INT:
226 *bytesPerComponent = sizeof(GC3Duint);
227 break;
228 case GraphicsContext3D::INT:
229 *bytesPerComponent = sizeof(GC3Dint);
230 break;
231 case GraphicsContext3D::FLOAT: // OES_texture_float
232 *bytesPerComponent = sizeof(GC3Dfloat);
233 break;
234 case GraphicsContext3D::HALF_FLOAT:
235 case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
236 *bytesPerComponent = sizeof(GC3Dhalffloat);
237 break;
238 case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV:
239 *bytesPerComponent = sizeof(GC3Dfloat) + sizeof(GC3Duint);
240 break;
241 default:
242 return false;
243 }
244 return true;
245}
246
247bool GraphicsContext3D::possibleFormatAndTypeForInternalFormat(GC3Denum internalFormat, GC3Denum& format, GC3Denum& type)
248{
249#define POSSIBLE_FORMAT_TYPE_CASE(internalFormatMacro, formatMacro, typeMacro) case internalFormatMacro: \
250 format = formatMacro; \
251 type = GraphicsContext3D::typeMacro; \
252 break;
253
254 switch (internalFormat) {
255 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB , GraphicsContext3D::RGB , UNSIGNED_BYTE );
256 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA , GraphicsContext3D::RGBA , UNSIGNED_BYTE );
257 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::LUMINANCE_ALPHA , GraphicsContext3D::LUMINANCE_ALPHA, UNSIGNED_BYTE );
258 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::LUMINANCE , GraphicsContext3D::LUMINANCE , UNSIGNED_BYTE );
259 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::ALPHA , GraphicsContext3D::ALPHA , UNSIGNED_BYTE );
260 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8 , GraphicsContext3D::RED , UNSIGNED_BYTE );
261 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8_SNORM , GraphicsContext3D::RED , BYTE );
262 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16F , GraphicsContext3D::RED , HALF_FLOAT );
263 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32F , GraphicsContext3D::RED , FLOAT );
264 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8UI , GraphicsContext3D::RED_INTEGER , UNSIGNED_BYTE );
265 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R8I , GraphicsContext3D::RED_INTEGER , BYTE );
266 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16UI , GraphicsContext3D::RED_INTEGER , UNSIGNED_SHORT );
267 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R16I , GraphicsContext3D::RED_INTEGER , SHORT );
268 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32UI , GraphicsContext3D::RED_INTEGER , UNSIGNED_INT );
269 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R32I , GraphicsContext3D::RED_INTEGER , INT );
270 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8 , GraphicsContext3D::RG , UNSIGNED_BYTE );
271 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8_SNORM , GraphicsContext3D::RG , BYTE );
272 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16F , GraphicsContext3D::RG , HALF_FLOAT );
273 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32F , GraphicsContext3D::RG , FLOAT );
274 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8UI , GraphicsContext3D::RG_INTEGER , UNSIGNED_BYTE );
275 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG8I , GraphicsContext3D::RG_INTEGER , BYTE );
276 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16UI , GraphicsContext3D::RG_INTEGER , UNSIGNED_SHORT );
277 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG16I , GraphicsContext3D::RG_INTEGER , SHORT );
278 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32UI , GraphicsContext3D::RG_INTEGER , UNSIGNED_INT );
279 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RG32I , GraphicsContext3D::RG_INTEGER , INT );
280 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8 , GraphicsContext3D::RGB , UNSIGNED_BYTE );
281 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::SRGB8 , GraphicsContext3D::RGB , UNSIGNED_BYTE );
282 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB565 , GraphicsContext3D::RGB , UNSIGNED_SHORT_5_6_5 );
283 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8_SNORM , GraphicsContext3D::RGB , BYTE );
284 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::R11F_G11F_B10F , GraphicsContext3D::RGB , UNSIGNED_INT_10F_11F_11F_REV );
285 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB9_E5 , GraphicsContext3D::RGB , UNSIGNED_INT_5_9_9_9_REV );
286 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16F , GraphicsContext3D::RGB , HALF_FLOAT );
287 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32F , GraphicsContext3D::RGB , FLOAT );
288 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8UI , GraphicsContext3D::RGB_INTEGER , UNSIGNED_BYTE );
289 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB8I , GraphicsContext3D::RGB_INTEGER , BYTE );
290 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16UI , GraphicsContext3D::RGB_INTEGER , UNSIGNED_SHORT );
291 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB16I , GraphicsContext3D::RGB_INTEGER , SHORT );
292 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32UI , GraphicsContext3D::RGB_INTEGER , UNSIGNED_INT );
293 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB32I , GraphicsContext3D::RGB_INTEGER , INT );
294 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8 , GraphicsContext3D::RGBA , UNSIGNED_BYTE );
295 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::SRGB8_ALPHA8 , GraphicsContext3D::RGBA , UNSIGNED_BYTE );
296 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8_SNORM , GraphicsContext3D::RGBA , BYTE );
297 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB5_A1 , GraphicsContext3D::RGBA , UNSIGNED_SHORT_5_5_5_1 );
298 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA4 , GraphicsContext3D::RGBA , UNSIGNED_SHORT_4_4_4_4 );
299 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB10_A2 , GraphicsContext3D::RGBA , UNSIGNED_INT_2_10_10_10_REV );
300 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16F , GraphicsContext3D::RGBA , HALF_FLOAT );
301 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32F , GraphicsContext3D::RGBA , FLOAT );
302 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8UI , GraphicsContext3D::RGBA_INTEGER , UNSIGNED_BYTE );
303 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA8I , GraphicsContext3D::RGBA_INTEGER , BYTE );
304 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGB10_A2UI , GraphicsContext3D::RGBA_INTEGER , UNSIGNED_INT_2_10_10_10_REV );
305 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16UI , GraphicsContext3D::RGBA_INTEGER , UNSIGNED_SHORT );
306 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA16I , GraphicsContext3D::RGBA_INTEGER , SHORT );
307 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32I , GraphicsContext3D::RGBA_INTEGER , INT );
308 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::RGBA32UI , GraphicsContext3D::RGBA_INTEGER , UNSIGNED_INT );
309 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT16 , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_SHORT );
310 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_SHORT );
311 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT24 , GraphicsContext3D::DEPTH_COMPONENT, UNSIGNED_INT );
312 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_COMPONENT32F, GraphicsContext3D::DEPTH_COMPONENT, FLOAT );
313 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH_STENCIL , GraphicsContext3D::DEPTH_STENCIL , UNSIGNED_INT_24_8 );
314 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH24_STENCIL8 , GraphicsContext3D::DEPTH_STENCIL , UNSIGNED_INT_24_8 );
315 POSSIBLE_FORMAT_TYPE_CASE(GraphicsContext3D::DEPTH32F_STENCIL8 , GraphicsContext3D::DEPTH_STENCIL , FLOAT_32_UNSIGNED_INT_24_8_REV);
316 POSSIBLE_FORMAT_TYPE_CASE(Extensions3D::SRGB_EXT , Extensions3D::SRGB_EXT , UNSIGNED_BYTE );
317 POSSIBLE_FORMAT_TYPE_CASE(Extensions3D::SRGB_ALPHA_EXT , Extensions3D::SRGB_ALPHA_EXT , UNSIGNED_BYTE );
318 default:
319 return false;
320 }
321#undef POSSIBLE_FORMAT_TYPE_CASE
322
323 return true;
324}
325
326GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment, unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
327{
328 ASSERT(imageSizeInBytes);
329 ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8);
330 if (width < 0 || height < 0)
331 return GraphicsContext3D::INVALID_VALUE;
332 unsigned int bytesPerComponent, componentsPerPixel;
333 if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent))
334 return GraphicsContext3D::INVALID_ENUM;
335 if (!width || !height) {
336 *imageSizeInBytes = 0;
337 if (paddingInBytes)
338 *paddingInBytes = 0;
339 return GraphicsContext3D::NO_ERROR;
340 }
341 Checked<uint32_t, RecordOverflow> checkedValue = bytesPerComponent * componentsPerPixel;
342 checkedValue *= width;
343 if (checkedValue.hasOverflowed())
344 return GraphicsContext3D::INVALID_VALUE;
345 unsigned int validRowSize = checkedValue.unsafeGet();
346 unsigned int padding = 0;
347 unsigned int residual = validRowSize % alignment;
348 if (residual) {
349 padding = alignment - residual;
350 checkedValue += padding;
351 }
352 // Last row needs no padding.
353 checkedValue *= (height - 1);
354 checkedValue += validRowSize;
355 if (checkedValue.hasOverflowed())
356 return GraphicsContext3D::INVALID_VALUE;
357 *imageSizeInBytes = checkedValue.unsafeGet();
358 if (paddingInBytes)
359 *paddingInBytes = padding;
360 return GraphicsContext3D::NO_ERROR;
361}
362
363GraphicsContext3D::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
364{
365 m_image = image;
366 m_imageHtmlDomSource = imageHtmlDomSource;
367 m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile);
368}
369
370bool GraphicsContext3D::packImageData(Image* image, const void* pixels, GC3Denum format, GC3Denum type, bool flipY, AlphaOp alphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data)
371{
372 if (!image || !pixels)
373 return false;
374
375 unsigned packedSize;
376 // Output data is tightly packed (alignment == 1).
377 if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, nullptr) != GraphicsContext3D::NO_ERROR)
378 return false;
379 data.resize(packedSize);
380
381 if (!packPixels(reinterpret_cast<const uint8_t*>(pixels), sourceFormat, width, height, sourceUnpackAlignment, format, type, alphaOp, data.data(), flipY))
382 return false;
383 if (ImageObserver* observer = image->imageObserver())
384 observer->didDraw(*image);
385 return true;
386}
387
388bool GraphicsContext3D::extractImageData(ImageData* imageData, GC3Denum format, GC3Denum type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data)
389{
390 if (!imageData)
391 return false;
392 int width = imageData->width();
393 int height = imageData->height();
394
395 unsigned int packedSize;
396 // Output data is tightly packed (alignment == 1).
397 if (computeImageSizeInBytes(format, type, width, height, 1, &packedSize, nullptr) != GraphicsContext3D::NO_ERROR)
398 return false;
399 data.resize(packedSize);
400
401 if (!packPixels(imageData->data()->data(), DataFormatRGBA8, width, height, 0, format, type, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing, data.data(), flipY))
402 return false;
403
404 return true;
405}
406
407bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int height, GC3Denum format, GC3Denum type, unsigned int unpackAlignment, bool flipY, bool premultiplyAlpha, const void* pixels, Vector<uint8_t>& data)
408{
409 // Assumes format, type, etc. have already been validated.
410 DataFormat sourceDataFormat = getDataFormat(format, type);
411
412 // Resize the output buffer.
413 unsigned int componentsPerPixel, bytesPerComponent;
414 if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent))
415 return false;
416 unsigned int bytesPerPixel = componentsPerPixel * bytesPerComponent;
417 data.resize(width * height * bytesPerPixel);
418
419 if (!packPixels(static_cast<const uint8_t*>(pixels), sourceDataFormat, width, height, unpackAlignment, format, type, (premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing), data.data(), flipY))
420 return false;
421
422 return true;
423}
424
425ALWAYS_INLINE unsigned TexelBytesForFormat(GraphicsContext3D::DataFormat format)
426{
427 switch (format) {
428 case GraphicsContext3D::DataFormatR8:
429 case GraphicsContext3D::DataFormatA8:
430 return 1;
431 case GraphicsContext3D::DataFormatRA8:
432 case GraphicsContext3D::DataFormatAR8:
433 case GraphicsContext3D::DataFormatRGBA5551:
434 case GraphicsContext3D::DataFormatRGBA4444:
435 case GraphicsContext3D::DataFormatRGB565:
436 case GraphicsContext3D::DataFormatA16F:
437 case GraphicsContext3D::DataFormatR16F:
438 return 2;
439 case GraphicsContext3D::DataFormatRGB8:
440 case GraphicsContext3D::DataFormatBGR8:
441 return 3;
442 case GraphicsContext3D::DataFormatRGBA8:
443 case GraphicsContext3D::DataFormatARGB8:
444 case GraphicsContext3D::DataFormatABGR8:
445 case GraphicsContext3D::DataFormatBGRA8:
446 case GraphicsContext3D::DataFormatR32F:
447 case GraphicsContext3D::DataFormatA32F:
448 case GraphicsContext3D::DataFormatRA16F:
449 return 4;
450 case GraphicsContext3D::DataFormatRGB16F:
451 return 6;
452 case GraphicsContext3D::DataFormatRA32F:
453 case GraphicsContext3D::DataFormatRGBA16F:
454 return 8;
455 case GraphicsContext3D::DataFormatRGB32F:
456 return 12;
457 case GraphicsContext3D::DataFormatRGBA32F:
458 return 16;
459 default:
460 return 0;
461 }
462}
463
464bool GraphicsContext3D::packPixels(const uint8_t* sourceData, DataFormat sourceDataFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, unsigned destinationFormat, unsigned destinationType, AlphaOp alphaOp, void* destinationData, bool flipY)
465{
466 int validSrc = width * TexelBytesForFormat(sourceDataFormat);
467 int remainder = sourceUnpackAlignment ? (validSrc % sourceUnpackAlignment) : 0;
468 int srcStride = remainder ? (validSrc + sourceUnpackAlignment - remainder) : validSrc;
469
470 // FIXME: Implement packing pixels to WebGL 2 formats
471 switch (destinationFormat) {
472 case GraphicsContext3D::RED:
473 case GraphicsContext3D::RED_INTEGER:
474 case GraphicsContext3D::RG:
475 case GraphicsContext3D::RG_INTEGER:
476 case GraphicsContext3D::RGB_INTEGER:
477 case GraphicsContext3D::RGBA_INTEGER:
478 case GraphicsContext3D::DEPTH_COMPONENT:
479 case GraphicsContext3D::DEPTH_STENCIL:
480 return false;
481 }
482 switch (destinationType) {
483 case GraphicsContext3D::BYTE:
484 case GraphicsContext3D::SHORT:
485 case GraphicsContext3D::INT:
486 case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV:
487 case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV:
488 case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV:
489 case GraphicsContext3D::UNSIGNED_INT_24_8:
490 return false;
491 }
492
493 DataFormat dstDataFormat = getDataFormat(destinationFormat, destinationType);
494 int dstStride = width * TexelBytesForFormat(dstDataFormat);
495 if (flipY) {
496 destinationData = static_cast<uint8_t*>(destinationData) + dstStride*(height - 1);
497 dstStride = -dstStride;
498 }
499 if (!hasAlpha(sourceDataFormat) || !hasColor(sourceDataFormat) || !hasColor(dstDataFormat))
500 alphaOp = AlphaDoNothing;
501
502 if (sourceDataFormat == dstDataFormat && alphaOp == AlphaDoNothing) {
503 const uint8_t* ptr = sourceData;
504 const uint8_t* ptrEnd = sourceData + srcStride * height;
505 unsigned rowSize = (dstStride > 0) ? dstStride: -dstStride;
506 uint8_t* dst = static_cast<uint8_t*>(destinationData);
507 while (ptr < ptrEnd) {
508 memcpy(dst, ptr, rowSize);
509 ptr += srcStride;
510 dst += dstStride;
511 }
512 return true;
513 }
514
515 FormatConverter converter(width, height, sourceData, destinationData, srcStride, dstStride);
516 converter.convert(sourceDataFormat, dstDataFormat, alphaOp);
517 if (!converter.success())
518 return false;
519 return true;
520}
521
522unsigned GraphicsContext3D::getClearBitsByAttachmentType(GC3Denum attachment)
523{
524 switch (attachment) {
525 case GraphicsContext3D::COLOR_ATTACHMENT0:
526 case Extensions3D::COLOR_ATTACHMENT1_EXT:
527 case Extensions3D::COLOR_ATTACHMENT2_EXT:
528 case Extensions3D::COLOR_ATTACHMENT3_EXT:
529 case Extensions3D::COLOR_ATTACHMENT4_EXT:
530 case Extensions3D::COLOR_ATTACHMENT5_EXT:
531 case Extensions3D::COLOR_ATTACHMENT6_EXT:
532 case Extensions3D::COLOR_ATTACHMENT7_EXT:
533 case Extensions3D::COLOR_ATTACHMENT8_EXT:
534 case Extensions3D::COLOR_ATTACHMENT9_EXT:
535 case Extensions3D::COLOR_ATTACHMENT10_EXT:
536 case Extensions3D::COLOR_ATTACHMENT11_EXT:
537 case Extensions3D::COLOR_ATTACHMENT12_EXT:
538 case Extensions3D::COLOR_ATTACHMENT13_EXT:
539 case Extensions3D::COLOR_ATTACHMENT14_EXT:
540 case Extensions3D::COLOR_ATTACHMENT15_EXT:
541 return GraphicsContext3D::COLOR_BUFFER_BIT;
542 case GraphicsContext3D::DEPTH_ATTACHMENT:
543 return GraphicsContext3D::DEPTH_BUFFER_BIT;
544 case GraphicsContext3D::STENCIL_ATTACHMENT:
545 return GraphicsContext3D::STENCIL_BUFFER_BIT;
546 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
547 return GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT;
548 default:
549 return 0;
550 }
551}
552
553unsigned GraphicsContext3D::getClearBitsByFormat(GC3Denum format)
554{
555 switch (format) {
556 case GraphicsContext3D::RGB:
557 case GraphicsContext3D::RGBA:
558 case GraphicsContext3D::LUMINANCE_ALPHA:
559 case GraphicsContext3D::LUMINANCE:
560 case GraphicsContext3D::ALPHA:
561 case GraphicsContext3D::R8:
562 case GraphicsContext3D::R8_SNORM:
563 case GraphicsContext3D::R16F:
564 case GraphicsContext3D::R32F:
565 case GraphicsContext3D::R8UI:
566 case GraphicsContext3D::R8I:
567 case GraphicsContext3D::R16UI:
568 case GraphicsContext3D::R16I:
569 case GraphicsContext3D::R32UI:
570 case GraphicsContext3D::R32I:
571 case GraphicsContext3D::RG8:
572 case GraphicsContext3D::RG8_SNORM:
573 case GraphicsContext3D::RG16F:
574 case GraphicsContext3D::RG32F:
575 case GraphicsContext3D::RG8UI:
576 case GraphicsContext3D::RG8I:
577 case GraphicsContext3D::RG16UI:
578 case GraphicsContext3D::RG16I:
579 case GraphicsContext3D::RG32UI:
580 case GraphicsContext3D::RG32I:
581 case GraphicsContext3D::RGB8:
582 case GraphicsContext3D::SRGB8:
583 case GraphicsContext3D::RGB565:
584 case GraphicsContext3D::RGB8_SNORM:
585 case GraphicsContext3D::R11F_G11F_B10F:
586 case GraphicsContext3D::RGB9_E5:
587 case GraphicsContext3D::RGB16F:
588 case GraphicsContext3D::RGB32F:
589 case GraphicsContext3D::RGB8UI:
590 case GraphicsContext3D::RGB8I:
591 case GraphicsContext3D::RGB16UI:
592 case GraphicsContext3D::RGB16I:
593 case GraphicsContext3D::RGB32UI:
594 case GraphicsContext3D::RGB32I:
595 case GraphicsContext3D::RGBA8:
596 case GraphicsContext3D::SRGB8_ALPHA8:
597 case GraphicsContext3D::RGBA8_SNORM:
598 case GraphicsContext3D::RGB5_A1:
599 case GraphicsContext3D::RGBA4:
600 case GraphicsContext3D::RGB10_A2:
601 case GraphicsContext3D::RGBA16F:
602 case GraphicsContext3D::RGBA32F:
603 case GraphicsContext3D::RGBA8UI:
604 case GraphicsContext3D::RGBA8I:
605 case GraphicsContext3D::RGB10_A2UI:
606 case GraphicsContext3D::RGBA16UI:
607 case GraphicsContext3D::RGBA16I:
608 case GraphicsContext3D::RGBA32I:
609 case GraphicsContext3D::RGBA32UI:
610 case Extensions3D::SRGB_EXT:
611 case Extensions3D::SRGB_ALPHA_EXT:
612 return GraphicsContext3D::COLOR_BUFFER_BIT;
613 case GraphicsContext3D::DEPTH_COMPONENT16:
614 case GraphicsContext3D::DEPTH_COMPONENT24:
615 case GraphicsContext3D::DEPTH_COMPONENT32F:
616 case GraphicsContext3D::DEPTH_COMPONENT:
617 return GraphicsContext3D::DEPTH_BUFFER_BIT;
618 case GraphicsContext3D::STENCIL_INDEX8:
619 return GraphicsContext3D::STENCIL_BUFFER_BIT;
620 case GraphicsContext3D::DEPTH_STENCIL:
621 case GraphicsContext3D::DEPTH24_STENCIL8:
622 case GraphicsContext3D::DEPTH32F_STENCIL8:
623 return GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT;
624 default:
625 return 0;
626 }
627}
628
629unsigned GraphicsContext3D::getChannelBitsByFormat(GC3Denum format)
630{
631 switch (format) {
632 case GraphicsContext3D::ALPHA:
633 return ChannelAlpha;
634 case GraphicsContext3D::LUMINANCE:
635 return ChannelRGB;
636 case GraphicsContext3D::LUMINANCE_ALPHA:
637 return ChannelRGBA;
638 case GraphicsContext3D::RGB:
639 case GraphicsContext3D::RGB565:
640 case Extensions3D::SRGB_EXT:
641 return ChannelRGB;
642 case GraphicsContext3D::RGBA:
643 case GraphicsContext3D::RGBA4:
644 case GraphicsContext3D::RGB5_A1:
645 case Extensions3D::SRGB_ALPHA_EXT:
646 return ChannelRGBA;
647 case GraphicsContext3D::DEPTH_COMPONENT16:
648 case GraphicsContext3D::DEPTH_COMPONENT:
649 return ChannelDepth;
650 case GraphicsContext3D::STENCIL_INDEX8:
651 return ChannelStencil;
652 case GraphicsContext3D::DEPTH_STENCIL:
653 return ChannelDepth | ChannelStencil;
654 default:
655 return 0;
656 }
657}
658
659#if !(PLATFORM(COCOA) && USE(OPENGL))
660void GraphicsContext3D::setContextVisibility(bool)
661{
662}
663#endif
664
665#if !PLATFORM(COCOA)
666void GraphicsContext3D::simulateContextChanged()
667{
668}
669#endif
670
671} // namespace WebCore
672
673#endif // ENABLE(GRAPHICS_CONTEXT_3D)
674