1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxUtils.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,294 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef GFX_UTILS_H 1.10 +#define GFX_UTILS_H 1.11 + 1.12 +#include "gfxTypes.h" 1.13 +#include "GraphicsFilter.h" 1.14 +#include "imgIContainer.h" 1.15 +#include "mozilla/gfx/2D.h" 1.16 +#include "mozilla/RefPtr.h" 1.17 + 1.18 +class gfxDrawable; 1.19 +class nsIntRegion; 1.20 +struct nsIntRect; 1.21 + 1.22 +namespace mozilla { 1.23 +namespace layers { 1.24 +class PlanarYCbCrData; 1.25 +} 1.26 +} 1.27 + 1.28 +class gfxUtils { 1.29 +public: 1.30 + typedef mozilla::gfx::DataSourceSurface DataSourceSurface; 1.31 + typedef mozilla::gfx::IntPoint IntPoint; 1.32 + typedef mozilla::gfx::Matrix Matrix; 1.33 + typedef mozilla::gfx::SourceSurface SourceSurface; 1.34 + typedef mozilla::gfx::SurfaceFormat SurfaceFormat; 1.35 + 1.36 + /* 1.37 + * Premultiply or Unpremultiply aSourceSurface, writing the result 1.38 + * to aDestSurface or back into aSourceSurface if aDestSurface is null. 1.39 + * 1.40 + * If aDestSurface is given, it must have identical format, dimensions, and 1.41 + * stride as the source. 1.42 + * 1.43 + * If the source is not gfxImageFormat::ARGB32, no operation is performed. If 1.44 + * aDestSurface is given, the data is copied over. 1.45 + */ 1.46 + static void PremultiplyImageSurface(gfxImageSurface *aSourceSurface, 1.47 + gfxImageSurface *aDestSurface = nullptr); 1.48 + static void UnpremultiplyImageSurface(gfxImageSurface *aSurface, 1.49 + gfxImageSurface *aDestSurface = nullptr); 1.50 + static mozilla::TemporaryRef<DataSourceSurface> UnpremultiplyDataSurface(DataSourceSurface* aSurface); 1.51 + 1.52 + static void ConvertBGRAtoRGBA(gfxImageSurface *aSourceSurface, 1.53 + gfxImageSurface *aDestSurface = nullptr); 1.54 + static void ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength); 1.55 + 1.56 + /** 1.57 + * Draw something drawable while working around limitations like bad support 1.58 + * for EXTEND_PAD, lack of source-clipping, or cairo / pixman bugs with 1.59 + * extreme user-space-to-image-space transforms. 1.60 + * 1.61 + * The input parameters here usually come from the output of our image 1.62 + * snapping algorithm in nsLayoutUtils.cpp. 1.63 + * This method is split from nsLayoutUtils::DrawPixelSnapped to allow for 1.64 + * adjusting the parameters. For example, certain images with transparent 1.65 + * margins only have a drawable subimage. For those images, imgFrame::Draw 1.66 + * will tweak the rects and transforms that it gets from the pixel snapping 1.67 + * algorithm before passing them on to this method. 1.68 + */ 1.69 + static void DrawPixelSnapped(gfxContext* aContext, 1.70 + gfxDrawable* aDrawable, 1.71 + const gfxMatrix& aUserSpaceToImageSpace, 1.72 + const gfxRect& aSubimage, 1.73 + const gfxRect& aSourceRect, 1.74 + const gfxRect& aImageRect, 1.75 + const gfxRect& aFill, 1.76 + const gfxImageFormat aFormat, 1.77 + GraphicsFilter aFilter, 1.78 + uint32_t aImageFlags = imgIContainer::FLAG_NONE); 1.79 + 1.80 + /** 1.81 + * Clip aContext to the region aRegion. 1.82 + */ 1.83 + static void ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion); 1.84 + 1.85 + /** 1.86 + * Clip aTarget to the region aRegion. 1.87 + */ 1.88 + static void ClipToRegion(mozilla::gfx::DrawTarget* aTarget, const nsIntRegion& aRegion); 1.89 + 1.90 + /** 1.91 + * Clip aContext to the region aRegion, snapping the rectangles. 1.92 + */ 1.93 + static void ClipToRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion); 1.94 + 1.95 + /** 1.96 + * Clip aTarget to the region aRegion, snapping the rectangles. 1.97 + */ 1.98 + static void ClipToRegionSnapped(mozilla::gfx::DrawTarget* aTarget, const nsIntRegion& aRegion); 1.99 + 1.100 + /** 1.101 + * Create a path consisting of rectangles in |aRegion|. 1.102 + */ 1.103 + static void PathFromRegion(gfxContext* aContext, const nsIntRegion& aRegion); 1.104 + 1.105 + /** 1.106 + * Create a path consisting of rectangles in |aRegion|, snapping the rectangles. 1.107 + */ 1.108 + static void PathFromRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion); 1.109 + 1.110 + /* 1.111 + * Convert image format to depth value 1.112 + */ 1.113 + static int ImageFormatToDepth(gfxImageFormat aFormat); 1.114 + 1.115 + /** 1.116 + * Return the transform matrix that maps aFrom to the rectangle defined by 1.117 + * aToTopLeft/aToTopRight/aToBottomRight. aFrom must be 1.118 + * nonempty and the destination rectangle must be axis-aligned. 1.119 + */ 1.120 + static gfxMatrix TransformRectToRect(const gfxRect& aFrom, 1.121 + const gfxPoint& aToTopLeft, 1.122 + const gfxPoint& aToTopRight, 1.123 + const gfxPoint& aToBottomRight); 1.124 + 1.125 + static Matrix TransformRectToRect(const gfxRect& aFrom, 1.126 + const IntPoint& aToTopLeft, 1.127 + const IntPoint& aToTopRight, 1.128 + const IntPoint& aToBottomRight); 1.129 + 1.130 + /** 1.131 + * If aIn can be represented exactly using an nsIntRect (i.e. 1.132 + * integer-aligned edges and coordinates in the int32_t range) then we 1.133 + * set aOut to that rectangle, otherwise return failure. 1.134 + */ 1.135 + static bool GfxRectToIntRect(const gfxRect& aIn, nsIntRect* aOut); 1.136 + 1.137 + /** 1.138 + * Return the smallest power of kScaleResolution (2) greater than or equal to 1.139 + * aVal. 1.140 + */ 1.141 + static gfxFloat ClampToScaleFactor(gfxFloat aVal); 1.142 + 1.143 + /** 1.144 + * Helper function for ConvertYCbCrToRGB that finds the 1.145 + * RGB buffer size and format for given YCbCrImage. 1.146 + * @param aSuggestedFormat will be set to gfxImageFormat::RGB24 1.147 + * if the desired format is not supported. 1.148 + * @param aSuggestedSize will be set to the picture size from aData 1.149 + * if either the suggested size was {0,0} 1.150 + * or simultaneous scaling and conversion is not supported. 1.151 + */ 1.152 + static void 1.153 + GetYCbCrToRGBDestFormatAndSize(const mozilla::layers::PlanarYCbCrData& aData, 1.154 + gfxImageFormat& aSuggestedFormat, 1.155 + gfxIntSize& aSuggestedSize); 1.156 + 1.157 + /** 1.158 + * Convert YCbCrImage into RGB aDestBuffer 1.159 + * Format and Size parameters must have 1.160 + * been passed to GetYCbCrToRGBDestFormatAndSize 1.161 + */ 1.162 + static void 1.163 + ConvertYCbCrToRGB(const mozilla::layers::PlanarYCbCrData& aData, 1.164 + const gfxImageFormat& aDestFormat, 1.165 + const gfxIntSize& aDestSize, 1.166 + unsigned char* aDestBuffer, 1.167 + int32_t aStride); 1.168 + 1.169 + /** 1.170 + * Creates a copy of aSurface, but having the SurfaceFormat aFormat. 1.171 + * 1.172 + * This function always creates a new surface. Do not call it if aSurface's 1.173 + * format is the same as aFormat. Such a non-conversion would just be an 1.174 + * unnecessary and wasteful copy (this function asserts to prevent that). 1.175 + * 1.176 + * This function is intended to be called by code that needs to access the 1.177 + * pixel data of the surface, but doesn't want to have lots of branches 1.178 + * to handle different pixel data formats (code which would become out of 1.179 + * date if and when new formats are added). Callers can use this function 1.180 + * to copy the surface to a specified format so that they only have to 1.181 + * handle pixel data in that one format. 1.182 + * 1.183 + * WARNING: There are format conversions that will not be supported by this 1.184 + * function. It very much depends on what the Moz2D backends support. If 1.185 + * the temporary B8G8R8A8 DrawTarget that this function creates has a 1.186 + * backend that supports DrawSurface() calls passing a surface with 1.187 + * aSurface's format it will work. Otherwise it will not. 1.188 + * 1.189 + * *** IMPORTANT PERF NOTE *** 1.190 + * 1.191 + * This function exists partly because format conversion is fraught with 1.192 + * non-obvious performance hazards, so we don't want Moz2D consumers to be 1.193 + * doing their own format conversion. Do not try to do so, or at least read 1.194 + * the comments in this functions implemtation. That said, the copy that 1.195 + * this function carries out has a cost and, although this function tries 1.196 + * to avoid perf hazards such as expensive uploads to/readbacks from the 1.197 + * GPU, it can't guarantee that it always successfully does so. Perf 1.198 + * critical code that can directly handle the common formats that it 1.199 + * encounters in a way that is cheaper than a copy-with-format-conversion 1.200 + * should consider doing so, and only use this function as a fallback to 1.201 + * handle other formats. 1.202 + * 1.203 + * XXXjwatt it would be nice if SourceSurface::GetDataSurface took a 1.204 + * SurfaceFormat argument (with a default argument meaning "use the 1.205 + * existing surface's format") and returned a DataSourceSurface in that 1.206 + * format. (There would then be an issue of callers maybe failing to 1.207 + * realize format conversion may involve expensive copying/uploading/ 1.208 + * readback.) 1.209 + */ 1.210 + static mozilla::TemporaryRef<DataSourceSurface> 1.211 + CopySurfaceToDataSourceSurfaceWithFormat(SourceSurface* aSurface, 1.212 + SurfaceFormat aFormat); 1.213 + 1.214 + static const uint8_t sUnpremultiplyTable[256*256]; 1.215 + static const uint8_t sPremultiplyTable[256*256]; 1.216 +#ifdef MOZ_DUMP_PAINTING 1.217 + /** 1.218 + * Writes a binary PNG file. 1.219 + */ 1.220 + static void WriteAsPNG(mozilla::gfx::DrawTarget* aDT, const char* aFile); 1.221 + 1.222 + /** 1.223 + * Write as a PNG encoded Data URL to stdout. 1.224 + */ 1.225 + static void DumpAsDataURL(mozilla::gfx::DrawTarget* aDT); 1.226 + 1.227 + /** 1.228 + * Copy a PNG encoded Data URL to the clipboard. 1.229 + */ 1.230 + static void CopyAsDataURL(mozilla::gfx::DrawTarget* aDT); 1.231 + 1.232 + static bool sDumpPaintList; 1.233 + static bool sDumpPainting; 1.234 + static bool sDumpPaintingToFile; 1.235 + static FILE* sDumpPaintFile; 1.236 + 1.237 + /** 1.238 + * Writes a binary PNG file. 1.239 + * Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads 1.240 + */ 1.241 + static void WriteAsPNG(mozilla::RefPtr<mozilla::gfx::SourceSurface> aSourceSurface, const char* aFile); 1.242 + 1.243 + /** 1.244 + * Write as a PNG encoded Data URL to stdout. 1.245 + * Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads 1.246 + */ 1.247 + static void DumpAsDataURL(mozilla::RefPtr<mozilla::gfx::SourceSurface> aSourceSurface); 1.248 + 1.249 + /** 1.250 + * Copy a PNG encoded Data URL to the clipboard. 1.251 + * Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads 1.252 + */ 1.253 + static void CopyAsDataURL(mozilla::RefPtr<mozilla::gfx::SourceSurface> aSourceSurface); 1.254 +#endif 1.255 +}; 1.256 + 1.257 +namespace mozilla { 1.258 +namespace gfx { 1.259 + 1.260 + 1.261 +/* These techniques are suggested by "Bit Twiddling Hacks" 1.262 + */ 1.263 + 1.264 +/** 1.265 + * Returns true if |aNumber| is a power of two 1.266 + * 0 is incorreclty considered a power of two 1.267 + */ 1.268 +static inline bool 1.269 +IsPowerOfTwo(int aNumber) 1.270 +{ 1.271 + return (aNumber & (aNumber - 1)) == 0; 1.272 +} 1.273 + 1.274 +/** 1.275 + * Returns the first integer greater than |aNumber| which is a power of two 1.276 + * Undefined for |aNumber| < 0 1.277 + */ 1.278 +static inline int 1.279 +NextPowerOfTwo(int aNumber) 1.280 +{ 1.281 +#if defined(__arm__) 1.282 + return 1 << (32 - __builtin_clz(aNumber - 1)); 1.283 +#else 1.284 + --aNumber; 1.285 + aNumber |= aNumber >> 1; 1.286 + aNumber |= aNumber >> 2; 1.287 + aNumber |= aNumber >> 4; 1.288 + aNumber |= aNumber >> 8; 1.289 + aNumber |= aNumber >> 16; 1.290 + return ++aNumber; 1.291 +#endif 1.292 +} 1.293 + 1.294 +} // namespace gfx 1.295 +} // namespace mozilla 1.296 + 1.297 +#endif