sRGB support in Ganesh. Several pieces:

sRGB support now also requires GL_EXT_texture_sRGB_decode, which allows
us to disable sRGB -> Linear conversion when reading textures. This gives
us an easy way to support "legacy" L32 mode. We disable decoding based on
the pixel config of the render target. Textures can override that behavior
(specifically for format-conversion draws where we want that behavior).

Added sBGRA pixel config, which is not-really-a-format. It's just sRGBA
internally, and the external format is BGR order, so TexImage calls will
swizzle correctly. This lets us interact with sRGB raster surfaces on BGR
platforms.

Devices without sRGB support behave like they always have: conversion from
color type and profile type ignores sRGB and always returns linear pixel
configs.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1789663002

Review URL: https://codereview.chromium.org/1789663002
This commit is contained in:
brianosman 2016-03-21 06:55:37 -07:00 committed by Commit bot
parent f8ee67edb8
commit a635936588
28 changed files with 234 additions and 68 deletions

View File

@ -157,7 +157,8 @@ void HelloWorldWindow::draw(SkCanvas* canvas) {
fRenderTarget->writePixels(0, 0, snap->width(), snap->height(), fRenderTarget->writePixels(0, 0, snap->width(), snap->height(),
SkImageInfo2GrPixelConfig(info.colorType(), SkImageInfo2GrPixelConfig(info.colorType(),
info.alphaType(), info.alphaType(),
info.profileType()), info.profileType(),
*fContext->caps()),
pmap.addr(), pmap.addr(),
pmap.rowBytes(), pmap.rowBytes(),
GrContext::kFlushWrites_PixelOp); GrContext::kFlushWrites_PixelOp);

View File

@ -137,6 +137,7 @@ public:
/** To avoid as-yet-unnecessary complexity we don't allow any partial support of MIP Maps (e.g. /** To avoid as-yet-unnecessary complexity we don't allow any partial support of MIP Maps (e.g.
only for POT textures) */ only for POT textures) */
bool mipMapSupport() const { return fMipMapSupport; } bool mipMapSupport() const { return fMipMapSupport; }
bool srgbSupport() const { return fSRGBSupport; }
bool twoSidedStencilSupport() const { return fTwoSidedStencilSupport; } bool twoSidedStencilSupport() const { return fTwoSidedStencilSupport; }
bool stencilWrapOpsSupport() const { return fStencilWrapOpsSupport; } bool stencilWrapOpsSupport() const { return fStencilWrapOpsSupport; }
bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; } bool discardRenderTargetSupport() const { return fDiscardRenderTargetSupport; }
@ -268,6 +269,7 @@ protected:
bool fNPOTTextureTileSupport : 1; bool fNPOTTextureTileSupport : 1;
bool fMipMapSupport : 1; bool fMipMapSupport : 1;
bool fSRGBSupport : 1;
bool fTwoSidedStencilSupport : 1; bool fTwoSidedStencilSupport : 1;
bool fStencilWrapOpsSupport : 1; bool fStencilWrapOpsSupport : 1;
bool fDiscardRenderTargetSupport : 1; bool fDiscardRenderTargetSupport : 1;

View File

@ -208,7 +208,6 @@ static inline char GrColorComponentFlagToChar(GrColorComponentFlags component) {
} }
static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) { static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) {
SkASSERT(config >= 0 && config < kGrPixelConfigCnt);
static const uint32_t kFlags[] = { static const uint32_t kFlags[] = {
0, // kUnknown_GrPixelConfig 0, // kUnknown_GrPixelConfig
kA_GrColorComponentFlag, // kAlpha_8_GrPixelConfig kA_GrColorComponentFlag, // kAlpha_8_GrPixelConfig
@ -218,6 +217,7 @@ static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) {
kRGBA_GrColorComponentFlags, // kRGBA_8888_GrPixelConfig kRGBA_GrColorComponentFlags, // kRGBA_8888_GrPixelConfig
kRGBA_GrColorComponentFlags, // kBGRA_8888_GrPixelConfig kRGBA_GrColorComponentFlags, // kBGRA_8888_GrPixelConfig
kRGBA_GrColorComponentFlags, // kSRGBA_8888_GrPixelConfig kRGBA_GrColorComponentFlags, // kSRGBA_8888_GrPixelConfig
kRGBA_GrColorComponentFlags, // kSBGRA_8888_GrPixelConfig
kRGB_GrColorComponentFlags, // kETC1_GrPixelConfig kRGB_GrColorComponentFlags, // kETC1_GrPixelConfig
kA_GrColorComponentFlag, // kLATC_GrPixelConfig kA_GrColorComponentFlag, // kLATC_GrPixelConfig
kA_GrColorComponentFlag, // kR11_EAC_GrPixelConfig kA_GrColorComponentFlag, // kR11_EAC_GrPixelConfig
@ -236,13 +236,14 @@ static inline uint32_t GrPixelConfigComponentMask(GrPixelConfig config) {
GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig); GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig);
GR_STATIC_ASSERT(8 == kETC1_GrPixelConfig); GR_STATIC_ASSERT(8 == kSBGRA_8888_GrPixelConfig);
GR_STATIC_ASSERT(9 == kLATC_GrPixelConfig); GR_STATIC_ASSERT(9 == kETC1_GrPixelConfig);
GR_STATIC_ASSERT(10 == kR11_EAC_GrPixelConfig); GR_STATIC_ASSERT(10 == kLATC_GrPixelConfig);
GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig); GR_STATIC_ASSERT(11 == kR11_EAC_GrPixelConfig);
GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig); GR_STATIC_ASSERT(12 == kASTC_12x12_GrPixelConfig);
GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig); GR_STATIC_ASSERT(13 == kRGBA_float_GrPixelConfig);
GR_STATIC_ASSERT(14 == kRGBA_half_GrPixelConfig); GR_STATIC_ASSERT(14 == kAlpha_half_GrPixelConfig);
GR_STATIC_ASSERT(15 == kRGBA_half_GrPixelConfig);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFlags) == kGrPixelConfigCnt); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFlags) == kGrPixelConfigCnt);
} }

View File

