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