From 1121170477302e25ef2a020cf2092aa6b399b3ef Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Tue, 25 Mar 2014 12:00:30 +0000 Subject: [PATCH] implement readPixels and writePixels natively, w/o using the (deprecated) SkCanvas::Config8888 enum. Revert "Revert "hide Config8888 entirely". Broke a bunch of builds." This reverts commit 763277ba157fef0f651004bb98a189e9f1ac730b. Needs chrome to remove the READPIXELS guard from skia's .gyp Review URL: https://codereview.chromium.org/199733016 git-svn-id: http://skia.googlecode.com/svn/trunk@13931 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkCanvas.h | 8 ++ include/core/SkColorPriv.h | 140 +++++++++++++++++- include/core/SkDevice.h | 2 + src/core/SkBitmapDevice.cpp | 48 ++----- src/core/SkConfig8888.cpp | 333 +++++++++++-------------------------------- src/core/SkConfig8888.h | 82 +++-------- src/core/SkDevice.cpp | 10 -- src/gpu/GrContext.cpp | 111 +++++---------- src/gpu/SkGr.cpp | 21 ++- tests/DeferredCanvasTest.cpp | 27 +--- tests/WritePixelsTest.cpp | 213 +++++++++++++-------------- tools/sk_tool_utils.cpp | 31 ---- tools/sk_tool_utils.h | 5 - 13 files changed, 421 insertions(+), 610 deletions(-) diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index f5d4fe6..0d8fd46 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -20,6 +20,12 @@ //#define SK_SUPPORT_LEGACY_READPIXELSCONFIG +#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG + #ifndef SK_SUPPORT_LEGACY_CONFIG8888 + #define SK_SUPPORT_LEGACY_CONFIG8888 + #endif +#endif + // if not defined, we always assume ClipToLayer for saveLayer() //#define SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG @@ -231,6 +237,7 @@ public: */ const void* peekPixels(SkImageInfo* info, size_t* rowBytes); +#ifdef SK_SUPPORT_LEGACY_CONFIG8888 /** * This enum can be used with read/writePixels to perform a pixel ops to or * from an 8888 config other than Skia's native config (SkPMColor). There @@ -265,6 +272,7 @@ public: kRGBA_Premul_Config8888, kRGBA_Unpremul_Config8888 }; +#endif #ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG /** diff --git a/include/core/SkColorPriv.h b/include/core/SkColorPriv.h index 7a74c4a..9591f22 100644 --- a/include/core/SkColorPriv.h +++ b/include/core/SkColorPriv.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #ifndef SkColorPriv_DEFINED #define SkColorPriv_DEFINED @@ -18,6 +16,134 @@ #include "SkColor.h" #include "SkMath.h" +////////////////////////////////////////////////////////////////////////////// + +#define SkASSERT_IS_BYTE(x) SkASSERT(0 == ((x) & ~0xFF)) + +/* + * Skia's 32bit backend only supports 1 sizzle order at a time (compile-time). + * This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B. + * + * For easier compatibility with Skia's GPU backend, we further restrict these + * to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does + * not directly correspond to the same shift-order, since we have to take endianess + * into account. + * + * Here we enforce this constraint. + */ + +#ifdef SK_CPU_BENDIAN + #define SK_RGBA_R32_SHIFT 24 + #define SK_RGBA_G32_SHIFT 16 + #define SK_RGBA_B32_SHIFT 8 + #define SK_RGBA_A32_SHIFT 0 + + #define SK_BGRA_B32_SHIFT 24 + #define SK_BGRA_G32_SHIFT 16 + #define SK_BGRA_R32_SHIFT 8 + #define SK_BGRA_A32_SHIFT 0 +#else + #define SK_RGBA_R32_SHIFT 0 + #define SK_RGBA_G32_SHIFT 8 + #define SK_RGBA_B32_SHIFT 16 + #define SK_RGBA_A32_SHIFT 24 + + #define SK_BGRA_B32_SHIFT 0 + #define SK_BGRA_G32_SHIFT 8 + #define SK_BGRA_R32_SHIFT 16 + #define SK_BGRA_A32_SHIFT 24 +#endif + +#if defined(SK_PMCOLOR_IS_RGBA) && defined(SK_PMCOLOR_IS_BGRA) + #error "can't define PMCOLOR to be RGBA and BGRA" +#endif + +#define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA \ + (SK_A32_SHIFT == SK_RGBA_A32_SHIFT && \ + SK_R32_SHIFT == SK_RGBA_R32_SHIFT && \ + SK_G32_SHIFT == SK_RGBA_G32_SHIFT && \ + SK_B32_SHIFT == SK_RGBA_B32_SHIFT) + +#define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA \ + (SK_A32_SHIFT == SK_BGRA_A32_SHIFT && \ + SK_R32_SHIFT == SK_BGRA_R32_SHIFT && \ + SK_G32_SHIFT == SK_BGRA_G32_SHIFT && \ + SK_B32_SHIFT == SK_BGRA_B32_SHIFT) + + +#if defined(SK_PMCOLOR_IS_RGBA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA + #error "SK_PMCOLOR_IS_RGBA does not match SK_*32_SHIFT values" +#endif + +#if defined(SK_PMCOLOR_IS_BGRA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA + #error "SK_PMCOLOR_IS_BGRA does not match SK_*32_SHIFT values" +#endif + +#if !defined(SK_PMCOLOR_IS_RGBA) && !defined(SK_PMCOLOR_IS_RGBA) + // deduce which to define from the _SHIFT defines + + #if LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA + #define SK_PMCOLOR_IS_RGBA + #elif LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA + #define SK_PMCOLOR_IS_BGRA + #else + #error "need 32bit packing to be either RGBA or BGRA" + #endif +#endif + +// hide these now that we're done +#undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA +#undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA + +////////////////////////////////////////////////////////////////////////////// + +// Reverse the bytes coorsponding to RED and BLUE in a packed pixels. Note the +// pair of them are in the same 2 slots in both RGBA and BGRA, thus there is +// no need to pass in the colortype to this function. +static inline uint32_t SkSwizzle_RB(uint32_t c) { + static const uint32_t kRBMask = (0xFF << SK_R32_SHIFT) | (0xFF << SK_B32_SHIFT); + + unsigned c0 = (c >> SK_R32_SHIFT) & 0xFF; + unsigned c1 = (c >> SK_B32_SHIFT) & 0xFF; + return (c & ~kRBMask) | (c0 << SK_B32_SHIFT) | (c1 << SK_R32_SHIFT); +} + +static inline uint32_t SkPackARGB_as_RGBA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { + SkASSERT_IS_BYTE(a); + SkASSERT_IS_BYTE(r); + SkASSERT_IS_BYTE(g); + SkASSERT_IS_BYTE(b); + return (a << SK_RGBA_A32_SHIFT) | (r << SK_RGBA_R32_SHIFT) | + (g << SK_RGBA_G32_SHIFT) | (b << SK_RGBA_B32_SHIFT); +} + +static inline uint32_t SkPackARGB_as_BGRA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { + SkASSERT_IS_BYTE(a); + SkASSERT_IS_BYTE(r); + SkASSERT_IS_BYTE(g); + SkASSERT_IS_BYTE(b); + return (a << SK_BGRA_A32_SHIFT) | (r << SK_BGRA_R32_SHIFT) | + (g << SK_BGRA_G32_SHIFT) | (b << SK_BGRA_B32_SHIFT); +} + +static inline SkPMColor SkSwizzle_RGBA_to_PMColor(uint32_t c) { +#ifdef SK_PMCOLOR_IS_RGBA + return c; +#else + return SkSwizzle_RB(c); +#endif +} + +static inline SkPMColor SkSwizzle_BGRA_to_PMColor(uint32_t c) { +#ifdef SK_PMCOLOR_IS_BGRA + return c; +#else + return SkSwizzle_RB(c); +#endif +} + +////////////////////////////////////////////////////////////////////////////// + ///@{ /** See ITU-R Recommendation BT.709 at http://www.itu.int/rec/R-REC-BT.709/ .*/ #define SK_ITU_BT709_LUM_COEFF_R (0.2126f) @@ -239,6 +365,16 @@ static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT); } +static inline uint32_t SkPackPMColor_as_RGBA(SkPMColor c) { + return SkPackARGB_as_RGBA(SkGetPackedA32(c), SkGetPackedR32(c), + SkGetPackedG32(c), SkGetPackedB32(c)); +} + +static inline uint32_t SkPackPMColor_as_BGRA(SkPMColor c) { + return SkPackARGB_as_BGRA(SkGetPackedA32(c), SkGetPackedR32(c), + SkGetPackedG32(c), SkGetPackedB32(c)); +} + /** * Abstract 4-byte interpolation, implemented on top of SkPMColor * utility functions. Third parameter controls blending of the first two: diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index abd0a63..6b94dd6 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -363,9 +363,11 @@ protected: const SkImageFilter::Context& ctx, SkBitmap* result, SkIPoint* offset) = 0; +#ifdef SK_SUPPORT_LEGACY_CONFIG8888 // This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if // either is identical to kNative_Premul_Config8888. Otherwise, -1. static const SkCanvas::Config8888 kPMColorAlias; +#endif protected: // default impl returns NULL diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index f0f4df4..d968cb8 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -221,47 +221,27 @@ static void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB, } } -static bool info2config8888(const SkImageInfo& info, SkCanvas::Config8888* config) { - bool pre; - switch (info.alphaType()) { - case kPremul_SkAlphaType: - case kOpaque_SkAlphaType: - pre = true; - break; - case kUnpremul_SkAlphaType: - pre = false; - break; - default: - return false; - } - switch (info.colorType()) { - case kRGBA_8888_SkColorType: - *config = pre ? SkCanvas::kRGBA_Premul_Config8888 : SkCanvas::kRGBA_Unpremul_Config8888; - return true; - case kBGRA_8888_SkColorType: - *config = pre ? SkCanvas::kBGRA_Premul_Config8888 : SkCanvas::kBGRA_Unpremul_Config8888; - return true; - default: - return false; - } -} - -// TODO: make this guy real, and not rely on legacy config8888 utility #include "SkConfig8888.h" + static bool copy_pixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes) { if (srcInfo.dimensions() != dstInfo.dimensions()) { return false; } if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) { - SkCanvas::Config8888 srcConfig, dstConfig; - if (!info2config8888(srcInfo, &srcConfig) || !info2config8888(dstInfo, &dstConfig)) { - return false; - } - SkConvertConfig8888Pixels((uint32_t*)dstPixels, dstRowBytes, dstConfig, - (const uint32_t*)srcPixels, srcRowBytes, srcConfig, - srcInfo.width(), srcInfo.height()); - return true; + SkDstPixelInfo dstPI; + dstPI.fColorType = dstInfo.colorType(); + dstPI.fAlphaType = dstInfo.alphaType(); + dstPI.fPixels = dstPixels; + dstPI.fRowBytes = dstRowBytes; + + SkSrcPixelInfo srcPI; + srcPI.fColorType = srcInfo.colorType(); + srcPI.fAlphaType = srcInfo.alphaType(); + srcPI.fPixels = srcPixels; + srcPI.fRowBytes = srcRowBytes; + + return srcPI.convertPixelsTo(&dstPI, srcInfo.width(), srcInfo.height()); } if (srcInfo.colorType() == dstInfo.colorType()) { switch (srcInfo.colorType()) { diff --git a/src/core/SkConfig8888.cpp b/src/core/SkConfig8888.cpp index dd5cbc4..189309d 100644 --- a/src/core/SkConfig8888.cpp +++ b/src/core/SkConfig8888.cpp @@ -1,280 +1,117 @@ #include "SkConfig8888.h" +#include "SkColorPriv.h" #include "SkMathPriv.h" #include "SkUnPreMultiply.h" -namespace { +enum AlphaVerb { + kNothing_AlphaVerb, + kPremul_AlphaVerb, + kUnpremul_AlphaVerb, +}; -template -inline uint32_t pack_config8888(uint32_t a, uint32_t r, - uint32_t g, uint32_t b) { -#ifdef SK_CPU_LENDIAN - return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) | - (g << (G_IDX * 8)) | (b << (B_IDX * 8)); -#else - return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) | - (g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8)); -#endif -} - -template -inline void unpack_config8888(uint32_t color, - uint32_t* a, uint32_t* r, - uint32_t* g, uint32_t* b) { -#ifdef SK_CPU_LENDIAN - *a = (color >> (A_IDX * 8)) & 0xff; - *r = (color >> (R_IDX * 8)) & 0xff; - *g = (color >> (G_IDX * 8)) & 0xff; - *b = (color >> (B_IDX * 8)) & 0xff; -#else - *a = (color >> ((3 - A_IDX) * 8)) & 0xff; - *r = (color >> ((3 - R_IDX) * 8)) & 0xff; - *g = (color >> ((3 - G_IDX) * 8)) & 0xff; - *b = (color >> ((3 - B_IDX) * 8)) & 0xff; -#endif -} - -#ifdef SK_CPU_LENDIAN - static const int SK_NATIVE_A_IDX = SK_A32_SHIFT / 8; - static const int SK_NATIVE_R_IDX = SK_R32_SHIFT / 8; - static const int SK_NATIVE_G_IDX = SK_G32_SHIFT / 8; - static const int SK_NATIVE_B_IDX = SK_B32_SHIFT / 8; -#else - static const int SK_NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8); - static const int SK_NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8); - static const int SK_NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8); - static const int SK_NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8); -#endif - -/** - * convert_pixel -inline uint32_t convert_pixel(uint32_t pixel) { - uint32_t a, r, g, b; - unpack_config8888(pixel, &a, &r, &g, &b); - if (IN_PM && !OUT_PM) { - // Using SkUnPreMultiply::ApplyScale is faster than (value * 0xff) / a. - if (a) { - SkUnPreMultiply::Scale scale = SkUnPreMultiply::GetScale(a); - r = SkUnPreMultiply::ApplyScale(scale, r); - g = SkUnPreMultiply::ApplyScale(scale, g); - b = SkUnPreMultiply::ApplyScale(scale, b); - } else { - return 0; - } - } else if (!IN_PM && OUT_PM) { - // This matches SkUnPreMultiply conversion which we are replacing. - r = SkMulDiv255Round(r, a); - g = SkMulDiv255Round(g, a); - b = SkMulDiv255Round(b, a); +template uint32_t convert32(uint32_t c) { + if (doSwapRB) { + c = SkSwizzle_RB(c); } - return pack_config8888(a, r, g, b); -} -template -inline uint32_t convert_pixel(uint32_t pixel) { - switch(IN_CFG) { - case SkCanvas::kNative_Premul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kNative_Unpremul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kBGRA_Premul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kBGRA_Unpremul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kRGBA_Premul_Config8888: - return convert_pixel(pixel); + // Lucky for us, in both RGBA and BGRA, the alpha component is always in the same place, so + // we can perform premul or unpremul the same way without knowing the swizzles for RGB. + switch (doAlpha) { + case kNothing_AlphaVerb: + // no change break; - case SkCanvas::kRGBA_Unpremul_Config8888: - return convert_pixel(pixel); + case kPremul_AlphaVerb: + c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), + SkGetPackedG32(c), SkGetPackedB32(c)); break; - default: - SkDEBUGFAIL("Unexpected config8888"); - return 0; + case kUnpremul_AlphaVerb: + c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c); break; } + return c; } -template -inline uint32_t convert_pixel(uint32_t pixel) { - switch(OUT_CFG) { - case SkCanvas::kNative_Premul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kNative_Unpremul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kBGRA_Premul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kBGRA_Unpremul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kRGBA_Premul_Config8888: - return convert_pixel(pixel); - break; - case SkCanvas::kRGBA_Unpremul_Config8888: - return convert_pixel(pixel); - break; - default: - SkDEBUGFAIL("Unexpected config8888"); - return 0; - break; +template +void convert32_row(uint32_t* dst, const uint32_t* src, int count) { + // This has to be correct if src == dst (but not partial overlap) + for (int i = 0; i < count; ++i) { + dst[i] = convert32(src[i]); } } -/** - * SkConvertConfig8888Pixels has 6 * 6 possible combinations of src and dst - * configs. Each is implemented as an instantiation templated function. Two - * levels of switch statements are used to select the correct instantiation, one - * for the src config and one for the dst config. - */ +static bool is_32bit_colortype(SkColorType ct) { + return kRGBA_8888_SkColorType == ct || kBGRA_8888_SkColorType == ct; +} -template -inline void convert_config8888(uint32_t* dstPixels, - size_t dstRowBytes, - const uint32_t* srcPixels, - size_t srcRowBytes, - int width, - int height) { - intptr_t dstPix = reinterpret_cast(dstPixels); - intptr_t srcPix = reinterpret_cast(srcPixels); +static AlphaVerb compute_AlphaVerb(SkAlphaType src, SkAlphaType dst) { + SkASSERT(kIgnore_SkAlphaType != src); + SkASSERT(kIgnore_SkAlphaType != dst); - for (int y = 0; y < height; ++y) { - srcPixels = reinterpret_cast(srcPix); - dstPixels = reinterpret_cast(dstPix); - for (int x = 0; x < width; ++x) { - dstPixels[x] = convert_pixel(srcPixels[x]); - } - dstPix += dstRowBytes; - srcPix += srcRowBytes; + if (kOpaque_SkAlphaType == src || kOpaque_SkAlphaType == dst || src == dst) { + return kNothing_AlphaVerb; } -} - -template -inline void convert_config8888(uint32_t* dstPixels, - size_t dstRowBytes, - SkCanvas::Config8888 dstConfig, - const uint32_t* srcPixels, - size_t srcRowBytes, - int width, - int height) { - switch(dstConfig) { - case SkCanvas::kNative_Premul_Config8888: - convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kNative_Unpremul_Config8888: - convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kBGRA_Premul_Config8888: - convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kBGRA_Unpremul_Config8888: - convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kRGBA_Premul_Config8888: - convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kRGBA_Unpremul_Config8888: - convert_config8888(dstPixels, dstRowBytes, srcPixels, srcRowBytes, width, height); - break; - default: - SkDEBUGFAIL("Unexpected config8888"); - break; + if (kPremul_SkAlphaType == dst) { + SkASSERT(kUnpremul_SkAlphaType == src); + return kPremul_AlphaVerb; + } else { + SkASSERT(kPremul_SkAlphaType == src); + SkASSERT(kUnpremul_SkAlphaType == dst); + return kUnpremul_AlphaVerb; } } +static void memcpy32_row(uint32_t* dst, const uint32_t* src, int count) { + memcpy(dst, src, count * 4); } -void SkConvertConfig8888Pixels(uint32_t* dstPixels, - size_t dstRowBytes, - SkCanvas::Config8888 dstConfig, - const uint32_t* srcPixels, - size_t srcRowBytes, - SkCanvas::Config8888 srcConfig, - int width, - int height) { - if (srcConfig == dstConfig) { - if (srcPixels == dstPixels) { - return; - } - if (dstRowBytes == srcRowBytes && - 4U * width == srcRowBytes) { - memcpy(dstPixels, srcPixels, srcRowBytes * height); - return; - } else { - intptr_t srcPix = reinterpret_cast(srcPixels); - intptr_t dstPix = reinterpret_cast(dstPixels); - for (int y = 0; y < height; ++y) { - srcPixels = reinterpret_cast(srcPix); - dstPixels = reinterpret_cast(dstPix); - memcpy(dstPixels, srcPixels, 4 * width); - srcPix += srcRowBytes; - dstPix += dstRowBytes; - } - return; - } +bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const { + if (width <= 0 || height <= 0) { + return false; } - switch(srcConfig) { - case SkCanvas::kNative_Premul_Config8888: - convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kNative_Unpremul_Config8888: - convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kBGRA_Premul_Config8888: - convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kBGRA_Unpremul_Config8888: - convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); - break; - case SkCanvas::kRGBA_Premul_Config8888: - convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); + + if (!is_32bit_colortype(fColorType) || !is_32bit_colortype(dst->fColorType)) { + return false; + } + + void (*proc)(uint32_t* dst, const uint32_t* src, int count); + AlphaVerb doAlpha = compute_AlphaVerb(fAlphaType, dst->fAlphaType); + bool doSwapRB = fColorType != dst->fColorType; + + switch (doAlpha) { + case kNothing_AlphaVerb: + if (doSwapRB) { + proc = convert32_row; + } else { + if (fPixels == dst->fPixels) { + return true; + } + proc = memcpy32_row; + } break; - case SkCanvas::kRGBA_Unpremul_Config8888: - convert_config8888(dstPixels, dstRowBytes, dstConfig, srcPixels, srcRowBytes, width, height); + case kPremul_AlphaVerb: + if (doSwapRB) { + proc = convert32_row; + } else { + proc = convert32_row; + } break; - default: - SkDEBUGFAIL("Unexpected config8888"); + case kUnpremul_AlphaVerb: + if (doSwapRB) { + proc = convert32_row; + } else { + proc = convert32_row; + } break; } -} -uint32_t SkPackConfig8888(SkCanvas::Config8888 config, - uint32_t a, - uint32_t r, - uint32_t g, - uint32_t b) { - switch (config) { - case SkCanvas::kNative_Premul_Config8888: - case SkCanvas::kNative_Unpremul_Config8888: - return pack_config8888(a, r, g, b); - case SkCanvas::kBGRA_Premul_Config8888: - case SkCanvas::kBGRA_Unpremul_Config8888: - return pack_config8888<3, 2, 1, 0>(a, r, g, b); - case SkCanvas::kRGBA_Premul_Config8888: - case SkCanvas::kRGBA_Unpremul_Config8888: - return pack_config8888<3, 0, 1, 2>(a, r, g, b); - default: - SkDEBUGFAIL("Unexpected config8888"); - return 0; + uint32_t* dstP = static_cast(dst->fPixels); + const uint32_t* srcP = static_cast(fPixels); + size_t srcInc = fRowBytes >> 2; + size_t dstInc = dst->fRowBytes >> 2; + for (int y = 0; y < height; ++y) { + proc(dstP, srcP, width); + dstP += dstInc; + srcP += srcInc; } + return true; } diff --git a/src/core/SkConfig8888.h b/src/core/SkConfig8888.h index 041773e..97a3433 100644 --- a/src/core/SkConfig8888.h +++ b/src/core/SkConfig8888.h @@ -5,75 +5,27 @@ * found in the LICENSE file. */ -#ifndef SkConfig8888_DEFINED -#define SkConfig8888_DEFINED +#ifndef SkPixelInfo_DEFINED +#define SkPixelInfo_DEFINED -#include "SkCanvas.h" -#include "SkColorPriv.h" +#include "SkImageInfo.h" -/** - * Converts pixels from one Config8888 to another Config8888 - */ -void SkConvertConfig8888Pixels(uint32_t* dstPixels, - size_t dstRowBytes, - SkCanvas::Config8888 dstConfig, - const uint32_t* srcPixels, - size_t srcRowBytes, - SkCanvas::Config8888 srcConfig, - int width, - int height); - -/** - * Packs a, r, g, b, values into byte order specified by config. - */ -uint32_t SkPackConfig8888(SkCanvas::Config8888 config, - uint32_t a, - uint32_t r, - uint32_t g, - uint32_t b); - -/////////////////////////////////////////////////////////////////////////////// -// Implementation - -namespace { +struct SkPixelInfo { + SkColorType fColorType; + SkAlphaType fAlphaType; + size_t fRowBytes; +}; -/** - Copies all pixels from a bitmap to a dst ptr with a given rowBytes and - Config8888. The bitmap must have kARGB_8888_Config. - */ - -static inline void SkCopyBitmapToConfig8888(uint32_t* dstPixels, - size_t dstRowBytes, - SkCanvas::Config8888 dstConfig8888, - const SkBitmap& srcBmp) { - SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config()); - SkAutoLockPixels alp(srcBmp); - int w = srcBmp.width(); - int h = srcBmp.height(); - size_t srcRowBytes = srcBmp.rowBytes(); - const uint32_t* srcPixels = reinterpret_cast(srcBmp.getPixels()); - - SkConvertConfig8888Pixels(dstPixels, dstRowBytes, dstConfig8888, srcPixels, srcRowBytes, SkCanvas::kNative_Premul_Config8888, w, h); -} - -/** - Copies over all pixels in a bitmap from a src ptr with a given rowBytes and - Config8888. The bitmap must have pixels and be kARGB_8888_Config. - */ -static inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp, - const uint32_t* srcPixels, - size_t srcRowBytes, - SkCanvas::Config8888 srcConfig8888) { - SkASSERT(SkBitmap::kARGB_8888_Config == dstBmp.config()); - SkAutoLockPixels alp(dstBmp); - int w = dstBmp.width(); - int h = dstBmp.height(); - size_t dstRowBytes = dstBmp.rowBytes(); - uint32_t* dstPixels = reinterpret_cast(dstBmp.getPixels()); +struct SkDstPixelInfo : SkPixelInfo { + void* fPixels; +}; - SkConvertConfig8888Pixels(dstPixels, dstRowBytes, SkCanvas::kNative_Premul_Config8888, srcPixels, srcRowBytes, srcConfig8888, w, h); -} +struct SkSrcPixelInfo : SkPixelInfo { + const void* fPixels; -} + // Guaranteed to work even if src.fPixels and dst.fPixels are the same + // (but not if they overlap partially) + bool convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const; +}; #endif diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index ac46755..4c75a36 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -8,16 +8,6 @@ #include "SkDevice.h" #include "SkMetaData.h" -#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) - const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kBGRA_Premul_Config8888; -#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) - const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = SkCanvas::kRGBA_Premul_Config8888; -#else - const SkCanvas::Config8888 SkBaseDevice::kPMColorAlias = (SkCanvas::Config8888) -1; -#endif - -/////////////////////////////////////////////////////////////////////////////// - SkBaseDevice::SkBaseDevice() : fLeakyProperties(SkDeviceProperties::MakeDefault()) #ifdef SK_DEBUG diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index c016d06..9a277b0 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -25,6 +25,7 @@ #include "GrSoftwarePathRenderer.h" #include "GrStencilBuffer.h" #include "GrTextStrike.h" +#include "SkGr.h" #include "SkRTConf.h" #include "SkRRect.h" #include "SkStrokeRec.h" @@ -1259,54 +1260,15 @@ bool GrContext::readTexturePixels(GrTexture* texture, #include "SkConfig8888.h" -namespace { -/** - * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel - * formats are representable as Config8888 and so the function returns false - * if the GrPixelConfig has no equivalent Config8888. - */ -bool grconfig_to_config8888(GrPixelConfig config, - bool unpremul, - SkCanvas::Config8888* config8888) { - switch (config) { - case kRGBA_8888_GrPixelConfig: - if (unpremul) { - *config8888 = SkCanvas::kRGBA_Unpremul_Config8888; - } else { - *config8888 = SkCanvas::kRGBA_Premul_Config8888; - } - return true; - case kBGRA_8888_GrPixelConfig: - if (unpremul) { - *config8888 = SkCanvas::kBGRA_Unpremul_Config8888; - } else { - *config8888 = SkCanvas::kBGRA_Premul_Config8888; - } - return true; - default: - return false; - } -} - -// It returns a configuration with where the byte position of the R & B components are swapped in -// relation to the input config. This should only be called with the result of -// grconfig_to_config8888 as it will fail for other configs. -SkCanvas::Config8888 swap_config8888_red_and_blue(SkCanvas::Config8888 config8888) { - switch (config8888) { - case SkCanvas::kBGRA_Premul_Config8888: - return SkCanvas::kRGBA_Premul_Config8888; - case SkCanvas::kBGRA_Unpremul_Config8888: - return SkCanvas::kRGBA_Unpremul_Config8888; - case SkCanvas::kRGBA_Premul_Config8888: - return SkCanvas::kBGRA_Premul_Config8888; - case SkCanvas::kRGBA_Unpremul_Config8888: - return SkCanvas::kBGRA_Unpremul_Config8888; - default: - GrCrash("Unexpected input"); - return SkCanvas::kBGRA_Unpremul_Config8888;; +// toggles between RGBA and BGRA +static SkColorType toggle_colortype32(SkColorType ct) { + if (kRGBA_8888_SkColorType == ct) { + return kBGRA_8888_SkColorType; + } else { + SkASSERT(kBGRA_8888_SkColorType == ct); + return kRGBA_8888_SkColorType; } } -} bool GrContext::readRenderTargetPixels(GrRenderTarget* target, int left, int top, int width, int height, @@ -1432,22 +1394,21 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target, } // Perform any conversions we weren't able to perform using a scratch texture. if (unpremul || swapRAndB) { - // These are initialized to suppress a warning - SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888; - SkCanvas::Config8888 dstC8888 = SkCanvas::kNative_Premul_Config8888; + SkDstPixelInfo dstPI; + if (!GrPixelConfig2ColorType(dstConfig, &dstPI.fColorType)) { + return false; + } + dstPI.fAlphaType = kUnpremul_SkAlphaType; + dstPI.fPixels = buffer; + dstPI.fRowBytes = rowBytes; - SkDEBUGCODE(bool c8888IsValid =) grconfig_to_config8888(dstConfig, false, &srcC8888); - grconfig_to_config8888(dstConfig, unpremul, &dstC8888); + SkSrcPixelInfo srcPI; + srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : dstPI.fColorType; + srcPI.fAlphaType = kPremul_SkAlphaType; + srcPI.fPixels = buffer; + srcPI.fRowBytes = rowBytes; - if (swapRAndB) { - SkASSERT(c8888IsValid); // we should only do r/b swap on 8888 configs - srcC8888 = swap_config8888_red_and_blue(srcC8888); - } - SkASSERT(c8888IsValid); - uint32_t* b32 = reinterpret_cast(buffer); - SkConvertConfig8888Pixels(b32, rowBytes, dstC8888, - b32, rowBytes, srcC8888, - width, height); + return srcPI.convertPixelsTo(&dstPI, width, height); } return true; } @@ -1567,18 +1528,24 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* target, effect.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix)); // handle the unpremul step on the CPU if we couldn't create an effect to do it. if (NULL == effect) { - SkCanvas::Config8888 srcConfig8888, dstConfig8888; - SkDEBUGCODE(bool success = ) - grconfig_to_config8888(srcConfig, true, &srcConfig8888); - SkASSERT(success); - SkDEBUGCODE(success = ) - grconfig_to_config8888(srcConfig, false, &dstConfig8888); - SkASSERT(success); - const uint32_t* src = reinterpret_cast(buffer); - tmpPixels.reset(width * height); - SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888, - src, rowBytes, srcConfig8888, - width, height); + SkSrcPixelInfo srcPI; + if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) { + return false; + } + srcPI.fAlphaType = kUnpremul_SkAlphaType; + srcPI.fPixels = buffer; + srcPI.fRowBytes = rowBytes; + + SkDstPixelInfo dstPI; + dstPI.fColorType = srcPI.fColorType; + dstPI.fAlphaType = kPremul_SkAlphaType; + dstPI.fPixels = tmpPixels.get(); + dstPI.fRowBytes = 4 * width; + + if (!srcPI.convertPixelsTo(&dstPI, width, height)) { + return false; + } + buffer = tmpPixels.get(); rowBytes = 4 * width; } diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index 94e4c8c..db46b86 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -34,11 +34,22 @@ static void build_compressed_data(void* buffer, const SkBitmap& bitmap) { SkColorTable* ctable = bitmap.getColorTable(); char* dst = (char*)buffer; - uint32_t* colorTableDst = reinterpret_cast(dst); - const uint32_t* colorTableSrc = reinterpret_cast(ctable->lockColors()); - SkConvertConfig8888Pixels(colorTableDst, 0, SkCanvas::kRGBA_Premul_Config8888, - colorTableSrc, 0, SkCanvas::kNative_Premul_Config8888, - ctable->count(), 1); + const int count = ctable->count(); + + SkDstPixelInfo dstPI; + dstPI.fColorType = kRGBA_8888_SkColorType; + dstPI.fAlphaType = kPremul_SkAlphaType; + dstPI.fPixels = buffer; + dstPI.fRowBytes = count * sizeof(SkPMColor); + + SkSrcPixelInfo srcPI; + srcPI.fColorType = kPMColor_SkColorType; + srcPI.fAlphaType = kPremul_SkAlphaType; + srcPI.fPixels = ctable->lockColors(); + srcPI.fRowBytes = count * sizeof(SkPMColor); + + srcPI.convertPixelsTo(&dstPI, count, 1); + ctable->unlockColors(); // always skip a full 256 number of entries, even if we memcpy'd fewer diff --git a/tests/DeferredCanvasTest.cpp b/tests/DeferredCanvasTest.cpp index aa360be..0af0c51 100644 --- a/tests/DeferredCanvasTest.cpp +++ b/tests/DeferredCanvasTest.cpp @@ -26,21 +26,6 @@ class GrContextFactory; static const int gWidth = 2; static const int gHeight = 2; -static void callWritePixels(SkCanvas* canvas, const SkBitmap& src, int x, int y, - SkCanvas::Config8888 config) { - SkBitmap bm(src); - bm.lockPixels(); - - SkImageInfo info = bm.info(); - sk_tool_utils::config8888_to_imagetypes(config, &info.fColorType, &info.fAlphaType); - - if (src.isOpaque()) { - info.fAlphaType = kOpaque_SkAlphaType; - } - - canvas->writePixels(info, bm.getPixels(), bm.rowBytes(), x, y); -} - static void create(SkBitmap* bm, SkColor color) { bm->allocN32Pixels(gWidth, gHeight); bm->eraseColor(color); @@ -122,7 +107,7 @@ static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter) SkAutoTUnref canvas(SkDeferredCanvas::Create(surface.get())); SkBitmap srcBitmap; - srcBitmap.allocN32Pixels(10, 10); + srcBitmap.allocPixels(SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType)); srcBitmap.eraseColor(SK_ColorGREEN); // Tests below depend on this bitmap being recognized as opaque @@ -174,7 +159,7 @@ static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter) REPORTER_ASSERT(reporter, 0 == surface->fRetainCount); surface->clearCounts(); - callWritePixels(canvas, srcBitmap, 0, 0, SkCanvas::kRGBA_Unpremul_Config8888); + canvas->writePixels(srcBitmap, 0, 0); REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); REPORTER_ASSERT(reporter, 0 == surface->fRetainCount); @@ -191,7 +176,7 @@ static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter) REPORTER_ASSERT(reporter, 0 == surface->fRetainCount); surface->clearCounts(); - callWritePixels(canvas, srcBitmap, 5, 0, SkCanvas::kRGBA_Unpremul_Config8888); + canvas->writePixels(srcBitmap, 5, 0); REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); REPORTER_ASSERT(reporter, 1 == surface->fRetainCount); @@ -213,7 +198,7 @@ static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter) REPORTER_ASSERT(reporter, 0 == surface->fRetainCount); surface->clearCounts(); - callWritePixels(canvas, srcBitmap, 0, 0, SkCanvas::kRGBA_Unpremul_Config8888); + canvas->writePixels(srcBitmap, 0, 0); REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); REPORTER_ASSERT(reporter, 0 == surface->fRetainCount); @@ -235,7 +220,7 @@ static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter) REPORTER_ASSERT(reporter, 0 == surface->fRetainCount); surface->clearCounts(); - callWritePixels(canvas, srcBitmap, 5, 0, SkCanvas::kRGBA_Unpremul_Config8888); + canvas->writePixels(srcBitmap, 5, 0); REPORTER_ASSERT(reporter, 1 == surface->fDiscardCount); // because of the clear REPORTER_ASSERT(reporter, 0 == surface->fRetainCount); @@ -259,7 +244,7 @@ static void TestDeferredCanvasWritePixelsToSurface(skiatest::Reporter* reporter) REPORTER_ASSERT(reporter, 0 == surface->fRetainCount); surface->clearCounts(); - callWritePixels(canvas, srcBitmap, 5, 0, SkCanvas::kRGBA_Unpremul_Config8888); + canvas->writePixels(srcBitmap, 5, 0); REPORTER_ASSERT(reporter, 0 == surface->fDiscardCount); REPORTER_ASSERT(reporter, 1 == surface->fRetainCount); diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp index fc0fe37..a1c978d 100644 --- a/tests/WritePixelsTest.cpp +++ b/tests/WritePixelsTest.cpp @@ -56,41 +56,18 @@ static SkPMColor getCanvasColor(int x, int y) { return SkPremultiplyARGBInline(a, r, g, b); } -static bool config8888IsPremul(SkCanvas::Config8888 config8888) { - switch (config8888) { - case SkCanvas::kNative_Premul_Config8888: - case SkCanvas::kBGRA_Premul_Config8888: - case SkCanvas::kRGBA_Premul_Config8888: - return true; - case SkCanvas::kNative_Unpremul_Config8888: - case SkCanvas::kBGRA_Unpremul_Config8888: - case SkCanvas::kRGBA_Unpremul_Config8888: - return false; - default: - SkASSERT(0); - return false; - } -} - // assumes any premu/.unpremul has been applied -static uint32_t packConfig8888(SkCanvas::Config8888 config8888, - U8CPU a, U8CPU r, U8CPU g, U8CPU b) { +static uint32_t packColorType(SkColorType ct, U8CPU a, U8CPU r, U8CPU g, U8CPU b) { uint32_t r32; uint8_t* result = reinterpret_cast(&r32); - switch (config8888) { - case SkCanvas::kNative_Premul_Config8888: - case SkCanvas::kNative_Unpremul_Config8888: - r32 = SkPackARGB32NoCheck(a, r, g, b); - break; - case SkCanvas::kBGRA_Premul_Config8888: - case SkCanvas::kBGRA_Unpremul_Config8888: + switch (ct) { + case kBGRA_8888_SkColorType: result[0] = b; result[1] = g; result[2] = r; result[3] = a; break; - case SkCanvas::kRGBA_Premul_Config8888: - case SkCanvas::kRGBA_Unpremul_Config8888: + case kRGBA_8888_SkColorType: result[0] = r; result[1] = g; result[2] = b; @@ -103,7 +80,7 @@ static uint32_t packConfig8888(SkCanvas::Config8888 config8888, return r32; } -static uint32_t getBitmapColor(int x, int y, int w, SkCanvas::Config8888 config8888) { +static uint32_t getBitmapColor(int x, int y, int w, SkColorType ct, SkAlphaType at) { int n = y * w + x; U8CPU b = n & 0xff; U8CPU g = (n >> 8) & 0xff; @@ -126,12 +103,12 @@ static uint32_t getBitmapColor(int x, int y, int w, SkCanvas::Config8888 config8 a = 0x00; break; } - if (config8888IsPremul(config8888)) { + if (kPremul_SkAlphaType == at) { r = SkMulDiv255Ceiling(r, a); g = SkMulDiv255Ceiling(g, a); b = SkMulDiv255Ceiling(b, a); } - return packConfig8888(config8888, a, r, g , b); + return packColorType(ct, a, r, g , b); } static void fillCanvas(SkCanvas* canvas) { @@ -154,48 +131,38 @@ static void fillCanvas(SkCanvas* canvas) { canvas->restore(); } -static SkPMColor convertConfig8888ToPMColor(SkCanvas::Config8888 config8888, - uint32_t color, - bool* premul) { - const uint8_t* c = reinterpret_cast(&color); - U8CPU a,r,g,b; - *premul = false; - switch (config8888) { - case SkCanvas::kNative_Premul_Config8888: - return color; - case SkCanvas::kNative_Unpremul_Config8888: - *premul = true; - a = SkGetPackedA32(color); - r = SkGetPackedR32(color); - g = SkGetPackedG32(color); - b = SkGetPackedB32(color); - break; - case SkCanvas::kBGRA_Unpremul_Config8888: - *premul = true; // fallthru - case SkCanvas::kBGRA_Premul_Config8888: - a = static_cast(c[3]); - r = static_cast(c[2]); - g = static_cast(c[1]); - b = static_cast(c[0]); +/** + * Lucky for us, alpha is always in the same spot (SK_A32_SHIFT), for both RGBA and BGRA. + * Thus this routine doesn't need to know the exact colortype + */ +static uint32_t premul(uint32_t color) { + unsigned a = SkGetPackedA32(color); + // these next three are not necessarily r,g,b in that order, but they are r,g,b in some order. + unsigned c0 = SkGetPackedR32(color); + unsigned c1 = SkGetPackedG32(color); + unsigned c2 = SkGetPackedB32(color); + c0 = SkMulDiv255Ceiling(c0, a); + c1 = SkMulDiv255Ceiling(c1, a); + c2 = SkMulDiv255Ceiling(c2, a); + return SkPackARGB32NoCheck(a, c0, c1, c2); +} + +static SkPMColor convert_to_PMColor(SkColorType ct, SkAlphaType at, uint32_t color) { + if (kUnpremul_SkAlphaType == at) { + color = premul(color); + } + switch (ct) { + case kRGBA_8888_SkColorType: + color = SkSwizzle_RGBA_to_PMColor(color); break; - case SkCanvas::kRGBA_Unpremul_Config8888: - *premul = true; // fallthru - case SkCanvas::kRGBA_Premul_Config8888: - a = static_cast(c[3]); - r = static_cast(c[0]); - g = static_cast(c[1]); - b = static_cast(c[2]); + case kBGRA_8888_SkColorType: + color = SkSwizzle_BGRA_to_PMColor(color); break; default: - SkDEBUGFAIL("Unexpected Config8888"); - return 0; - } - if (*premul) { - r = SkMulDiv255Ceiling(r, a); - g = SkMulDiv255Ceiling(g, a); - b = SkMulDiv255Ceiling(b, a); + SkASSERT(0); + break; } - return SkPackARGB32(a, r, g, b); + return color; } static bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) { @@ -218,39 +185,54 @@ static bool checkPixel(SkPMColor a, SkPMColor b, bool didPremulConversion) { SkAbs32(aB - bB) <= 1; } -static bool checkWrite(skiatest::Reporter* reporter, - SkCanvas* canvas, - const SkBitmap& bitmap, - int writeX, int writeY, - SkCanvas::Config8888 config8888) { - SkBaseDevice* dev = canvas->getDevice(); - if (!dev) { +static bool checkWrite(skiatest::Reporter* reporter, SkCanvas* canvas, const SkBitmap& bitmap, + int writeX, int writeY) { + SkImageInfo canvasInfo; + size_t canvasRowBytes; + const uint32_t* canvasPixels; + + // Can't use canvas->peekPixels(), as we are trying to look at GPU pixels sometimes as well. + // At some point this will be unsupported, as we won't allow accessBitmap() to magically call + // readPixels for the client. + SkBitmap secretDevBitmap; + { + SkBaseDevice* dev = canvas->getDevice(); + if (!dev) { + return false; + } + secretDevBitmap = dev->accessBitmap(false); + } + SkAutoLockPixels alp(secretDevBitmap); + canvasInfo = secretDevBitmap.info(); + canvasRowBytes = secretDevBitmap.rowBytes(); + canvasPixels = static_cast(secretDevBitmap.getPixels()); + + if (NULL == canvasPixels) { return false; } - SkBitmap devBmp = dev->accessBitmap(false); - if (devBmp.width() != DEV_W || - devBmp.height() != DEV_H || - devBmp.config() != SkBitmap::kARGB_8888_Config || - devBmp.isNull()) { + + if (canvasInfo.width() != DEV_W || + canvasInfo.height() != DEV_H || + canvasInfo.colorType() != kPMColor_SkColorType) { return false; } - SkAutoLockPixels alp(devBmp); - intptr_t canvasPixels = reinterpret_cast(devBmp.getPixels()); - size_t canvasRowBytes = devBmp.rowBytes(); + const SkImageInfo bmInfo = bitmap.info(); + SkIRect writeRect = SkIRect::MakeXYWH(writeX, writeY, bitmap.width(), bitmap.height()); for (int cy = 0; cy < DEV_H; ++cy) { - const SkPMColor* canvasRow = reinterpret_cast(canvasPixels); for (int cx = 0; cx < DEV_W; ++cx) { - SkPMColor canvasPixel = canvasRow[cx]; + SkPMColor canvasPixel = canvasPixels[cx]; if (writeRect.contains(cx, cy)) { int bx = cx - writeX; int by = cy - writeY; - uint32_t bmpColor8888 = getBitmapColor(bx, by, bitmap.width(), config8888); - bool mul; - SkPMColor bmpPMColor = convertConfig8888ToPMColor(config8888, bmpColor8888, &mul); - bool check; - REPORTER_ASSERT(reporter, check = checkPixel(bmpPMColor, canvasPixel, mul)); + uint32_t bmpColor8888 = getBitmapColor(bx, by, bitmap.width(), + bmInfo.colorType(), bmInfo.alphaType()); + bool mul = (kUnpremul_SkAlphaType == bmInfo.alphaType()); + SkPMColor bmpPMColor = convert_to_PMColor(bmInfo.colorType(), bmInfo.alphaType(), + bmpColor8888); + bool check = checkPixel(bmpPMColor, canvasPixel, mul); + REPORTER_ASSERT(reporter, check); if (!check) { return false; } @@ -264,7 +246,7 @@ static bool checkWrite(skiatest::Reporter* reporter, } } if (cy != DEV_H -1) { - const char* pad = reinterpret_cast(canvasPixels + 4 * DEV_W); + const char* pad = reinterpret_cast(canvasPixels + DEV_W); for (size_t px = 0; px < canvasRowBytes - 4 * DEV_W; ++px) { bool check; REPORTER_ASSERT(reporter, check = (pad[px] == static_cast(DEV_PAD))); @@ -273,7 +255,7 @@ static bool checkWrite(skiatest::Reporter* reporter, } } } - canvasPixels += canvasRowBytes; + canvasPixels += canvasRowBytes/4; } return true; @@ -354,21 +336,16 @@ static SkBaseDevice* createDevice(const CanvasConfig& c, GrContext* grCtx) { return NULL; } -static bool setupBitmap(SkBitmap* bitmap, - SkCanvas::Config8888 config8888, - int w, int h, - bool tightRowBytes) { - size_t rowBytes = tightRowBytes ? 0 : 4 * w + 60; - SkImageInfo info = SkImageInfo::MakeN32Premul(w, h); - if (!allocRowBytes(bitmap, info, rowBytes)) { +static bool setupBitmap(SkBitmap* bm, SkColorType ct, SkAlphaType at, int w, int h, int tightRB) { + size_t rowBytes = tightRB ? 0 : 4 * w + 60; + SkImageInfo info = SkImageInfo::Make(w, h, ct, at); + if (!allocRowBytes(bm, info, rowBytes)) { return false; } - SkAutoLockPixels alp(*bitmap); - intptr_t pixels = reinterpret_cast(bitmap->getPixels()); + SkAutoLockPixels alp(*bm); for (int y = 0; y < h; ++y) { for (int x = 0; x < w; ++x) { - uint32_t* pixel = reinterpret_cast(pixels + y * bitmap->rowBytes() + x * 4); - *pixel = getBitmapColor(x, y, w, config8888); + *bm->getAddr32(x, y) = getBitmapColor(x, y, w, ct, at); } } return true; @@ -452,31 +429,33 @@ DEF_GPUTEST(WritePixels, reporter, factory) { SkAutoTUnref device(createDevice(gCanvasConfigs[i], context)); SkCanvas canvas(device); - static const SkCanvas::Config8888 gSrcConfigs[] = { - SkCanvas::kNative_Premul_Config8888, - SkCanvas::kNative_Unpremul_Config8888, - SkCanvas::kBGRA_Premul_Config8888, - SkCanvas::kBGRA_Unpremul_Config8888, - SkCanvas::kRGBA_Premul_Config8888, - SkCanvas::kRGBA_Unpremul_Config8888, + static const struct { + SkColorType fColorType; + SkAlphaType fAlphaType; + } gSrcConfigs[] = { + { kRGBA_8888_SkColorType, kPremul_SkAlphaType }, + { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType }, + { kBGRA_8888_SkColorType, kPremul_SkAlphaType }, + { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType }, }; for (size_t r = 0; r < SK_ARRAY_COUNT(testRects); ++r) { const SkIRect& rect = testRects[r]; for (int tightBmp = 0; tightBmp < 2; ++tightBmp) { for (size_t c = 0; c < SK_ARRAY_COUNT(gSrcConfigs); ++c) { + const SkColorType ct = gSrcConfigs[c].fColorType; + const SkAlphaType at = gSrcConfigs[c].fAlphaType; + fillCanvas(&canvas); - SkCanvas::Config8888 config8888 = gSrcConfigs[c]; SkBitmap bmp; - REPORTER_ASSERT(reporter, setupBitmap(&bmp, config8888, rect.width(), rect.height(), SkToBool(tightBmp))); + REPORTER_ASSERT(reporter, setupBitmap(&bmp, ct, at, rect.width(), + rect.height(), SkToBool(tightBmp))); uint32_t idBefore = canvas.getDevice()->accessBitmap(false).getGenerationID(); - SkColorType ct; - SkAlphaType at; - sk_tool_utils::config8888_to_imagetypes(config8888, &ct, &at); - sk_tool_utils::write_pixels(&canvas, bmp, rect.fLeft, rect.fTop, ct, at); + // sk_tool_utils::write_pixels(&canvas, bmp, rect.fLeft, rect.fTop, ct, at); + canvas.writePixels(bmp, rect.fLeft, rect.fTop); uint32_t idAfter = canvas.getDevice()->accessBitmap(false).getGenerationID(); - REPORTER_ASSERT(reporter, checkWrite(reporter, &canvas, bmp, rect.fLeft, rect.fTop, config8888)); + REPORTER_ASSERT(reporter, checkWrite(reporter, &canvas, bmp, rect.fLeft, rect.fTop)); // we should change the genID iff pixels were actually written. SkIRect canvasRect = SkIRect::MakeSize(canvas.getDeviceSize()); diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp index d13b0d8..3eb5555 100644 --- a/tools/sk_tool_utils.cpp +++ b/tools/sk_tool_utils.cpp @@ -17,37 +17,6 @@ const char* colortype_name(SkColorType ct) { } } -void config8888_to_imagetypes(SkCanvas::Config8888 config, SkColorType* ct, SkAlphaType* at) { - switch (config) { - case SkCanvas::kNative_Premul_Config8888: - *ct = kPMColor_SkColorType; - *at = kPremul_SkAlphaType; - break; - case SkCanvas::kNative_Unpremul_Config8888: - *ct = kPMColor_SkColorType; - *at = kUnpremul_SkAlphaType; - break; - case SkCanvas::kBGRA_Premul_Config8888: - *ct = kBGRA_8888_SkColorType; - *at = kPremul_SkAlphaType; - break; - case SkCanvas::kBGRA_Unpremul_Config8888: - *ct = kBGRA_8888_SkColorType; - *at = kUnpremul_SkAlphaType; - break; - case SkCanvas::kRGBA_Premul_Config8888: - *ct = kRGBA_8888_SkColorType; - *at = kPremul_SkAlphaType; - break; - case SkCanvas::kRGBA_Unpremul_Config8888: - *ct = kRGBA_8888_SkColorType; - *at = kUnpremul_SkAlphaType; - break; - default: - SkASSERT(0); - } -} - void write_pixels(SkCanvas* canvas, const SkBitmap& bitmap, int x, int y, SkColorType colorType, SkAlphaType alphaType) { SkBitmap tmp(bitmap); diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h index ac1cdab..48fd716 100644 --- a/tools/sk_tool_utils.h +++ b/tools/sk_tool_utils.h @@ -16,11 +16,6 @@ namespace sk_tool_utils { const char* colortype_name(SkColorType); /** - * Return the colorType and alphaType that correspond to the specified Config8888 - */ - void config8888_to_imagetypes(SkCanvas::Config8888, SkColorType*, SkAlphaType*); - - /** * Call canvas->writePixels() by using the pixels from bitmap, but with an info that claims * the pixels are colorType + alphaType */ -- 2.7.4