@ -24,6 +24,11 @@ public:
static const GrTextureParams gParams(SkShader::kClamp_TileMode, kBilerp_FilterMode); static const GrTextureParams gParams(SkShader::kClamp_TileMode, kBilerp_FilterMode);
return gParams; return gParams;
} }
static const GrTextureParams& ClampNoFilterForceAllowSRGB() {
static const GrTextureParams gParams(SkShader::kClamp_TileMode, kNone_FilterMode,
kForceAllowSRGB_SRGBMode);
return gParams;
}
GrTextureParams() { GrTextureParams() {
this->reset(); this->reset();
@ -35,10 +40,19 @@ public:
kMipMap_FilterMode kMipMap_FilterMode
}; };
enum SRGBMode {
kRespectDestination_SRGBMode,
kForceAllowSRGB_SRGBMode,
};
GrTextureParams(SkShader::TileMode tileXAndY, FilterMode filterMode) { GrTextureParams(SkShader::TileMode tileXAndY, FilterMode filterMode) {
this->reset(tileXAndY, filterMode); this->reset(tileXAndY, filterMode);
} }
GrTextureParams(SkShader::TileMode tileXandY, FilterMode filterMode, SRGBMode srgbMode) {
this->reset(tileXandY, filterMode, srgbMode);
}
GrTextureParams(const SkShader::TileMode tileModes[2], FilterMode filterMode) { GrTextureParams(const SkShader::TileMode tileModes[2], FilterMode filterMode) {
this->reset(tileModes, filterMode); this->reset(tileModes, filterMode);
} }
@ -51,6 +65,7 @@ public:
fTileModes[0] = params.fTileModes[0]; fTileModes[0] = params.fTileModes[0];
fTileModes[1] = params.fTileModes[1]; fTileModes[1] = params.fTileModes[1];
fFilterMode = params.fFilterMode; fFilterMode = params.fFilterMode;
fSRGBMode = params.fSRGBMode;
return *this; return *this;
} }
@ -61,12 +76,20 @@ public:
void reset(SkShader::TileMode tileXAndY, FilterMode filterMode) { void reset(SkShader::TileMode tileXAndY, FilterMode filterMode) {
fTileModes[0] = fTileModes[1] = tileXAndY; fTileModes[0] = fTileModes[1] = tileXAndY;
fFilterMode = filterMode; fFilterMode = filterMode;
fSRGBMode = kRespectDestination_SRGBMode;
}
void reset(SkShader::TileMode tileXandY, FilterMode filterMode, SRGBMode srgbMode) {
fTileModes[0] = fTileModes[1] = tileXandY;
fFilterMode = filterMode;
fSRGBMode = srgbMode;
} }
void reset(const SkShader::TileMode tileModes[2], FilterMode filterMode) { void reset(const SkShader::TileMode tileModes[2], FilterMode filterMode) {
fTileModes[0] = tileModes[0]; fTileModes[0] = tileModes[0];
fTileModes[1] = tileModes[1]; fTileModes[1] = tileModes[1];
fFilterMode = filterMode; fFilterMode = filterMode;
fSRGBMode = kRespectDestination_SRGBMode;
} }
void setClampNoFilter() { void setClampNoFilter() {
@ -84,6 +107,8 @@ public:
void setTileModeY(const SkShader::TileMode tm) { fTileModes[1] = tm; } void setTileModeY(const SkShader::TileMode tm) { fTileModes[1] = tm; }
void setTileModeXAndY(const SkShader::TileMode tm) { fTileModes[0] = fTileModes[1] = tm; } void setTileModeXAndY(const SkShader::TileMode tm) { fTileModes[0] = fTileModes[1] = tm; }
void setSRGBMode(SRGBMode srgbMode) { fSRGBMode = srgbMode; }
SkShader::TileMode getTileModeX() const { return fTileModes[0]; } SkShader::TileMode getTileModeX() const { return fTileModes[0]; }
SkShader::TileMode getTileModeY() const { return fTileModes[1]; } SkShader::TileMode getTileModeY() const { return fTileModes[1]; }
@ -95,10 +120,13 @@ public:
FilterMode filterMode() const { return fFilterMode; } FilterMode filterMode() const { return fFilterMode; }
SRGBMode srgbMode() const { return fSRGBMode; }
bool operator== (const GrTextureParams& other) const { bool operator== (const GrTextureParams& other) const {
return fTileModes[0] == other.fTileModes[0] && return fTileModes[0] == other.fTileModes[0] &&
fTileModes[1] == other.fTileModes[1] && fTileModes[1] == other.fTileModes[1] &&
fFilterMode == other.fFilterMode; fFilterMode == other.fFilterMode &&
fSRGBMode == other.fSRGBMode;
} }
bool operator!= (const GrTextureParams& other) const { return !(*this == other); } bool operator!= (const GrTextureParams& other) const { return !(*this == other); }
@ -106,5 +134,6 @@ public:
private: private:
SkShader::TileMode fTileModes[2]; SkShader::TileMode fTileModes[2];
FilterMode fFilterMode; FilterMode fFilterMode;
SRGBMode fSRGBMode;
}; };
#endif #endif

View File

@ -217,6 +217,10 @@ enum GrPixelConfig {
* Premultiplied and sRGB. Byte order is r,g,b,a. * Premultiplied and sRGB. Byte order is r,g,b,a.
*/ */
kSRGBA_8888_GrPixelConfig, kSRGBA_8888_GrPixelConfig,
/**
* Premultiplied and sRGB. Byte order is b,g,r,a.
*/
kSBGRA_8888_GrPixelConfig,
/** /**
* ETC1 Compressed Data * ETC1 Compressed Data
*/ */
@ -268,8 +272,10 @@ static const int kGrPixelConfigCnt = kLast_GrPixelConfig + 1;
#endif #endif
#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
static const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig; static const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig;
static const GrPixelConfig kSkiaGamma8888_GrPixelConfig = kSBGRA_8888_GrPixelConfig;
#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
static const GrPixelConfig kSkia8888_GrPixelConfig = kRGBA_8888_GrPixelConfig; static const GrPixelConfig kSkia8888_GrPixelConfig = kRGBA_8888_GrPixelConfig;
static const GrPixelConfig kSkiaGamma8888_GrPixelConfig = kSRGBA_8888_GrPixelConfig;
#else #else
#error "SK_*32_SHIFT values must correspond to GL_BGRA or GL_RGBA format." #error "SK_*32_SHIFT values must correspond to GL_BGRA or GL_RGBA format."
#endif #endif
@ -311,6 +317,7 @@ static inline bool GrPixelConfigIs8888(GrPixelConfig config) {
case kRGBA_8888_GrPixelConfig: case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig: case kBGRA_8888_GrPixelConfig:
case kSRGBA_8888_GrPixelConfig: case kSRGBA_8888_GrPixelConfig:
case kSBGRA_8888_GrPixelConfig:
return true; return true;
default: default:
return false; return false;
@ -322,6 +329,7 @@ static inline bool GrPixelConfigIs8888(GrPixelConfig config) {
static inline bool GrPixelConfigIsSRGB(GrPixelConfig config) { static inline bool GrPixelConfigIsSRGB(GrPixelConfig config) {
switch (config) { switch (config) {
case kSRGBA_8888_GrPixelConfig: case kSRGBA_8888_GrPixelConfig:
case kSBGRA_8888_GrPixelConfig:
return true; return true;
default: default:
return false; return false;
@ -336,6 +344,10 @@ static inline GrPixelConfig GrPixelConfigSwapRAndB(GrPixelConfig config) {
return kRGBA_8888_GrPixelConfig; return kRGBA_8888_GrPixelConfig;
case kRGBA_8888_GrPixelConfig: case kRGBA_8888_GrPixelConfig:
return kBGRA_8888_GrPixelConfig; return kBGRA_8888_GrPixelConfig;
case kSBGRA_8888_GrPixelConfig:
return kSRGBA_8888_GrPixelConfig;
case kSRGBA_8888_GrPixelConfig:
return kSBGRA_8888_GrPixelConfig;
default: default:
return kUnknown_GrPixelConfig; return kUnknown_GrPixelConfig;
} }
@ -353,6 +365,7 @@ static inline size_t GrBytesPerPixel(GrPixelConfig config) {
case kRGBA_8888_GrPixelConfig: case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig: case kBGRA_8888_GrPixelConfig:
case kSRGBA_8888_GrPixelConfig: case kSRGBA_8888_GrPixelConfig:
case kSBGRA_8888_GrPixelConfig:
return 4; return 4;
case kRGBA_half_GrPixelConfig: case kRGBA_half_GrPixelConfig:
return 8; return 8;
@ -386,6 +399,16 @@ static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) {
} }
} }
static inline bool GrAllowSRGBForDestinationPixelConfig(GrPixelConfig config) {
switch (config) {
case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig:
return false;
default:
return true;
}
}
/** /**
* Optional bitfield flags that can be set on GrSurfaceDesc (below). * Optional bitfield flags that can be set on GrSurfaceDesc (below).
*/ */

View File

@ -15,6 +15,7 @@
#include "SkFilterQuality.h" #include "SkFilterQuality.h"
#include "SkImageInfo.h" #include "SkImageInfo.h"
class GrCaps;
class GrContext; class GrContext;
class GrTexture; class GrTexture;
class GrTextureParams; class GrTextureParams;
@ -70,10 +71,10 @@ static inline GrColor SkPMColorToGrColor(SkPMColor c) {
GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams&); GrTexture* GrRefCachedBitmapTexture(GrContext*, const SkBitmap&, const GrTextureParams&);
// TODO: Move SkImageInfo2GrPixelConfig to SkGrPriv.h (requires cleanup to SkWindow its subclasses). // TODO: Move SkImageInfo2GrPixelConfig to SkGrPriv.h (requires cleanup to SkWindow its subclasses).
GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType, SkAlphaType, SkColorProfileType); GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType, SkAlphaType, SkColorProfileType, const GrCaps&);
static inline GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info) { static inline GrPixelConfig SkImageInfo2GrPixelConfig(const SkImageInfo& info, const GrCaps& caps) {
return SkImageInfo2GrPixelConfig(info.colorType(), info.alphaType(), info.profileType()); return SkImageInfo2GrPixelConfig(info.colorType(), info.alphaType(), info.profileType(), caps);
} }
GrTextureParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality paintFilterQuality, GrTextureParams::FilterMode GrSkFilterQualityToGrFilterMode(SkFilterQuality paintFilterQuality,

View File

@ -310,7 +310,8 @@ public:
fCurRenderTarget->writePixels(0, 0, bm.width(), bm.height(), fCurRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
SkImageInfo2GrPixelConfig(bm.colorType(), SkImageInfo2GrPixelConfig(bm.colorType(),
bm.alphaType(), bm.alphaType(),
bm.profileType()), bm.profileType(),
*fCurContext->caps()),
bm.getPixels(), bm.getPixels(),
bm.rowBytes(), bm.rowBytes(),
GrContext::kFlushWrites_PixelOp); GrContext::kFlushWrites_PixelOp);

