1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef WebGLImageConversion_h
6#define WebGLImageConversion_h
7
8#include "platform/PlatformExport.h"
9#include "platform/graphics/Image.h"
10#include "third_party/khronos/GLES2/gl2.h"
11#include "third_party/khronos/GLES2/gl2ext.h"
12#include "wtf/RefPtr.h"
13
14namespace blink {
15class Image;
16class IntSize;
17
18// Helper functions for texture uploading and pixel readback.
19class PLATFORM_EXPORT WebGLImageConversion {
20public:
21    // Attempt to enumerate all possible native image formats to
22    // reduce the amount of temporary allocations during texture
23    // uploading. This enum must be public because it is accessed
24    // by non-member functions.
25    enum DataFormat {
26        DataFormatRGBA8 = 0,
27        DataFormatRGBA16F,
28        DataFormatRGBA32F,
29        DataFormatRGB8,
30        DataFormatRGB16F,
31        DataFormatRGB32F,
32        DataFormatBGR8,
33        DataFormatBGRA8,
34        DataFormatARGB8,
35        DataFormatABGR8,
36        DataFormatRGBA5551,
37        DataFormatRGBA4444,
38        DataFormatRGB565,
39        DataFormatR8,
40        DataFormatR16F,
41        DataFormatR32F,
42        DataFormatRA8,
43        DataFormatRA16F,
44        DataFormatRA32F,
45        DataFormatAR8,
46        DataFormatA8,
47        DataFormatA16F,
48        DataFormatA32F,
49        DataFormatNumFormats
50    };
51
52    enum ChannelBits {
53        ChannelRed = 1,
54        ChannelGreen = 2,
55        ChannelBlue = 4,
56        ChannelAlpha = 8,
57        ChannelDepth = 16,
58        ChannelStencil = 32,
59        ChannelRGB = ChannelRed | ChannelGreen | ChannelBlue,
60        ChannelRGBA = ChannelRGB | ChannelAlpha,
61    };
62
63    // Possible alpha operations that may need to occur during
64    // pixel packing. FIXME: kAlphaDoUnmultiply is lossy and must
65    // be removed.
66    enum AlphaOp {
67        AlphaDoNothing = 0,
68        AlphaDoPremultiply = 1,
69        AlphaDoUnmultiply = 2
70    };
71
72    enum ImageHtmlDomSource {
73        HtmlDomImage = 0,
74        HtmlDomCanvas = 1,
75        HtmlDomVideo = 2,
76        HtmlDomNone = 3
77    };
78
79    class PLATFORM_EXPORT ImageExtractor {
80    public:
81        ImageExtractor(Image*, ImageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
82
83        ~ImageExtractor();
84
85        bool extractSucceeded() { return m_extractSucceeded; }
86        const void* imagePixelData() { return m_imagePixelData; }
87        unsigned imageWidth() { return m_imageWidth; }
88        unsigned imageHeight() { return m_imageHeight; }
89        DataFormat imageSourceFormat() { return m_imageSourceFormat; }
90        AlphaOp imageAlphaOp() { return m_alphaOp; }
91        unsigned imageSourceUnpackAlignment() { return m_imageSourceUnpackAlignment; }
92        ImageHtmlDomSource imageHtmlDomSource() { return m_imageHtmlDomSource; }
93    private:
94        // Extract the image and keeps track of its status, such as width, height, Source Alignment, format and AlphaOp etc.
95        // This needs to lock the resources or relevant data if needed and return true upon success
96        bool extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
97
98        RefPtr<NativeImageSkia> m_nativeImage;
99        RefPtr<NativeImageSkia> m_skiaImage;
100        Image* m_image;
101        ImageHtmlDomSource m_imageHtmlDomSource;
102        bool m_extractSucceeded;
103        const void* m_imagePixelData;
104        unsigned m_imageWidth;
105        unsigned m_imageHeight;
106        DataFormat m_imageSourceFormat;
107        AlphaOp m_alphaOp;
108        unsigned m_imageSourceUnpackAlignment;
109    };
110
111    // Computes the components per pixel and bytes per component
112    // for the given format and type combination. Returns false if
113    // either was an invalid enum.
114    static bool computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent);
115
116    // Computes the image size in bytes. If paddingInBytes is not null, padding
117    // is also calculated in return. Returns NO_ERROR if succeed, otherwise
118    // return the suggested GL error indicating the cause of the failure:
119    //   INVALID_VALUE if width/height is negative or overflow happens.
120    //   INVALID_ENUM if format/type is illegal.
121    static GLenum computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes);
122
123    // Check if the format is one of the formats from the ImageData or DOM elements.
124    // The formats from ImageData is always RGBA8.
125    // The formats from DOM elements vary with Graphics ports. It can only be RGBA8 or BGRA8.
126    static ALWAYS_INLINE bool srcFormatComeFromDOMElementOrImageData(DataFormat SrcFormat)
127    {
128        return SrcFormat == DataFormatBGRA8 || SrcFormat == DataFormatRGBA8;
129    }
130
131    static unsigned getClearBitsByFormat(GLenum);
132    static unsigned getChannelBitsByFormat(GLenum);
133
134    // The Following functions are implemented in GraphicsContext3DImagePacking.cpp
135
136    // Packs the contents of the given Image which is passed in |pixels| into the passed Vector
137    // according to the given format and type, and obeying the flipY and AlphaOp flags.
138    // Returns true upon success.
139    static bool packImageData(Image*, const void* pixels, GLenum format, GLenum type, bool flipY, AlphaOp, DataFormat sourceFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, Vector<uint8_t>& data);
140
141    // Extracts the contents of the given ImageData into the passed Vector,
142    // packing the pixel data according to the given format and type,
143    // and obeying the flipY and premultiplyAlpha flags. Returns true
144    // upon success.
145    static bool extractImageData(const uint8_t*, const IntSize&, GLenum format, GLenum type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data);
146
147    // Helper function which extracts the user-supplied texture
148    // data, applying the flipY and premultiplyAlpha parameters.
149    // If the data is not tightly packed according to the passed
150    // unpackAlignment, the output data will be tightly packed.
151    // Returns true if successful, false if any error occurred.
152    static bool extractTextureData(unsigned width, unsigned height, GLenum format, GLenum type, unsigned unpackAlignment, bool flipY, bool premultiplyAlpha, const void* pixels, Vector<uint8_t>& data);
153
154    // End GraphicsContext3DImagePacking.cpp functions
155
156private:
157    // Helper for packImageData/extractImageData/extractTextureData which implement packing of pixel
158    // data into the specified OpenGL destination format and type.
159    // A sourceUnpackAlignment of zero indicates that the source
160    // data is tightly packed. Non-zero values may take a slow path.
161    // Destination data will have no gaps between rows.
162    // Implemented in GraphicsContext3DImagePacking.cpp
163    static bool packPixels(const uint8_t* sourceData, DataFormat sourceDataFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, unsigned destinationFormat, unsigned destinationType, AlphaOp, void* destinationData, bool flipY);
164};
165
166} // namespace blink
167
168#endif // WebGLImageConversion_h
169