text: // Copyright 2014 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef WebGLImageConversion_h
  #define WebGLImageConversion_h
  
  #include "platform/PlatformExport.h"
  #include "platform/graphics/Image.h"
  #include "third_party/khronos/GLES2/gl2.h"
  #include "third_party/khronos/GLES2/gl2ext.h"
  #include "third_party/khronos/GLES3/gl3.h"
  #include "third_party/skia/include/core/SkBitmap.h"
  #include "wtf/RefPtr.h"
  
  namespace blink {
  class Image;
  class IntSize;
  
  // Helper functions for texture uploading and pixel readback.
  class PLATFORM_EXPORT WebGLImageConversion {
  public:
      // Attempt to enumerate all possible native image formats to
      // reduce the amount of temporary allocations during texture
      // uploading. This enum must be public because it is accessed
      // by non-member functions.
      // "_S" postfix indicates signed type.
      enum DataFormat {
          DataFormatRGBA8 = 0,
          DataFormatRGBA8_S,
          DataFormatRGBA16,
          DataFormatRGBA16_S,
          DataFormatRGBA32,
          DataFormatRGBA32_S,
          DataFormatRGBA16F,
          DataFormatRGBA32F,
          DataFormatRGBA2_10_10_10,
          DataFormatRGB8,
          DataFormatRGB8_S,
          DataFormatRGB16,
          DataFormatRGB16_S,
          DataFormatRGB32,
          DataFormatRGB32_S,
          DataFormatRGB16F,
          DataFormatRGB32F,
          DataFormatBGR8,
          DataFormatBGRA8,
          DataFormatARGB8,
          DataFormatABGR8,
          DataFormatRGBA5551,
          DataFormatRGBA4444,
          DataFormatRGB565,
          DataFormatRGB10F11F11F,
          DataFormatRGB5999,
          DataFormatRG8,
          DataFormatRG8_S,
          DataFormatRG16,
          DataFormatRG16_S,
          DataFormatRG32,
          DataFormatRG32_S,
          DataFormatRG16F,
          DataFormatRG32F,
          DataFormatR8,
          DataFormatR8_S,
          DataFormatR16,
          DataFormatR16_S,
          DataFormatR32,
          DataFormatR32_S,
          DataFormatR16F,
          DataFormatR32F,
          DataFormatRA8,
          DataFormatRA16F,
          DataFormatRA32F,
          DataFormatAR8,
          DataFormatA8,
          DataFormatA16F,
          DataFormatA32F,
          DataFormatD16,
          DataFormatD32,
          DataFormatD32F,
          DataFormatDS24_8,
          DataFormatNumFormats
      };
  
      enum ChannelBits {
          ChannelRed = 1,
          ChannelGreen = 2,
          ChannelBlue = 4,
          ChannelAlpha = 8,
          ChannelDepth = 16,
          ChannelStencil = 32,
          ChannelRG = ChannelRed | ChannelGreen,
          ChannelRGB = ChannelRed | ChannelGreen | ChannelBlue,
          ChannelRGBA = ChannelRGB | ChannelAlpha,
          ChannelDepthStencil = ChannelDepth | ChannelStencil,
      };
  
      // Possible alpha operations that may need to occur during
      // pixel packing. FIXME: kAlphaDoUnmultiply is lossy and must
      // be removed.
      enum AlphaOp {
          AlphaDoNothing = 0,
          AlphaDoPremultiply = 1,
          AlphaDoUnmultiply = 2
      };
  
      enum ImageHtmlDomSource {
          HtmlDomImage = 0,
          HtmlDomCanvas = 1,
          HtmlDomVideo = 2,
          HtmlDomNone = 3
      };
  
      class PLATFORM_EXPORT ImageExtractor {
      public:
          ImageExtractor(Image*, ImageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
  
          ~ImageExtractor();
  
          bool extractSucceeded() { return m_extractSucceeded; }
          const void* imagePixelData() { return m_imagePixelData; }
          unsigned imageWidth() { return m_imageWidth; }
          unsigned imageHeight() { return m_imageHeight; }
          DataFormat imageSourceFormat() { return m_imageSourceFormat; }
          AlphaOp imageAlphaOp() { return m_alphaOp; }
          unsigned imageSourceUnpackAlignment() { return m_imageSourceUnpackAlignment; }
          ImageHtmlDomSource imageHtmlDomSource() { return m_imageHtmlDomSource; }
      private:
          // Extract the image and keeps track of its status, such as width, height, Source Alignment, format and AlphaOp etc.
          // This needs to lock the resources or relevant data if needed and return true upon success
          bool extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
  
          SkBitmap m_bitmap;
          SkBitmap m_skiaBitmap;
          Image* m_image;
          ImageHtmlDomSource m_imageHtmlDomSource;
          bool m_extractSucceeded;
          const void* m_imagePixelData;
          unsigned m_imageWidth;
          unsigned m_imageHeight;
          DataFormat m_imageSourceFormat;
          AlphaOp m_alphaOp;
          unsigned m_imageSourceUnpackAlignment;
      };
  
      // Computes the components per pixel and bytes per component
      // for the given format and type combination. Returns false if
      // either was an invalid enum.
      static bool computeFormatAndTypeParameters(GLenum format, GLenum type, unsigned* componentsPerPixel, unsigned* bytesPerComponent);
  
      // Computes the image size in bytes. If paddingInBytes is not null, padding
      // is also calculated in return. Returns NO_ERROR if succeed, otherwise
      // return the suggested GL error indicating the cause of the failure:
      //   INVALID_VALUE if width/height is negative or overflow happens.
      //   INVALID_ENUM if format/type is illegal.
      static GLenum computeImageSizeInBytes(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, unsigned* imageSizeInBytes, unsigned* paddingInBytes);
  
      // Check if the format is one of the formats from the ImageData or DOM elements.
      // The formats from ImageData is always RGBA8.
      // The formats from DOM elements vary with Graphics ports. It can only be RGBA8 or BGRA8.
      static ALWAYS_INLINE bool srcFormatComeFromDOMElementOrImageData(DataFormat SrcFormat)
      {
          return SrcFormat == DataFormatBGRA8 || SrcFormat == DataFormatRGBA8;
      }
  
      // The input can be either format or internalformat.
      static unsigned getChannelBitsByFormat(GLenum);
  
      // The Following functions are implemented in GraphicsContext3DImagePacking.cpp
  
      // Packs the contents of the given Image which is passed in |pixels| into the passed Vector
      // according to the given format and type, and obeying the flipY and AlphaOp flags.
      // Returns true upon success.
      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);
  
      // Extracts the contents of the given ImageData into the passed Vector,
      // packing the pixel data according to the given format and type,
      // and obeying the flipY and premultiplyAlpha flags. Returns true
      // upon success.
      static bool extractImageData(const uint8_t*, const IntSize&, GLenum format, GLenum type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data);
  
      // Helper function which extracts the user-supplied texture
      // data, applying the flipY and premultiplyAlpha parameters.
      // If the data is not tightly packed according to the passed
      // unpackAlignment, the output data will be tightly packed.
      // Returns true if successful, false if any error occurred.
      static bool extractTextureData(unsigned width, unsigned height, GLenum format, GLenum type, unsigned unpackAlignment, bool flipY, bool premultiplyAlpha, const void* pixels, Vector<uint8_t>& data);
  
      // End GraphicsContext3DImagePacking.cpp functions
  
  private:
      // Helper for packImageData/extractImageData/extractTextureData which implement packing of pixel
      // data into the specified OpenGL destination format and type.
      // A sourceUnpackAlignment of zero indicates that the source
      // data is tightly packed. Non-zero values may take a slow path.
      // Destination data will have no gaps between rows.
      // Implemented in GraphicsContext3DImagePacking.cpp
      static bool packPixels(const uint8_t* sourceData, DataFormat sourceDataFormat, unsigned width, unsigned height, unsigned sourceUnpackAlignment, unsigned destinationFormat, unsigned destinationType, AlphaOp, void* destinationData, bool flipY);
  };
  
  } // namespace blink
  
  #endif // WebGLImageConversion_h
  