View File

@ -171,7 +171,8 @@ bool SkImageCacherator::lockAsBitmap(SkBitmap* bitmap, const SkImage* client,
} }
const uint32_t pixelOpsFlags = 0; const uint32_t pixelOpsFlags = 0;
if (!tex->readPixels(0, 0, bitmap->width(), bitmap->height(), SkImageInfo2GrPixelConfig(fInfo), if (!tex->readPixels(0, 0, bitmap->width(), bitmap->height(),
SkImageInfo2GrPixelConfig(fInfo, *tex->getContext()->caps()),
bitmap->getPixels(), bitmap->rowBytes(), pixelOpsFlags)) { bitmap->getPixels(), bitmap->rowBytes(), pixelOpsFlags)) {
bitmap->reset(); bitmap->reset();
return false; return false;
@ -273,7 +274,7 @@ GrTexture* SkImageCacherator::lockTexture(GrContext* ctx, const GrUniqueKey& key
} }
} }
const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(fInfo); const GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(fInfo, *ctx->caps());
// 3. Ask the generator to return a compressed form that the GPU might support // 3. Ask the generator to return a compressed form that the GPU might support
SkAutoTUnref<SkData> data(this->refEncoded(ctx)); SkAutoTUnref<SkData> data(this->refEncoded(ctx));

View File

@ -136,6 +136,7 @@ SkImageFilter::Proxy* SkSpecialImage::internal_getProxy() const {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#include "SkImage.h" #include "SkImage.h"
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrContext.h"
#include "SkGrPriv.h" #include "SkGrPriv.h"
#endif #endif
@ -206,7 +207,7 @@ public:
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
GrTexture* texture = as_IB(fImage.get())->peekTexture(); GrTexture* texture = as_IB(fImage.get())->peekTexture();
if (texture) { if (texture) {
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info); GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *texture->getContext()->caps());
desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fFlags = kRenderTarget_GrSurfaceFlag;
return SkSpecialSurface::MakeRenderTarget(this->proxy(), texture->getContext(), desc); return SkSpecialSurface::MakeRenderTarget(this->proxy(), texture->getContext(), desc);
@ -430,7 +431,7 @@ public:
} }
sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override { sk_sp<SkSpecialSurface> onMakeSurface(const SkImageInfo& info) const override {
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info); GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(info, *fTexture->getContext()->caps());
desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fFlags = kRenderTarget_GrSurfaceFlag;
return SkSpecialSurface::MakeRenderTarget(this->proxy(), fTexture->getContext(), desc); return SkSpecialSurface::MakeRenderTarget(this->proxy(), fTexture->getContext(), desc);

View File

@ -198,6 +198,8 @@ GrTexture* GaussianBlur(GrContext* context,
SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() || SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
kRGBA_8888_GrPixelConfig == srcTexture->config() || kRGBA_8888_GrPixelConfig == srcTexture->config() ||
kSRGBA_8888_GrPixelConfig == srcTexture->config() ||
kSBGRA_8888_GrPixelConfig == srcTexture->config() ||
kAlpha_8_GrPixelConfig == srcTexture->config()); kAlpha_8_GrPixelConfig == srcTexture->config());
GrSurfaceDesc desc; GrSurfaceDesc desc;

View File

@ -331,6 +331,7 @@ SkColorFilter* SkTable_ColorFilter::newComposed(const SkColorFilter* innerFilter
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "GrContext.h"
#include "GrFragmentProcessor.h" #include "GrFragmentProcessor.h"
#include "GrInvariantOutput.h" #include "GrInvariantOutput.h"
#include "SkGr.h" #include "SkGr.h"
@ -466,7 +467,7 @@ const GrFragmentProcessor* ColorTableEffect::Create(GrContext* context, SkBitmap
desc.fHeight = 128; desc.fHeight = 128;
desc.fRowHeight = bitmap.height(); desc.fRowHeight = bitmap.height();
desc.fContext = context; desc.fContext = context;
desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info()); desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info(), *context->caps());
GrTextureStripAtlas* atlas = GrTextureStripAtlas::GetAtlas(desc); GrTextureStripAtlas* atlas = GrTextureStripAtlas::GetAtlas(desc);
int row = atlas->lockRow(bitmap); int row = atlas->lockRow(bitmap);
SkAutoTUnref<GrTexture> texture; SkAutoTUnref<GrTexture> texture;

View File

@ -905,6 +905,7 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
#include "effects/GrTextureStripAtlas.h" #include "effects/GrTextureStripAtlas.h"
#include "GrContext.h"
#include "GrInvariantOutput.h" #include "GrInvariantOutput.h"
#include "gl/GrGLContext.h" #include "gl/GrGLContext.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h" #include "glsl/GrGLSLFragmentShaderBuilder.h"
@ -1117,7 +1118,7 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
desc.fHeight = 32; desc.fHeight = 32;
desc.fRowHeight = bitmap.height(); desc.fRowHeight = bitmap.height();
desc.fContext = ctx; desc.fContext = ctx;
desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info()); desc.fConfig = SkImageInfo2GrPixelConfig(bitmap.info(), *ctx->caps());
fAtlas = GrTextureStripAtlas::GetAtlas(desc); fAtlas = GrTextureStripAtlas::GetAtlas(desc);
SkASSERT(fAtlas); SkASSERT(fAtlas);

View File

@ -83,6 +83,7 @@ void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
GrCaps::GrCaps(const GrContextOptions& options) { GrCaps::GrCaps(const GrContextOptions& options) {
fMipMapSupport = false; fMipMapSupport = false;
fNPOTTextureTileSupport = false; fNPOTTextureTileSupport = false;
fSRGBSupport = false;
fTwoSidedStencilSupport = false; fTwoSidedStencilSupport = false;
fStencilWrapOpsSupport = false; fStencilWrapOpsSupport = false;
fDiscardRenderTargetSupport = false; fDiscardRenderTargetSupport = false;
@ -157,6 +158,7 @@ SkString GrCaps::dump() const {
static const char* gNY[] = {"NO", "YES"}; static const char* gNY[] = {"NO", "YES"};
r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]); r.appendf("MIP Map Support : %s\n", gNY[fMipMapSupport]);
r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]); r.appendf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
r.appendf("sRGB Support : %s\n", gNY[fSRGBSupport]);
r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]); r.appendf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]); r.appendf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]); r.appendf("Discard Render Target Support : %s\n", gNY[fDiscardRenderTargetSupport]);
@ -210,6 +212,7 @@ SkString GrCaps::dump() const {
"RGBA8888", // kRGBA_8888_GrPixelConfig, "RGBA8888", // kRGBA_8888_GrPixelConfig,
"BGRA8888", // kBGRA_8888_GrPixelConfig, "BGRA8888", // kBGRA_8888_GrPixelConfig,
"SRGBA8888",// kSRGBA_8888_GrPixelConfig, "SRGBA8888",// kSRGBA_8888_GrPixelConfig,
"SBGRA8888",// kSBGRA_8888_GrPixelConfig,
"ETC1", // kETC1_GrPixelConfig, "ETC1", // kETC1_GrPixelConfig,
"LATC", // kLATC_GrPixelConfig, "LATC", // kLATC_GrPixelConfig,
"R11EAC", // kR11_EAC_GrPixelConfig, "R11EAC", // kR11_EAC_GrPixelConfig,
@ -226,13 +229,14 @@ SkString GrCaps::dump() const {
GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig); GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig); GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig); GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig);
GR_STATIC_ASSERT(8 == kETC1_GrPixelConfig); GR_STATIC_ASSERT(8 == kSBGRA_8888_GrPixelConfig);
GR_STATIC_ASSERT(9 == kLATC_GrPixelConfig); GR_STATIC_ASSERT(9 == kETC1_GrPixelConfig);
GR_STATIC_ASSERT(10 == kR11_EAC_GrPixelConfig); GR_STATIC_ASSERT(10 == kLATC_GrPixelConfig);
GR_STATIC_ASSERT(11 == kASTC_12x12_GrPixelConfig); GR_STATIC_ASSERT(11 == kR11_EAC_GrPixelConfig);
GR_STATIC_ASSERT(12 == kRGBA_float_GrPixelConfig); GR_STATIC_ASSERT(12 == kASTC_12x12_GrPixelConfig);
GR_STATIC_ASSERT(13 == kAlpha_half_GrPixelConfig); GR_STATIC_ASSERT(13 == kRGBA_float_GrPixelConfig);
GR_STATIC_ASSERT(14 == kRGBA_half_GrPixelConfig); GR_STATIC_ASSERT(14 == kAlpha_half_GrPixelConfig);
GR_STATIC_ASSERT(15 == kRGBA_half_GrPixelConfig);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt); GR_STATIC_ASSERT(SK_ARRAY_COUNT(kConfigNames) == kGrPixelConfigCnt);
SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, false)); SkASSERT(!this->isConfigRenderable(kUnknown_GrPixelConfig, false));

View File

@ -193,6 +193,7 @@ GrRenderTarget* SkGpuDevice::CreateRenderTarget(
SkColorType ct = origInfo.colorType(); SkColorType ct = origInfo.colorType();
SkAlphaType at = origInfo.alphaType(); SkAlphaType at = origInfo.alphaType();
SkColorProfileType pt = origInfo.profileType();
if (kRGB_565_SkColorType == ct) { if (kRGB_565_SkColorType == ct) {
at = kOpaque_SkAlphaType; // force this setting at = kOpaque_SkAlphaType; // force this setting
} else if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType) { } else if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType) {
@ -202,13 +203,13 @@ GrRenderTarget* SkGpuDevice::CreateRenderTarget(
if (kOpaque_SkAlphaType != at) { if (kOpaque_SkAlphaType != at) {
at = kPremul_SkAlphaType; // force this setting at = kPremul_SkAlphaType; // force this setting
} }
const SkImageInfo info = SkImageInfo::Make(origInfo.width(), origInfo.height(), ct, at); const SkImageInfo info = SkImageInfo::Make(origInfo.width(), origInfo.height(), ct, at, pt);
GrSurfaceDesc desc; GrSurfaceDesc desc;
desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fWidth = info.width(); desc.fWidth = info.width();
desc.fHeight = info.height(); desc.fHeight = info.height();
desc.fConfig = SkImageInfo2GrPixelConfig(info); desc.fConfig = SkImageInfo2GrPixelConfig(info, *context->caps());
desc.fSampleCnt = sampleCount; desc.fSampleCnt = sampleCount;
desc.fTextureStorageAllocator = textureStorageAllocator; desc.fTextureStorageAllocator = textureStorageAllocator;
desc.fIsMipMapped = false; desc.fIsMipMapped = false;
@ -227,7 +228,7 @@ bool SkGpuDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
// TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo); GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
if (kUnknown_GrPixelConfig == config) { if (kUnknown_GrPixelConfig == config) {
return false; return false;
} }
@ -244,7 +245,7 @@ bool SkGpuDevice::onWritePixels(const SkImageInfo& info, const void* pixels, siz
int x, int y) { int x, int y) {
ASSERT_SINGLE_OWNER ASSERT_SINGLE_OWNER
// TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
GrPixelConfig config = SkImageInfo2GrPixelConfig(info); GrPixelConfig config = SkImageInfo2GrPixelConfig(info, *fContext->caps());
if (kUnknown_GrPixelConfig == config) { if (kUnknown_GrPixelConfig == config) {
return false; return false;
} }

View File

@ -43,12 +43,12 @@
# include "etc1.h" # include "etc1.h"
#endif #endif
GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info) { GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo& info, const GrCaps& caps) {
GrSurfaceDesc desc; GrSurfaceDesc desc;
desc.fFlags = kNone_GrSurfaceFlags; desc.fFlags = kNone_GrSurfaceFlags;
desc.fWidth = info.width(); desc.fWidth = info.width();
desc.fHeight = info.height(); desc.fHeight = info.height();
desc.fConfig = SkImageInfo2GrPixelConfig(info); desc.fConfig = SkImageInfo2GrPixelConfig(info, caps);
desc.fSampleCnt = 0; desc.fSampleCnt = 0;
return desc; return desc;
} }
@ -213,7 +213,7 @@ static GrTexture* load_etc1_texture(GrContext* ctx, const SkBitmap &bm, GrSurfac
} }
GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bitmap) { GrTexture* GrUploadBitmapToTexture(GrContext* ctx, const SkBitmap& bitmap) {
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info()); GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info(), *ctx->caps());
if (GrTexture *texture = load_etc1_texture(ctx, bitmap, desc)) { if (GrTexture *texture = load_etc1_texture(ctx, bitmap, desc)) {
return texture; return texture;
} }
@ -238,10 +238,34 @@ GrTexture* GrUploadPixmapToTexture(GrContext* ctx, const SkPixmap& pixmap, SkBud
SkPixmap tmpPixmap; SkPixmap tmpPixmap;
SkBitmap tmpBitmap; SkBitmap tmpBitmap;
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info());
const GrCaps* caps = ctx->caps(); const GrCaps* caps = ctx->caps();
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(pixmap.info(), *caps);
if (kIndex_8_SkColorType == pixmap.colorType()) { if (caps->srgbSupport() && !GrPixelConfigIsSRGB(desc.fConfig) &&
kSRGB_SkColorProfileType == pixmap.info().profileType()) {
// We we supplied sRGB as the profile type, but we don't have a suitable pixel config.
// Convert to 8888 sRGB so we can handle the data correctly. The raster backend doesn't
// handle sRGB Index8 -> sRGB 8888 correctly (yet), so lie about both the source and
// destination (claim they're linear):
SkImageInfo linSrcInfo = SkImageInfo::Make(pixmap.width(), pixmap.height(),
pixmap.colorType(), pixmap.alphaType());
SkPixmap linSrcPixmap(linSrcInfo, pixmap.addr(), pixmap.rowBytes(), pixmap.ctable());
SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height(),
kSRGB_SkColorProfileType);
tmpBitmap.allocPixels(dstInfo);
SkImageInfo linDstInfo = SkImageInfo::MakeN32Premul(pixmap.width(), pixmap.height());
if (!linSrcPixmap.readPixels(linDstInfo, tmpBitmap.getPixels(), tmpBitmap.rowBytes())) {
return nullptr;
}
if (!tmpBitmap.peekPixels(&tmpPixmap)) {
return nullptr;
}
pmap = &tmpPixmap;
// must rebuild desc, since we've forced the info to be N32
desc = GrImageInfoToSurfaceDesc(pmap->info(), *caps);
} else if (kIndex_8_SkColorType == pixmap.colorType()) {
if (caps->isConfigTexturable(kIndex_8_GrPixelConfig)) { if (caps->isConfigTexturable(kIndex_8_GrPixelConfig)) {
size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig, size_t imageSize = GrCompressedFormatDataSize(kIndex_8_GrPixelConfig,
pixmap.width(), pixmap.height()); pixmap.width(), pixmap.height());
@ -263,7 +287,7 @@ GrTexture* GrUploadPixmapToTexture(GrContext* ctx, const SkPixmap& pixmap, SkBud
} }
pmap = &tmpPixmap; pmap = &tmpPixmap;
// must rebuild desc, since we've forced the info to be N32 // must rebuild desc, since we've forced the info to be N32
desc = GrImageInfoToSurfaceDesc(pmap->info()); desc = GrImageInfoToSurfaceDesc(pmap->info(), *caps);
} }
} }
@ -289,7 +313,7 @@ void GrInstallBitmapUniqueKeyInvalidator(const GrUniqueKey& key, SkPixelRef* pix
GrTexture* GrGenerateMipMapsAndUploadToTexture(GrContext* ctx, const SkBitmap& bitmap) GrTexture* GrGenerateMipMapsAndUploadToTexture(GrContext* ctx, const SkBitmap& bitmap)
{ {
GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info()); GrSurfaceDesc desc = GrImageInfoToSurfaceDesc(bitmap.info(), *ctx->caps());
if (kIndex_8_SkColorType != bitmap.colorType() && !bitmap.readyToDraw()) { if (kIndex_8_SkColorType != bitmap.colorType() && !bitmap.readyToDraw()) {
GrTexture* texture = load_etc1_texture(ctx, bitmap, desc); GrTexture* texture = load_etc1_texture(ctx, bitmap, desc);
if (texture) { if (texture) {
@ -358,7 +382,10 @@ GrTexture* GrRefCachedBitmapTexture(GrContext* ctx, const SkBitmap& bitmap,
// alphatype is ignore for now, but if GrPixelConfig is expanded to encompass // alphatype is ignore for now, but if GrPixelConfig is expanded to encompass
// alpha info, that will be considered. // alpha info, that will be considered.
GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProfileType pt) { GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProfileType pt,
const GrCaps& caps) {
// We intentionally ignore profile type for non-8888 formats. Anything we can't support
// in hardware will be expanded to sRGB 8888 in GrUploadPixmapToTexture.
switch (ct) { switch (ct) {
case kUnknown_SkColorType: case kUnknown_SkColorType:
return kUnknown_GrPixelConfig; return kUnknown_GrPixelConfig;
@ -369,12 +396,11 @@ GrPixelConfig SkImageInfo2GrPixelConfig(SkColorType ct, SkAlphaType, SkColorProf
case kARGB_4444_SkColorType: case kARGB_4444_SkColorType:
return kRGBA_4444_GrPixelConfig; return kRGBA_4444_GrPixelConfig;
case kRGBA_8888_SkColorType: case kRGBA_8888_SkColorType:
//if (kSRGB_SkColorProfileType == pt) { return (kSRGB_SkColorProfileType == pt && caps.srgbSupport())
// return kSRGBA_8888_GrPixelConfig; ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
//}
return kRGBA_8888_GrPixelConfig;
case kBGRA_8888_SkColorType: case kBGRA_8888_SkColorType:
return kBGRA_8888_GrPixelConfig; return (kSRGB_SkColorProfileType == pt && caps.srgbSupport())
? kSBGRA_8888_GrPixelConfig : kBGRA_8888_GrPixelConfig;
case kIndex_8_SkColorType: case kIndex_8_SkColorType:
return kIndex_8_GrPixelConfig; return kIndex_8_GrPixelConfig;
case kGray_8_SkColorType: case kGray_8_SkColorType:
@ -413,6 +439,10 @@ bool GrPixelConfig2ColorAndProfileType(GrPixelConfig config, SkColorType* ctOut,
ct = kRGBA_8888_SkColorType; ct = kRGBA_8888_SkColorType;
pt = kSRGB_SkColorProfileType; pt = kSRGB_SkColorProfileType;
break; break;
case kSBGRA_8888_GrPixelConfig:
ct = kBGRA_8888_SkColorType;
pt = kSRGB_SkColorProfileType;
break;
default: default:
return false; return false;
} }

View File

@ -75,7 +75,7 @@ static SkGrPixelRef* copy_to_new_texture_pixelref(GrTexture* texture, SkColorTyp
srcRect = *subset; srcRect = *subset;
} }
desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fFlags = kRenderTarget_GrSurfaceFlag;
desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType, dstPT); desc.fConfig = SkImageInfo2GrPixelConfig(dstCT, kPremul_SkAlphaType, dstPT, *context->caps());
desc.fTextureStorageAllocator = texture->desc().fTextureStorageAllocator; desc.fTextureStorageAllocator = texture->desc().fTextureStorageAllocator;
desc.fIsMipMapped = false; desc.fIsMipMapped = false;

View File

@ -95,7 +95,7 @@ bool SkPaintToGrPaintWithTexture(GrContext* context,
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo&); GrSurfaceDesc GrImageInfoToSurfaceDesc(const SkImageInfo&, const GrCaps&);
bool GrPixelConfig2ColorAndProfileType(GrPixelConfig, SkColorType*, SkColorProfileType*); bool GrPixelConfig2ColorAndProfileType(GrPixelConfig, SkColorType*, SkColorProfileType*);

View File

@ -98,7 +98,7 @@ GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
const GrSwizzle& swizzle, const GrSwizzle& swizzle,
PMConversion pmConversion, PMConversion pmConversion,
const SkMatrix& matrix) const SkMatrix& matrix)
: INHERITED(texture, matrix) : INHERITED(texture, matrix, GrTextureParams::ClampNoFilterForceAllowSRGB())
, fSwizzle(swizzle) , fSwizzle(swizzle)
, fPMConversion(pmConversion) { , fPMConversion(pmConversion) {
this->initClassID<GrConfigConversionEffect>(); this->initClassID<GrConfigConversionEffect>();
@ -296,7 +296,8 @@ const GrFragmentProcessor* GrConfigConversionEffect::Create(GrTexture* texture,
// If we returned a GrConfigConversionEffect that was equivalent to a GrSimpleTextureEffect // If we returned a GrConfigConversionEffect that was equivalent to a GrSimpleTextureEffect
// then we may pollute our texture cache with redundant shaders. So in the case that no // then we may pollute our texture cache with redundant shaders. So in the case that no
// conversions were requested we instead return a GrSimpleTextureEffect. // conversions were requested we instead return a GrSimpleTextureEffect.
return GrSimpleTextureEffect::Create(texture, matrix); return GrSimpleTextureEffect::Create(texture, matrix,
GrTextureParams::ClampNoFilterForceAllowSRGB());
} else { } else {
if (kRGBA_8888_GrPixelConfig != texture->config() && if (kRGBA_8888_GrPixelConfig != texture->config() &&
kBGRA_8888_GrPixelConfig != texture->config() && kBGRA_8888_GrPixelConfig != texture->config() &&

View File

@ -158,7 +158,7 @@ int GrTextureStripAtlas::lockRow(const SkBitmap& data) {
// that is not currently in use // that is not currently in use
fTexture->writePixels(0, rowNumber * fDesc.fRowHeight, fTexture->writePixels(0, rowNumber * fDesc.fRowHeight,
fDesc.fWidth, fDesc.fRowHeight, fDesc.fWidth, fDesc.fRowHeight,
SkImageInfo2GrPixelConfig(data.info()), SkImageInfo2GrPixelConfig(data.info(), *this->getContext()->caps()),
data.getPixels(), data.getPixels(),
data.rowBytes(), data.rowBytes(),
GrContext::kDontFlush_PixelOpsFlag); GrContext::kDontFlush_PixelOpsFlag);

View File

@ -1435,27 +1435,31 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
} }
fConfigTable[kBGRA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA(); fConfigTable[kBGRA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
// We only enable srgb support if both textures and FBOs support srgb. // We only enable srgb support if both textures and FBOs support srgb,
bool srgbSupport = false; // *and* we can disable sRGB decode-on-read, to support "legacy" mode.
if (kGL_GrGLStandard == standard) { if (kGL_GrGLStandard == standard) {
if (ctxInfo.version() >= GR_GL_VER(3,0)) { if (ctxInfo.version() >= GR_GL_VER(3,0)) {
srgbSupport = true; fSRGBSupport = true;
} else if (ctxInfo.hasExtension("GL_EXT_texture_sRGB")) { } else if (ctxInfo.hasExtension("GL_EXT_texture_sRGB")) {
if (ctxInfo.hasExtension("GL_ARB_framebuffer_sRGB") || if (ctxInfo.hasExtension("GL_ARB_framebuffer_sRGB") ||
ctxInfo.hasExtension("GL_EXT_framebuffer_sRGB")) { ctxInfo.hasExtension("GL_EXT_framebuffer_sRGB")) {
srgbSupport = true; fSRGBSupport = true;
} }
} }
// All the above srgb extensions support toggling srgb writes // All the above srgb extensions support toggling srgb writes
fSRGBWriteControl = srgbSupport; fSRGBWriteControl = fSRGBSupport;
} else { } else {
// See https://bug.skia.org/4148 for PowerVR issue. // See https://bug.skia.org/4148 for PowerVR issue.
srgbSupport = kPowerVRRogue_GrGLRenderer != ctxInfo.renderer() && fSRGBSupport = kPowerVRRogue_GrGLRenderer != ctxInfo.renderer() &&
(ctxInfo.version() >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_sRGB")); (ctxInfo.version() >= GR_GL_VER(3,0) || ctxInfo.hasExtension("GL_EXT_sRGB"));
// ES through 3.1 requires EXT_srgb_write_control to support toggling // ES through 3.1 requires EXT_srgb_write_control to support toggling
// sRGB writing for destinations. // sRGB writing for destinations.
fSRGBWriteControl = ctxInfo.hasExtension("GL_EXT_sRGB_write_control"); fSRGBWriteControl = ctxInfo.hasExtension("GL_EXT_sRGB_write_control");
} }
if (!ctxInfo.hasExtension("GL_EXT_texture_sRGB_decode")) {
// To support "legacy" L32 mode, we require the ability to turn off sRGB decode:
fSRGBSupport = false;
}
fConfigTable[kSRGBA_8888_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_SRGB_ALPHA; fConfigTable[kSRGBA_8888_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_SRGB_ALPHA;
fConfigTable[kSRGBA_8888_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_SRGB8_ALPHA8; fConfigTable[kSRGBA_8888_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_SRGB8_ALPHA8;
// GL does not do srgb<->rgb conversions when transferring between cpu and gpu. Thus, the // GL does not do srgb<->rgb conversions when transferring between cpu and gpu. Thus, the
@ -1464,7 +1468,7 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
GR_GL_RGBA; GR_GL_RGBA;
fConfigTable[kSRGBA_8888_GrPixelConfig].fFormats.fExternalType = GR_GL_UNSIGNED_BYTE; fConfigTable[kSRGBA_8888_GrPixelConfig].fFormats.fExternalType = GR_GL_UNSIGNED_BYTE;
fConfigTable[kSRGBA_8888_GrPixelConfig].fFormatType = kNormalizedFixedPoint_FormatType; fConfigTable[kSRGBA_8888_GrPixelConfig].fFormatType = kNormalizedFixedPoint_FormatType;
if (srgbSupport) { if (fSRGBSupport) {
fConfigTable[kSRGBA_8888_GrPixelConfig].fFlags = ConfigInfo::kTextureable_Flag | fConfigTable[kSRGBA_8888_GrPixelConfig].fFlags = ConfigInfo::kTextureable_Flag |
allRenderFlags; allRenderFlags;
} }
@ -1473,6 +1477,26 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
} }
fConfigTable[kSRGBA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA(); fConfigTable[kSRGBA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
// sBGRA is not a "real" thing in OpenGL, but GPUs support it, and on platforms where
// kN32 == BGRA, we need some way to work with it. (The default framebuffer on Windows
// is in this format, for example).
fConfigTable[kSBGRA_8888_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_SRGB_ALPHA;
fConfigTable[kSBGRA_8888_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_SRGB8_ALPHA8;
// GL does not do srgb<->rgb conversions when transferring between cpu and gpu. Thus, the
// external format is GL_BGRA.
fConfigTable[kSBGRA_8888_GrPixelConfig].fFormats.fExternalFormat[kOther_ExternalFormatUsage] =
GR_GL_BGRA;
fConfigTable[kSBGRA_8888_GrPixelConfig].fFormats.fExternalType = GR_GL_UNSIGNED_BYTE;
fConfigTable[kSBGRA_8888_GrPixelConfig].fFormatType = kNormalizedFixedPoint_FormatType;
if (fSRGBSupport) {
fConfigTable[kSBGRA_8888_GrPixelConfig].fFlags = ConfigInfo::kTextureable_Flag |
allRenderFlags;
}
if (texStorageSupported) {
fConfigTable[kSBGRA_8888_GrPixelConfig].fFlags |= ConfigInfo::kCanUseTexStorage_Flag;
}
fConfigTable[kSBGRA_8888_GrPixelConfig].fSwizzle = GrSwizzle::RGBA();
fConfigTable[kRGB_565_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_RGB; fConfigTable[kRGB_565_GrPixelConfig].fFormats.fBaseInternalFormat = GR_GL_RGB;
if (this->ES2CompatibilitySupport()) { if (this->ES2CompatibilitySupport()) {
fConfigTable[kRGB_565_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_RGB565; fConfigTable[kRGB_565_GrPixelConfig].fFormats.fSizedInternalFormat = GR_GL_RGB565;
@ -1792,6 +1816,11 @@ void GrGLCaps::initConfigTable(const GrGLContextInfo& ctxInfo, const GrGLInterfa
if (ctxInfo.standard() == kGLES_GrGLStandard && ctxInfo.version() == GR_GL_VER(2,0)) { if (ctxInfo.standard() == kGLES_GrGLStandard && ctxInfo.version() == GR_GL_VER(2,0)) {
fConfigTable[kSRGBA_8888_GrPixelConfig].fFormats.fExternalFormat[kTexImage_ExternalFormatUsage] = fConfigTable[kSRGBA_8888_GrPixelConfig].fFormats.fExternalFormat[kTexImage_ExternalFormatUsage] =
GR_GL_SRGB_ALPHA; GR_GL_SRGB_ALPHA;
// Additionally, because we had to "invent" sBGRA, there is no way to make it work
// in ES 2.0, because there is no <internalFormat> we can use. So just make that format
// unsupported. (If we have no sRGB support at all, this will get overwritten below).
fConfigTable[kSBGRA_8888_GrPixelConfig].fFlags = 0;
} }
// If BGRA is supported as an internal format it must always be specified to glTex[Sub]Image // If BGRA is supported as an internal format it must always be specified to glTex[Sub]Image

View File

@ -120,12 +120,10 @@ public:
const GrGLInterface* glInterface); const GrGLInterface* glInterface);
bool isConfigTexturable(GrPixelConfig config) const override { bool isConfigTexturable(GrPixelConfig config) const override {
SkASSERT(kGrPixelConfigCnt > config);
return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kTextureable_Flag); return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kTextureable_Flag);
} }
bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override { bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override {
SkASSERT(kGrPixelConfigCnt > config);
if (withMSAA) { if (withMSAA) {
return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderableWithMSAA_Flag); return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kRenderableWithMSAA_Flag);
} else { } else {
@ -134,7 +132,6 @@ public:
} }
bool isConfigTexSupportEnabled(GrPixelConfig config) const { bool isConfigTexSupportEnabled(GrPixelConfig config) const {
SkASSERT(kGrPixelConfigCnt > config);
return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseTexStorage_Flag); return SkToBool(fConfigTable[config].fFlags & ConfigInfo::kCanUseTexStorage_Flag);
} }

View File

@ -506,12 +506,17 @@
/* TextureUsage */ /* TextureUsage */
#define GR_GL_FRAMEBUFFER_ATTACHMENT 0x93A3 #define GR_GL_FRAMEBUFFER_ATTACHMENT 0x93A3
/* TextureSRGBDecode */
#define GR_GL_DECODE_EXT 0x8A49
#define GR_GL_SKIP_DECODE_EXT 0x8A4A
/* TextureParameterName */ /* TextureParameterName */
#define GR_GL_TEXTURE_MAG_FILTER 0x2800 #define GR_GL_TEXTURE_MAG_FILTER 0x2800
#define GR_GL_TEXTURE_MIN_FILTER 0x2801 #define GR_GL_TEXTURE_MIN_FILTER 0x2801
#define GR_GL_TEXTURE_WRAP_S 0x2802 #define GR_GL_TEXTURE_WRAP_S 0x2802
#define GR_GL_TEXTURE_WRAP_T 0x2803 #define GR_GL_TEXTURE_WRAP_T 0x2803
#define GR_GL_TEXTURE_USAGE 0x93A2 #define GR_GL_TEXTURE_USAGE 0x93A2
#define GR_GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
/* TextureTarget */ /* TextureTarget */
/* GL_TEXTURE_2D */ /* GL_TEXTURE_2D */

View File

@ -898,6 +898,7 @@ static inline GrGLint config_alignment(GrPixelConfig config) {
case kRGBA_8888_GrPixelConfig: case kRGBA_8888_GrPixelConfig:
case kBGRA_8888_GrPixelConfig: case kBGRA_8888_GrPixelConfig:
case kSRGBA_8888_GrPixelConfig: case kSRGBA_8888_GrPixelConfig:
case kSBGRA_8888_GrPixelConfig:
case kRGBA_float_GrPixelConfig: case kRGBA_float_GrPixelConfig:
return 4; return 4;
default: default:
@ -2100,13 +2101,15 @@ bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcesso
SkSTArray<8, const GrTextureAccess*> textureAccesses; SkSTArray<8, const GrTextureAccess*> textureAccesses;
program->setData(primProc, pipeline, &textureAccesses); program->setData(primProc, pipeline, &textureAccesses);
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
bool allowSRGB = GrAllowSRGBForDestinationPixelConfig(glRT->config());
int numTextureAccesses = textureAccesses.count(); int numTextureAccesses = textureAccesses.count();
for (int i = 0; i < numTextureAccesses; i++) { for (int i = 0; i < numTextureAccesses; i++) {
this->bindTexture(i, textureAccesses[i]->getParams(), this->bindTexture(i, textureAccesses[i]->getParams(), allowSRGB,
static_cast<GrGLTexture*>(textureAccesses[i]->getTexture())); static_cast<GrGLTexture*>(textureAccesses[i]->getTexture()));
} }
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(pipeline.getRenderTarget());
this->flushStencil(pipeline.getStencil()); this->flushStencil(pipeline.getStencil());
this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin()); this->flushScissor(pipeline.getScissorState(), glRT->getViewport(), glRT->origin());
this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled()); this->flushHWAAState(glRT, pipeline.isHWAntialiasState(), !pipeline.getStencil().isDisabled());
@ -2607,6 +2610,16 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height,
tempDrawInfo->fSwizzle = GrSwizzle::BGRA(); tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig; tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
} else if (readConfig == kSBGRA_8888_GrPixelConfig &&
this->glCaps().isConfigRenderable(kSRGBA_8888_GrPixelConfig, false) &&
this->readPixelsSupported(kSRGBA_8888_GrPixelConfig, kSRGBA_8888_GrPixelConfig)) {
// We're trying to read sBGRA but it's not supported. If sRGBA is renderable and
// we can read it back, then do a swizzling draw to a sRGBA and read it back (which
// will effectively be sBGRA).
tempDrawInfo->fTempSurfaceDesc.fConfig = kSRGBA_8888_GrPixelConfig;
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
tempDrawInfo->fReadConfig = kSRGBA_8888_GrPixelConfig;
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
} else if (readConfig == kAlpha_8_GrPixelConfig) { } else if (readConfig == kAlpha_8_GrPixelConfig) {
// onReadPixels implements a fallback for cases where we are want to read kAlpha_8, // onReadPixels implements a fallback for cases where we are want to read kAlpha_8,
// it's unsupported, but 32bit RGBA reads are supported. // it's unsupported, but 32bit RGBA reads are supported.
@ -3311,7 +3324,8 @@ static void get_tex_param_swizzle(GrPixelConfig config,
} }
} }
void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture) { void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, bool dstConfigAllowsSRGB,
GrGLTexture* texture) {
SkASSERT(texture); SkASSERT(texture);
#ifdef SK_DEBUG #ifdef SK_DEBUG
@ -3347,6 +3361,19 @@ void GrGLGpu::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
bool setAll = timestamp < this->getResetTimestamp(); bool setAll = timestamp < this->getResetTimestamp();
GrGLTexture::TexParams newTexParams; GrGLTexture::TexParams newTexParams;
if (this->caps()->srgbSupport()) {
// By default, the decision to allow SRGB decode is based on the destination config.
// A texture can override that by specifying a value in GrTextureParams.
newTexParams.fSRGBDecode =
(dstConfigAllowsSRGB || GrTextureParams::kForceAllowSRGB_SRGBMode == params.srgbMode())
? GR_GL_DECODE_EXT : GR_GL_SKIP_DECODE_EXT;
if (setAll || newTexParams.fSRGBDecode != oldTexParams.fSRGBDecode) {
this->setTextureUnit(unitIdx);
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SRGB_DECODE_EXT, newTexParams.fSRGBDecode));
}
}
static GrGLenum glMinFilterModes[] = { static GrGLenum glMinFilterModes[] = {
GR_GL_NEAREST, GR_GL_NEAREST,
GR_GL_LINEAR, GR_GL_LINEAR,
@ -4014,7 +4041,7 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture()); GrGLTexture* srcTex = static_cast<GrGLTexture*>(src->asTexture());
GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode); GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
this->bindTexture(0, params, srcTex); this->bindTexture(0, params, true, srcTex);
GrGLIRect dstVP; GrGLIRect dstVP;
this->bindSurfaceFBOForCopy(dst, GR_GL_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget); this->bindSurfaceFBOForCopy(dst, GR_GL_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget);

View File

@ -59,7 +59,8 @@ public:
void discard(GrRenderTarget*) override; void discard(GrRenderTarget*) override;
// Used by GrGLProgram to configure OpenGL state. // Used by GrGLProgram to configure OpenGL state.
void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture); void bindTexture(int unitIdx, const GrTextureParams& params, bool dstConfigAllowsSRGB,
GrGLTexture* texture);
bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes, bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
GrPixelConfig readConfig, DrawPreference*, GrPixelConfig readConfig, DrawPreference*,

View File

@ -25,6 +25,7 @@ public:
GrGLenum fWrapT; GrGLenum fWrapT;
GrGLenum fMaxMipMapLevel; GrGLenum fMaxMipMapLevel;
GrGLenum fSwizzleRGBA[4]; GrGLenum fSwizzleRGBA[4];
GrGLenum fSRGBDecode;
void invalidate() { memset(this, 0xff, sizeof(TexParams)); } void invalidate() { memset(this, 0xff, sizeof(TexParams)); }
}; };

View File

@ -111,7 +111,8 @@ static void apply_premul(const SkImageInfo& info, void* pixels, size_t rowBytes)
bool SkImage_Gpu::onReadPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, bool SkImage_Gpu::onReadPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
int srcX, int srcY, CachingHint) const { int srcX, int srcY, CachingHint) const {
GrPixelConfig config = SkImageInfo2GrPixelConfig(info.colorType(), info.alphaType(), GrPixelConfig config = SkImageInfo2GrPixelConfig(info.colorType(), info.alphaType(),
info.profileType()); info.profileType(),
*fTexture->getContext()->caps());
uint32_t flags = 0; uint32_t flags = 0;
if (kUnpremul_SkAlphaType == info.alphaType() && kPremul_SkAlphaType == fAlphaType) { if (kUnpremul_SkAlphaType == info.alphaType() && kPremul_SkAlphaType == fAlphaType) {
// let the GPU perform this transformation for us // let the GPU perform this transformation for us

View File

@ -329,9 +329,13 @@ GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo,
// TODO: Query the actual framebuffer for sRGB capable. However, to // TODO: Query the actual framebuffer for sRGB capable. However, to
// preserve old (fake-linear) behavior, we don't do this. Instead, rely // preserve old (fake-linear) behavior, we don't do this. Instead, rely
// on the flag (currently driven via 'C' mode in SampleApp). // on the flag (currently driven via 'C' mode in SampleApp).
desc.fConfig = (info().profileType() == kSRGB_SkColorProfileType || //
// Also, we may not have real sRGB support (ANGLE, in particular), so check for
// that, and fall back to L32:
desc.fConfig = grContext->caps()->srgbSupport() &&
(info().profileType() == kSRGB_SkColorProfileType ||
info().colorType() == kRGBA_F16_SkColorType) info().colorType() == kRGBA_F16_SkColorType)
? kSRGBA_8888_GrPixelConfig // This may not be the right byte-order ? kSkiaGamma8888_GrPixelConfig
: kSkia8888_GrPixelConfig; : kSkia8888_GrPixelConfig;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin; desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
desc.fSampleCnt = attachmentInfo.fSampleCount; desc.fSampleCnt = attachmentInfo.fSampleCount;

View File

@ -424,7 +424,8 @@ static void test_readpixels_texture(skiatest::Reporter* reporter, GrTexture* tex
GrPixelConfig dstConfig = GrPixelConfig dstConfig =
SkImageInfo2GrPixelConfig(gReadPixelsConfigs[c].fColorType, SkImageInfo2GrPixelConfig(gReadPixelsConfigs[c].fColorType,
gReadPixelsConfigs[c].fAlphaType, gReadPixelsConfigs[c].fAlphaType,
kLinear_SkColorProfileType); kLinear_SkColorProfileType,
*texture->getContext()->caps());
uint32_t flags = 0; uint32_t flags = 0;
if (gReadPixelsConfigs[c].fAlphaType == kUnpremul_SkAlphaType) { if (gReadPixelsConfigs[c].fAlphaType == kUnpremul_SkAlphaType) {
flags = GrContext::kUnpremul_PixelOpsFlag; flags = GrContext::kUnpremul_PixelOpsFlag;