Introduce GrColorType
This begins the journey towards using different types to refer to CPU data and GPU texture formats. This is one part of removing GrPixelConfig and more directly using GL/VK texture formats GrColorType represents a particular layout of color/gray/alpha channels in CPU memory. It does not refer to texture formats or sRGB-encoding. It is basically SkColorType specialized to the GPU backend with some formats added and some removed. Read/WritePixel interfaces use GrColorType to describe the CPU side of the transaction. There's still a lot of punting to GrPixelConfig in API-specific code. There's a lot more to be done. Bug: 6718 Bug: 7580 Change-Id: I8d813ae9a4416a06596f22a4b87da02091989718 Reviewed-on: https://skia-review.googlesource.com/107264 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
adb4fcbbfd
commit
c320b15768
@ -9,9 +9,10 @@
|
||||
#define GrTypesPriv_DEFINED
|
||||
|
||||
#include <chrono>
|
||||
#include "GrTypes.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "GrSharedEnums.h"
|
||||
#include "GrTypes.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
class GrCaps;
|
||||
|
||||
@ -760,37 +761,6 @@ static constexpr GrPixelConfig kAlpha_half_as_Red_GrPixelConfig = kPrivateConfig
|
||||
static constexpr GrPixelConfig kGray_8_as_Lum_GrPixelConfig = kPrivateConfig4_GrPixelConfig;
|
||||
static constexpr GrPixelConfig kGray_8_as_Red_GrPixelConfig = kPrivateConfig5_GrPixelConfig;
|
||||
|
||||
/**
|
||||
* Utility functions for GrPixelConfig
|
||||
*/
|
||||
// Returns true if the pixel config is 32 bits per pixel
|
||||
static inline bool GrPixelConfigIs8888Unorm(GrPixelConfig config) {
|
||||
switch (config) {
|
||||
case kRGBA_8888_GrPixelConfig:
|
||||
case kBGRA_8888_GrPixelConfig:
|
||||
case kSRGBA_8888_GrPixelConfig:
|
||||
case kSBGRA_8888_GrPixelConfig:
|
||||
return true;
|
||||
case kUnknown_GrPixelConfig:
|
||||
case kAlpha_8_GrPixelConfig:
|
||||
case kAlpha_8_as_Alpha_GrPixelConfig:
|
||||
case kAlpha_8_as_Red_GrPixelConfig:
|
||||
case kGray_8_GrPixelConfig:
|
||||
case kGray_8_as_Lum_GrPixelConfig:
|
||||
case kGray_8_as_Red_GrPixelConfig:
|
||||
case kRGB_565_GrPixelConfig:
|
||||
case kRGBA_4444_GrPixelConfig:
|
||||
case kRGBA_float_GrPixelConfig:
|
||||
case kRG_float_GrPixelConfig:
|
||||
case kAlpha_half_GrPixelConfig:
|
||||
case kAlpha_half_as_Red_GrPixelConfig:
|
||||
case kRGBA_half_GrPixelConfig:
|
||||
return false;
|
||||
}
|
||||
SK_ABORT("Invalid pixel config");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refers to the encoding of a GPU buffer as it will be interpreted by the GPU when sampling and
|
||||
* blending.
|
||||
@ -806,6 +776,10 @@ enum class GrSRGBConversion {
|
||||
kLinearToSRGB,
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility functions for GrPixelConfig
|
||||
*/
|
||||
|
||||
// Returns whether the config's color channels are sRGB encoded.
|
||||
static inline GrSRGBEncoded GrPixelConfigIsSRGBEncoded(GrPixelConfig config) {
|
||||
switch (config) {
|
||||
@ -1045,6 +1019,215 @@ static inline GrPixelConfigIsClamped GrGetPixelConfigIsClamped(GrPixelConfig con
|
||||
: GrPixelConfigIsClamped::kYes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like SkColorType this describes a layout of pixel data in CPU memory. It specifies the channels,
|
||||
* their type, and width. This exists so that the GPU backend can have private types that have no
|
||||
* analog in the public facing SkColorType enum and omit types not implemented in the GPU backend.
|
||||
* It does not refer to a texture format and the mapping to texture formats may be many-to-many.
|
||||
* It does not specify the sRGB encding of the stored values.
|
||||
*/
|
||||
enum class GrColorType {
|
||||
kUnknown,
|
||||
kAlpha_8,
|
||||
kRGB_565,
|
||||
kABGR_4444, // This name differs from SkColorType. kARGB_4444_SkColorType is misnamed.
|
||||
kRGBA_8888,
|
||||
kBGRA_8888,
|
||||
kGray_8,
|
||||
kAlpha_F16,
|
||||
kRGBA_F16,
|
||||
kRG_F32,
|
||||
kRGBA_F32,
|
||||
};
|
||||
|
||||
static inline SkColorType GrColorTypeToSkColorType(GrColorType ct) {
|
||||
switch (ct) {
|
||||
case GrColorType::kUnknown: return kUnknown_SkColorType;
|
||||
case GrColorType::kAlpha_8: return kAlpha_8_SkColorType;
|
||||
case GrColorType::kRGB_565: return kRGB_565_SkColorType;
|
||||
case GrColorType::kABGR_4444: return kARGB_4444_SkColorType;
|
||||
case GrColorType::kRGBA_8888: return kRGBA_8888_SkColorType;
|
||||
case GrColorType::kBGRA_8888: return kBGRA_8888_SkColorType;
|
||||
case GrColorType::kGray_8: return kGray_8_SkColorType;
|
||||
case GrColorType::kAlpha_F16: return kUnknown_SkColorType;
|
||||
case GrColorType::kRGBA_F16: return kRGBA_F16_SkColorType;
|
||||
case GrColorType::kRG_F32: return kUnknown_SkColorType;
|
||||
case GrColorType::kRGBA_F32: return kUnknown_SkColorType;
|
||||
}
|
||||
SK_ABORT("Invalid GrColorType");
|
||||
return kUnknown_SkColorType;
|
||||
}
|
||||
|
||||
static inline GrColorType SkColorTypeToGrColorType(SkColorType ct) {
|
||||
switch (ct) {
|
||||
case kUnknown_SkColorType: return GrColorType::kUnknown;
|
||||
case kAlpha_8_SkColorType: return GrColorType::kAlpha_8;
|
||||
case kRGB_565_SkColorType: return GrColorType::kRGB_565;
|
||||
case kARGB_4444_SkColorType: return GrColorType::kABGR_4444;
|
||||
case kRGBA_8888_SkColorType: return GrColorType::kRGBA_8888;
|
||||
case kBGRA_8888_SkColorType: return GrColorType::kBGRA_8888;
|
||||
case kRGB_888x_SkColorType: return GrColorType::kUnknown;
|
||||
case kGray_8_SkColorType: return GrColorType::kGray_8;
|
||||
case kRGBA_F16_SkColorType: return GrColorType::kRGBA_F16;
|
||||
case kRGBA_1010102_SkColorType: return GrColorType::kUnknown;
|
||||
case kRGB_101010x_SkColorType: return GrColorType::kUnknown;
|
||||
}
|
||||
SK_ABORT("Invalid SkColorType");
|
||||
return GrColorType::kUnknown;
|
||||
}
|
||||
|
||||
static inline int GrColorTypeBytesPerPixel(GrColorType ct) {
|
||||
switch (ct) {
|
||||
case GrColorType::kUnknown: return 0;
|
||||
case GrColorType::kAlpha_8: return 1;
|
||||
case GrColorType::kRGB_565: return 2;
|
||||
case GrColorType::kABGR_4444: return 2;
|
||||
case GrColorType::kRGBA_8888: return 4;
|
||||
case GrColorType::kBGRA_8888: return 4;
|
||||
case GrColorType::kGray_8: return 1;
|
||||
case GrColorType::kAlpha_F16: return 2;
|
||||
case GrColorType::kRGBA_F16: return 8;
|
||||
case GrColorType::kRG_F32: return 8;
|
||||
case GrColorType::kRGBA_F32: return 16;
|
||||
}
|
||||
SK_ABORT("Invalid GrColorType");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int GrColorTypeIsAlphaOnly(GrColorType ct) {
|
||||
switch (ct) {
|
||||
case GrColorType::kUnknown: return false;
|
||||
case GrColorType::kAlpha_8: return true;
|
||||
case GrColorType::kRGB_565: return false;
|
||||
case GrColorType::kABGR_4444: return false;
|
||||
case GrColorType::kRGBA_8888: return false;
|
||||
case GrColorType::kBGRA_8888: return false;
|
||||
case GrColorType::kGray_8: return false;
|
||||
case GrColorType::kAlpha_F16: return true;
|
||||
case GrColorType::kRGBA_F16: return false;
|
||||
case GrColorType::kRG_F32: return false;
|
||||
case GrColorType::kRGBA_F32: return false;
|
||||
}
|
||||
SK_ABORT("Invalid GrColorType");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline GrColorType GrPixelConfigToColorTypeAndEncoding(GrPixelConfig config,
|
||||
GrSRGBEncoded* srgbEncoded) {
|
||||
SkASSERT(srgbEncoded);
|
||||
switch (config) {
|
||||
case kUnknown_GrPixelConfig:
|
||||
return GrColorType::kUnknown;
|
||||
case kAlpha_8_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kAlpha_8;
|
||||
case kGray_8_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kGray_8;
|
||||
case kRGB_565_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kRGB_565;
|
||||
case kRGBA_4444_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kABGR_4444;
|
||||
case kRGBA_8888_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kRGBA_8888;
|
||||
case kBGRA_8888_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kBGRA_8888;
|
||||
case kSRGBA_8888_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kYes;
|
||||
return GrColorType::kRGBA_8888;
|
||||
case kSBGRA_8888_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kYes;
|
||||
return GrColorType::kBGRA_8888;
|
||||
case kRGBA_float_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kRGBA_F32;
|
||||
case kRG_float_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kRG_F32;
|
||||
case kAlpha_half_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kAlpha_F16;
|
||||
case kRGBA_half_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kRGBA_F16;
|
||||
case kAlpha_8_as_Alpha_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kAlpha_8;
|
||||
case kAlpha_8_as_Red_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kAlpha_8;
|
||||
case kAlpha_half_as_Red_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kAlpha_F16;
|
||||
case kGray_8_as_Lum_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kGray_8;
|
||||
case kGray_8_as_Red_GrPixelConfig:
|
||||
*srgbEncoded = GrSRGBEncoded::kNo;
|
||||
return GrColorType::kGray_8;
|
||||
}
|
||||
SK_ABORT("Invalid GrPixelConfig");
|
||||
return GrColorType::kUnknown;
|
||||
}
|
||||
|
||||
static inline GrColorType GrPixelConfigToColorType(GrPixelConfig config) {
|
||||
GrSRGBEncoded bogusEncoded;
|
||||
return GrPixelConfigToColorTypeAndEncoding(config, &bogusEncoded);
|
||||
}
|
||||
|
||||
static inline GrPixelConfig GrColorTypeToPixelConfig(GrColorType config,
|
||||
GrSRGBEncoded srgbEncoded) {
|
||||
switch (config) {
|
||||
case GrColorType::kUnknown:
|
||||
return kUnknown_GrPixelConfig;
|
||||
case GrColorType::kAlpha_8:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
|
||||
: kAlpha_8_GrPixelConfig;
|
||||
|
||||
case GrColorType::kGray_8:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
|
||||
: kGray_8_GrPixelConfig;
|
||||
|
||||
case GrColorType::kRGB_565:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
|
||||
: kRGB_565_GrPixelConfig;
|
||||
|
||||
case GrColorType::kABGR_4444:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
|
||||
: kRGBA_4444_GrPixelConfig;
|
||||
|
||||
case GrColorType::kRGBA_8888:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kSRGBA_8888_GrPixelConfig
|
||||
: kRGBA_8888_GrPixelConfig;
|
||||
|
||||
case GrColorType::kBGRA_8888:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kSBGRA_8888_GrPixelConfig
|
||||
: kBGRA_8888_GrPixelConfig;
|
||||
|
||||
case GrColorType::kRGBA_F32:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
|
||||
: kRGBA_float_GrPixelConfig;
|
||||
|
||||
case GrColorType::kRG_F32:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
|
||||
: kRG_float_GrPixelConfig;
|
||||
|
||||
case GrColorType::kAlpha_F16:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
|
||||
: kAlpha_half_GrPixelConfig;
|
||||
|
||||
case GrColorType::kRGBA_F16:
|
||||
return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig
|
||||
: kRGBA_half_GrPixelConfig;
|
||||
}
|
||||
SK_ABORT("Invalid GrColorType");
|
||||
return kUnknown_GrPixelConfig;
|
||||
}
|
||||
|
||||
class GrReleaseProcHelper : public SkRefCnt {
|
||||
public:
|
||||
// These match the definitions in SkImage, from whence they came
|
||||
|
@ -95,8 +95,8 @@ void SkInternalAtlasTextContext::flush() {
|
||||
}
|
||||
GrDeferredTextureUploadWritePixelsFn writePixelsFn =
|
||||
[this](GrTextureProxy* proxy, int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* data, size_t rowBytes) -> bool {
|
||||
SkASSERT(kAlpha_8_GrPixelConfig == config);
|
||||
GrColorType colorType, const void* data, size_t rowBytes) -> bool {
|
||||
SkASSERT(GrColorType::kAlpha_8 == colorType);
|
||||
SkASSERT(proxy == this->fDistanceFieldAtlas.fProxy);
|
||||
void* handle = fDistanceFieldAtlas.fTextureHandle;
|
||||
this->fRenderer->setTextureData(handle, data, left, top, width, height, rowBytes);
|
||||
|
@ -506,12 +506,10 @@ void GrContextPriv::flush(GrSurfaceProxy* proxy) {
|
||||
fContext->fDrawingManager->flush(proxy);
|
||||
}
|
||||
|
||||
bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
|
||||
bool sw_convert_to_premul(GrColorType srcColorType, int width, int height, size_t inRowBytes,
|
||||
const void* inPixels, size_t outRowBytes, void* outPixels) {
|
||||
SkColorType colorType;
|
||||
if (!GrPixelConfigToColorType(srcConfig, &colorType) ||
|
||||
4 != SkColorTypeBytesPerPixel(colorType))
|
||||
{
|
||||
SkColorType colorType = GrColorTypeToSkColorType(srcColorType);
|
||||
if (kUnknown_SkColorType == colorType || 4 != SkColorTypeBytesPerPixel(colorType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -524,45 +522,90 @@ bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: This will be removed when GrSurfaceContexts are aware of their color types.
|
||||
// (skbug.com/6718)
|
||||
static bool valid_premul_config(GrPixelConfig config) {
|
||||
return GrPixelConfigIs8888Unorm(config) || kRGBA_half_GrPixelConfig == config;
|
||||
switch (config) {
|
||||
case kUnknown_GrPixelConfig: return false;
|
||||
case kAlpha_8_GrPixelConfig: return false;
|
||||
case kGray_8_GrPixelConfig: return false;
|
||||
case kRGB_565_GrPixelConfig: return false;
|
||||
case kRGBA_4444_GrPixelConfig: return true;
|
||||
case kRGBA_8888_GrPixelConfig: return true;
|
||||
case kBGRA_8888_GrPixelConfig: return true;
|
||||
case kSRGBA_8888_GrPixelConfig: return true;
|
||||
case kSBGRA_8888_GrPixelConfig: return true;
|
||||
case kRGBA_float_GrPixelConfig: return true;
|
||||
case kRG_float_GrPixelConfig: return false;
|
||||
case kAlpha_half_GrPixelConfig: return false;
|
||||
case kRGBA_half_GrPixelConfig: return true;
|
||||
case kAlpha_8_as_Alpha_GrPixelConfig: return false;
|
||||
case kAlpha_8_as_Red_GrPixelConfig: return false;
|
||||
case kAlpha_half_as_Red_GrPixelConfig: return false;
|
||||
case kGray_8_as_Lum_GrPixelConfig: return false;
|
||||
case kGray_8_as_Red_GrPixelConfig: return false;
|
||||
}
|
||||
SK_ABORT("Invalid GrPixelConfig");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool valid_pixel_conversion(GrPixelConfig srcConfig, GrPixelConfig dstConfig,
|
||||
static bool valid_premul_color_type(GrColorType ct) {
|
||||
switch (ct) {
|
||||
case GrColorType::kUnknown: return false;
|
||||
case GrColorType::kAlpha_8: return false;
|
||||
case GrColorType::kRGB_565: return false;
|
||||
case GrColorType::kABGR_4444: return true;
|
||||
case GrColorType::kRGBA_8888: return true;
|
||||
case GrColorType::kBGRA_8888: return true;
|
||||
case GrColorType::kGray_8: return false;
|
||||
case GrColorType::kAlpha_F16: return false;
|
||||
case GrColorType::kRGBA_F16: return true;
|
||||
case GrColorType::kRG_F32: return false;
|
||||
case GrColorType::kRGBA_F32: return true;
|
||||
}
|
||||
SK_ABORT("Invalid GrColorType");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool valid_pixel_conversion(GrColorType cpuColorType, GrPixelConfig gpuConfig,
|
||||
bool premulConversion) {
|
||||
// We only allow premul <-> unpremul conversions for some formats
|
||||
if (premulConversion && (!valid_premul_config(srcConfig) || !valid_premul_config(dstConfig))) {
|
||||
if (premulConversion &&
|
||||
(!valid_premul_color_type(cpuColorType) || !valid_premul_config(gpuConfig))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pm_upm_must_round_trip(GrPixelConfig config, SkColorSpace* colorSpace) {
|
||||
return !colorSpace &&
|
||||
(kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config);
|
||||
static bool pm_upm_must_round_trip(GrColorType cpuColorType, const SkColorSpace* cpuColorSpace) {
|
||||
return !cpuColorSpace &&
|
||||
(GrColorType::kRGBA_8888 == cpuColorType || GrColorType::kBGRA_8888 == cpuColorType);
|
||||
}
|
||||
|
||||
static GrSRGBConversion determine_write_pixels_srgb_conversion(
|
||||
GrPixelConfig srcConfig,
|
||||
const SkColorSpace* srcColorSpace,
|
||||
GrSRGBEncoded dstSRGBEncoded,
|
||||
const SkColorSpace* dstColorSpace) {
|
||||
// TODO: This will be removed when GrSurfaceContexts are aware of their color types.
|
||||
// (skbug.com/6718)
|
||||
static bool pm_upm_must_round_trip(GrPixelConfig surfaceConfig,
|
||||
const SkColorSpace* surfaceColorSpace) {
|
||||
return !surfaceColorSpace &&
|
||||
(kRGBA_8888_GrPixelConfig == surfaceConfig || kBGRA_8888_GrPixelConfig == surfaceConfig);
|
||||
}
|
||||
|
||||
static GrSRGBConversion determine_write_pixels_srgb_conversion(GrColorType srcColorType,
|
||||
const SkColorSpace* srcColorSpace,
|
||||
GrSRGBEncoded dstSRGBEncoded,
|
||||
const SkColorSpace* dstColorSpace,
|
||||
const GrCaps& caps) {
|
||||
// No support for sRGB-encoded alpha.
|
||||
if (GrPixelConfigIsAlphaOnly(srcConfig)) {
|
||||
if (GrColorTypeIsAlphaOnly(srcColorType)) {
|
||||
return GrSRGBConversion::kNone;
|
||||
}
|
||||
// When the destination has no color space or it has a ~sRGB gamma but isn't sRGB encoded
|
||||
// (because of caps) then we act in "legacy" mode where no conversions are performed.
|
||||
if (!dstColorSpace ||
|
||||
(dstColorSpace->gammaCloseToSRGB() && GrSRGBEncoded::kNo == dstSRGBEncoded)) {
|
||||
// No conversions without GPU support for sRGB. (Legacy mode)
|
||||
if (!caps.srgbSupport()) {
|
||||
return GrSRGBConversion::kNone;
|
||||
}
|
||||
// Similarly, if the src was sRGB gamma and 8888 but we didn't choose a sRGB config we must be
|
||||
// in legacy mode. For now, anyway.
|
||||
if (srcColorSpace && srcColorSpace->gammaCloseToSRGB() &&
|
||||
GrSRGBEncoded::kNo == GrPixelConfigIsSRGBEncoded(srcConfig) &&
|
||||
GrPixelConfigIs8888Unorm(srcConfig)) {
|
||||
// If the GrSurfaceContext has no color space then it is in legacy mode.
|
||||
if (!dstColorSpace) {
|
||||
return GrSRGBConversion::kNone;
|
||||
}
|
||||
|
||||
@ -571,28 +614,24 @@ static GrSRGBConversion determine_write_pixels_srgb_conversion(
|
||||
|
||||
// For now we are assuming that if color space of the dst does not have sRGB gamma then the
|
||||
// texture format is not sRGB encoded and vice versa. Note that we already checked for "legacy"
|
||||
// mode being forced on by caps above. This may change in the future.
|
||||
// mode being forced on by caps above. This may change in the future. We will then have to
|
||||
// perform shader based conversions.
|
||||
SkASSERT(dstColorSpaceIsSRGB == (GrSRGBEncoded::kYes == dstSRGBEncoded));
|
||||
|
||||
// Similarly we are assuming that if the color space of the src does not have sRGB gamma then
|
||||
// the CPU pixels don't have a sRGB pixel config. This will become moot soon as we will not
|
||||
// be using GrPixelConfig to describe CPU pixel allocations.
|
||||
SkASSERT(srcColorSpaceIsSRGB == GrPixelConfigIsSRGB(srcConfig));
|
||||
|
||||
if (srcColorSpaceIsSRGB == dstColorSpaceIsSRGB) {
|
||||
return GrSRGBConversion::kNone;
|
||||
}
|
||||
return srcColorSpaceIsSRGB ? GrSRGBConversion::kSRGBToLinear : GrSRGBConversion::kLinearToSRGB;
|
||||
}
|
||||
|
||||
static GrSRGBConversion determine_read_pixels_srgb_conversion(
|
||||
GrSRGBEncoded srcSRGBEncoded,
|
||||
const SkColorSpace* srcColorSpace,
|
||||
GrPixelConfig dstConfig,
|
||||
const SkColorSpace* dstColorSpace) {
|
||||
static GrSRGBConversion determine_read_pixels_srgb_conversion(GrSRGBEncoded srcSRGBEncoded,
|
||||
const SkColorSpace* srcColorSpace,
|
||||
GrColorType dstColorType,
|
||||
const SkColorSpace* dstColorSpace,
|
||||
const GrCaps& caps) {
|
||||
// This is symmetrical with the write version.
|
||||
switch (determine_write_pixels_srgb_conversion(dstConfig, dstColorSpace, srcSRGBEncoded,
|
||||
srcColorSpace)) {
|
||||
switch (determine_write_pixels_srgb_conversion(dstColorType, dstColorSpace, srcSRGBEncoded,
|
||||
srcColorSpace, caps)) {
|
||||
case GrSRGBConversion::kNone: return GrSRGBConversion::kNone;
|
||||
case GrSRGBConversion::kLinearToSRGB: return GrSRGBConversion::kSRGBToLinear;
|
||||
case GrSRGBConversion::kSRGBToLinear: return GrSRGBConversion::kLinearToSRGB;
|
||||
@ -600,11 +639,10 @@ static GrSRGBConversion determine_read_pixels_srgb_conversion(
|
||||
return GrSRGBConversion::kNone;
|
||||
}
|
||||
|
||||
bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig srcConfig, SkColorSpace* srcColorSpace,
|
||||
const void* buffer, size_t rowBytes,
|
||||
uint32_t pixelOpsFlags) {
|
||||
bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width,
|
||||
int height, GrColorType srcColorType,
|
||||
SkColorSpace* srcColorSpace, const void* buffer,
|
||||
size_t rowBytes, uint32_t pixelOpsFlags) {
|
||||
// TODO: Color space conversion
|
||||
|
||||
ASSERT_SINGLE_OWNER_PRIV
|
||||
@ -622,14 +660,15 @@ bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
|
||||
|
||||
// The src is unpremul but the dst is premul -> premul the src before or as part of the write
|
||||
const bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
|
||||
if (!valid_pixel_conversion(srcConfig, dstProxy->config(), premul)) {
|
||||
|
||||
if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need to guarantee round-trip conversion if we are reading and writing 8888 non-sRGB data,
|
||||
// without any color spaces attached, and the caller wants us to premul.
|
||||
bool useConfigConversionEffect =
|
||||
premul && pm_upm_must_round_trip(srcConfig, srcColorSpace) &&
|
||||
premul && pm_upm_must_round_trip(srcColorType, srcColorSpace) &&
|
||||
pm_upm_must_round_trip(dstProxy->config(), dst->colorSpaceInfo().colorSpace());
|
||||
|
||||
// Are we going to try to premul as part of a draw? For the non-legacy case, we always allow
|
||||
@ -640,8 +679,8 @@ bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
|
||||
// Trim the params here so that if we wind up making a temporary surface it can be as small as
|
||||
// necessary and because GrGpu::getWritePixelsInfo requires it.
|
||||
if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(),
|
||||
GrBytesPerPixel(srcConfig), &left, &top, &width,
|
||||
&height, &buffer, &rowBytes)) {
|
||||
GrColorTypeBytesPerPixel(srcColorType), &left, &top,
|
||||
&width, &height, &buffer, &rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -649,10 +688,10 @@ bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
|
||||
: GrGpu::kNoDraw_DrawPreference;
|
||||
GrGpu::WritePixelTempDrawInfo tempDrawInfo;
|
||||
GrSRGBConversion srgbConversion = determine_write_pixels_srgb_conversion(
|
||||
srcConfig, srcColorSpace, GrPixelConfigIsSRGBEncoded(dstProxy->config()),
|
||||
dst->colorSpaceInfo().colorSpace());
|
||||
srcColorType, srcColorSpace, GrPixelConfigIsSRGBEncoded(dstProxy->config()),
|
||||
dst->colorSpaceInfo().colorSpace(), *fContext->caps());
|
||||
if (!fContext->fGpu->getWritePixelsInfo(dstSurface, dstProxy->origin(), width, height,
|
||||
srcConfig, srgbConversion, &drawPreference,
|
||||
srcColorType, srgbConversion, &drawPreference,
|
||||
&tempDrawInfo)) {
|
||||
return false;
|
||||
}
|
||||
@ -678,7 +717,7 @@ bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
|
||||
if (premul && (!tempProxy || !premulOnGpu)) {
|
||||
size_t tmpRowBytes = 4 * width;
|
||||
tmpPixels.reset(width * height);
|
||||
if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
|
||||
if (!sw_convert_to_premul(srcColorType, width, height, rowBytes, buffer, tmpRowBytes,
|
||||
tmpPixels.get())) {
|
||||
return false;
|
||||
}
|
||||
@ -706,7 +745,7 @@ bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
|
||||
}
|
||||
|
||||
if (!fContext->fGpu->writePixels(texture, tempProxy->origin(), 0, 0, width, height,
|
||||
tempDrawInfo.fWriteConfig, buffer, rowBytes)) {
|
||||
tempDrawInfo.fWriteColorType, buffer, rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
tempProxy = nullptr;
|
||||
@ -730,16 +769,16 @@ bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
|
||||
this->flushSurfaceWrites(renderTargetContext->asRenderTargetProxy());
|
||||
}
|
||||
} else {
|
||||
return fContext->fGpu->writePixels(dstSurface, dstProxy->origin(), left, top, width,
|
||||
height, srcConfig, buffer, rowBytes);
|
||||
return fContext->fGpu->writePixels(dstSurface, dstProxy->origin(), left, top, width, height,
|
||||
srcColorType, buffer, rowBytes);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dstConfig, SkColorSpace* dstColorSpace,
|
||||
void* buffer, size_t rowBytes, uint32_t flags) {
|
||||
bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width,
|
||||
int height, GrColorType dstColorType,
|
||||
SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes,
|
||||
uint32_t flags) {
|
||||
// TODO: Color space conversion
|
||||
|
||||
ASSERT_SINGLE_OWNER_PRIV
|
||||
@ -758,7 +797,8 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src,
|
||||
|
||||
// The src is premul but the dst is unpremul -> unpremul the src after or as part of the read
|
||||
bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
|
||||
if (!valid_pixel_conversion(srcProxy->config(), dstConfig, unpremul)) {
|
||||
|
||||
if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -767,7 +807,7 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src,
|
||||
bool useConfigConversionEffect =
|
||||
unpremul &&
|
||||
pm_upm_must_round_trip(srcProxy->config(), src->colorSpaceInfo().colorSpace()) &&
|
||||
pm_upm_must_round_trip(dstConfig, dstColorSpace);
|
||||
pm_upm_must_round_trip(dstColorType, dstColorSpace);
|
||||
|
||||
// Are we going to try to unpremul as part of a draw? For the non-legacy case, we always allow
|
||||
// this. GrConfigConversionEffect fails on some GPUs, so only allow this if it works perfectly.
|
||||
@ -777,8 +817,8 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src,
|
||||
// Adjust the params so that if we wind up using an intermediate surface we've already done
|
||||
// all the trimming and the temporary can be the min size required.
|
||||
if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(),
|
||||
GrBytesPerPixel(dstConfig), &left,
|
||||
&top, &width, &height, &buffer, &rowBytes)) {
|
||||
GrColorTypeBytesPerPixel(dstColorType), &left, &top,
|
||||
&width, &height, &buffer, &rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -787,9 +827,10 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src,
|
||||
GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
|
||||
GrSRGBConversion srgbConversion = determine_read_pixels_srgb_conversion(
|
||||
GrPixelConfigIsSRGBEncoded(srcProxy->config()), src->colorSpaceInfo().colorSpace(),
|
||||
dstConfig, dstColorSpace);
|
||||
dstColorType, dstColorSpace, *fContext->caps());
|
||||
|
||||
if (!fContext->fGpu->getReadPixelsInfo(srcSurface, srcProxy->origin(), width, height, rowBytes,
|
||||
dstConfig, srgbConversion, &drawPreference,
|
||||
dstColorType, srgbConversion, &drawPreference,
|
||||
&tempDrawInfo)) {
|
||||
return false;
|
||||
}
|
||||
@ -861,10 +902,10 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src,
|
||||
if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
|
||||
return false;
|
||||
}
|
||||
GrPixelConfig configToRead = dstConfig;
|
||||
GrColorType colorTypeToRead = dstColorType;
|
||||
if (didTempDraw) {
|
||||
this->flushSurfaceWrites(proxyToRead.get());
|
||||
configToRead = tempDrawInfo.fReadConfig;
|
||||
colorTypeToRead = tempDrawInfo.fReadColorType;
|
||||
}
|
||||
|
||||
if (!proxyToRead->instantiate(this->resourceProvider())) {
|
||||
@ -873,17 +914,15 @@ bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src,
|
||||
|
||||
GrSurface* surfaceToRead = proxyToRead->priv().peekSurface();
|
||||
|
||||
if (!fContext->fGpu->readPixels(surfaceToRead, proxyToRead->origin(),
|
||||
left, top, width, height, configToRead, buffer, rowBytes)) {
|
||||
if (!fContext->fGpu->readPixels(surfaceToRead, proxyToRead->origin(), left, top, width, height,
|
||||
colorTypeToRead, buffer, rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Perform umpremul conversion if we weren't able to perform it as a draw.
|
||||
if (unpremul) {
|
||||
SkColorType colorType;
|
||||
if (!GrPixelConfigToColorType(dstConfig, &colorType) ||
|
||||
4 != SkColorTypeBytesPerPixel(colorType))
|
||||
{
|
||||
SkColorType colorType = GrColorTypeToSkColorType(dstColorType);
|
||||
if (kUnknown_SkColorType == colorType || 4 != SkColorTypeBytesPerPixel(colorType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -142,11 +142,9 @@ public:
|
||||
* @return true if the read succeeded, false if not. The read can fail because of an unsupported
|
||||
* pixel configs
|
||||
*/
|
||||
bool readSurfacePixels(GrSurfaceContext* src,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dstConfig, SkColorSpace* dstColorSpace, void* buffer,
|
||||
size_t rowBytes = 0,
|
||||
uint32_t pixelOpsFlags = 0);
|
||||
bool readSurfacePixels(GrSurfaceContext* src, int left, int top, int width, int height,
|
||||
GrColorType dstColorType, SkColorSpace* dstColorSpace, void* buffer,
|
||||
size_t rowBytes = 0, uint32_t pixelOpsFlags = 0);
|
||||
|
||||
/**
|
||||
* Writes a rectangle of pixels to a surface.
|
||||
@ -164,11 +162,9 @@ public:
|
||||
* @return true if the write succeeded, false if not. The write can fail because of an
|
||||
* unsupported combination of surface and src configs.
|
||||
*/
|
||||
bool writeSurfacePixels(GrSurfaceContext* dst,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig srcConfig, SkColorSpace* srcColorSpace, const void* buffer,
|
||||
size_t rowBytes,
|
||||
uint32_t pixelOpsFlags = 0);
|
||||
bool writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width, int height,
|
||||
GrColorType srcColorType, SkColorSpace* srcColorSpace,
|
||||
const void* buffer, size_t rowBytes, uint32_t pixelOpsFlags = 0);
|
||||
|
||||
GrBackend getBackend() const { return fContext->fBackend; }
|
||||
|
||||
|
@ -55,11 +55,12 @@ public:
|
||||
|
||||
auto uploadMask = [this, proxy](GrDeferredTextureUploadWritePixelsFn& writePixelsFn) {
|
||||
this->wait();
|
||||
GrColorType pixelColorType = SkColorTypeToGrColorType(this->fPixels.info().colorType());
|
||||
// If the worker thread was unable to allocate pixels, this check will fail, and we'll
|
||||
// end up drawing with an uninitialized mask texture, but at least we won't crash.
|
||||
if (this->fPixels.addr()) {
|
||||
writePixelsFn(proxy, 0, 0, this->fPixels.width(), this->fPixels.height(),
|
||||
proxy->config(), this->fPixels.addr(), this->fPixels.rowBytes());
|
||||
pixelColorType, this->fPixels.addr(), this->fPixels.rowBytes());
|
||||
}
|
||||
// Upload has finished, so tell the proxy to release this GrDeferredProxyUploader
|
||||
proxy->texPriv().resetDeferredUploader();
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include "GrTypes.h"
|
||||
#include "GrTypesPriv.h"
|
||||
|
||||
class GrTextureProxy;
|
||||
|
||||
@ -115,7 +116,7 @@ private:
|
||||
*/
|
||||
using GrDeferredTextureUploadWritePixelsFn =
|
||||
std::function<bool(GrTextureProxy*, int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer, size_t rowBytes)>;
|
||||
GrColorType colorType, const void* buffer, size_t rowBytes)>;
|
||||
|
||||
/**
|
||||
* A deferred texture upload is simply a std::function that takes a
|
||||
|
@ -138,8 +138,10 @@ void GrDrawOpAtlas::Plot::uploadToTexture(GrDeferredTextureUploadWritePixelsFn&
|
||||
const unsigned char* dataPtr = fData;
|
||||
dataPtr += rowBytes * fDirtyRect.fTop;
|
||||
dataPtr += fBytesPerPixel * fDirtyRect.fLeft;
|
||||
// TODO: Make GrDrawOpAtlas store a GrColorType rather than GrPixelConfig.
|
||||
auto colorType = GrPixelConfigToColorType(fConfig);
|
||||
writePixels(proxy, fOffset.fX + fDirtyRect.fLeft, fOffset.fY + fDirtyRect.fTop,
|
||||
fDirtyRect.width(), fDirtyRect.height(), fConfig, dataPtr, rowBytes);
|
||||
fDirtyRect.width(), fDirtyRect.height(), colorType, dataPtr, rowBytes);
|
||||
fDirtyRect.setEmpty();
|
||||
SkDEBUGCODE(fDirty = false;)
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ bool GrGpu::copySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
}
|
||||
|
||||
bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin, int width,
|
||||
int height, size_t rowBytes, GrPixelConfig dstConfig,
|
||||
int height, size_t rowBytes, GrColorType dstColorType,
|
||||
GrSRGBConversion srgbConversion, DrawPreference* drawPreference,
|
||||
ReadPixelTempDrawInfo* tempDrawInfo) {
|
||||
SkASSERT(drawPreference);
|
||||
@ -201,43 +201,38 @@ bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
|
||||
SkASSERT(srcSurface);
|
||||
SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
|
||||
|
||||
// Default values for intermediate draws. The intermediate texture config matches the dst's
|
||||
// config, is approx sized to the read rect, no swizzling or spoofing of the dst config.
|
||||
tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
|
||||
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
|
||||
tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
|
||||
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstConfig;
|
||||
tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
|
||||
tempDrawInfo->fReadConfig = dstConfig;
|
||||
|
||||
// We currently do not support reading into the packed formats 565 or 4444 as they are not
|
||||
// required to have read back support on all devices and backends.
|
||||
if (kRGB_565_GrPixelConfig == dstConfig || kRGBA_4444_GrPixelConfig == dstConfig) {
|
||||
if (GrColorType::kRGB_565 == dstColorType || GrColorType::kABGR_4444 == dstColorType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrPixelConfig tempSurfaceConfig = kUnknown_GrPixelConfig;
|
||||
// GrGpu::readPixels doesn't do any sRGB conversions, so we must draw if there is one.
|
||||
switch (srgbConversion) {
|
||||
case GrSRGBConversion::kNone:
|
||||
// We support reading from RGBA to just A. In that case there is no sRGB version of the
|
||||
// dst format but we still want to succeed.
|
||||
if (GrColorTypeIsAlphaOnly(dstColorType)) {
|
||||
tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kNo);
|
||||
} else {
|
||||
tempSurfaceConfig = GrColorTypeToPixelConfig(
|
||||
dstColorType, GrPixelConfigIsSRGBEncoded(srcSurface->config()));
|
||||
}
|
||||
break;
|
||||
case GrSRGBConversion::kLinearToSRGB:
|
||||
SkASSERT(this->caps()->srgbSupport());
|
||||
// This check goes away when we start referring to CPU data using color type.
|
||||
SkASSERT(GrSRGBEncoded::kYes == GrPixelConfigIsSRGBEncoded(dstConfig));
|
||||
tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kYes);
|
||||
// Currently we don't expect to make a SRGB encoded surface and then read data from it
|
||||
// such that we treat it as though it were linear and is then converted to sRGB.
|
||||
if (GrSRGBEncoded::kYes == GrPixelConfigIsSRGBEncoded(srcSurface->config())) {
|
||||
if (GrPixelConfigIsSRGB(srcSurface->config())) {
|
||||
return false;
|
||||
}
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
break;
|
||||
case GrSRGBConversion::kSRGBToLinear:
|
||||
SkASSERT(this->caps()->srgbSupport());
|
||||
// This assert goes away when we start referring to CPU data using color type.
|
||||
SkASSERT(GrSRGBEncoded::kNo == GrPixelConfigIsSRGBEncoded(dstConfig));
|
||||
tempSurfaceConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kNo);
|
||||
// We don't currently support reading sRGB encoded data into linear from a surface
|
||||
// unless it is an sRGB-encoded config. That is likely to change when we need to store
|
||||
// sRGB encoded data in 101010102 and F16 textures. We'll have to provoke the caller to
|
||||
@ -248,8 +243,23 @@ bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
break;
|
||||
}
|
||||
if (kUnknown_GrPixelConfig == tempSurfaceConfig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->onGetReadPixelsInfo(srcSurface, srcOrigin, width, height, rowBytes, dstConfig,
|
||||
// Default values for intermediate draws. The intermediate texture config matches the dst's
|
||||
// config, is approx sized to the read rect, no swizzling or spoofing of the dst config.
|
||||
tempDrawInfo->fTempSurfaceDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
|
||||
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
|
||||
tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
|
||||
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = tempSurfaceConfig;
|
||||
tempDrawInfo->fTempSurfaceFit = SkBackingFit::kApprox;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
|
||||
tempDrawInfo->fReadColorType = dstColorType;
|
||||
|
||||
if (!this->onGetReadPixelsInfo(srcSurface, srcOrigin, width, height, rowBytes, dstColorType,
|
||||
drawPreference, tempDrawInfo)) {
|
||||
return false;
|
||||
}
|
||||
@ -266,47 +276,45 @@ bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin, int width,
|
||||
int height, GrPixelConfig srcConfig, GrSRGBConversion srgbConversion,
|
||||
DrawPreference* drawPreference,
|
||||
int height, GrColorType srcColorType,
|
||||
GrSRGBConversion srgbConversion, DrawPreference* drawPreference,
|
||||
WritePixelTempDrawInfo* tempDrawInfo) {
|
||||
SkASSERT(drawPreference);
|
||||
SkASSERT(tempDrawInfo);
|
||||
SkASSERT(dstSurface);
|
||||
SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference);
|
||||
|
||||
// Default values for intermediate draws. The intermediate texture config matches the dst's
|
||||
// config, is approx sized to the write rect, no swizzling or sppofing of the src config.
|
||||
tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
||||
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
|
||||
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
|
||||
tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
|
||||
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
|
||||
tempDrawInfo->fWriteConfig = srcConfig;
|
||||
|
||||
GrPixelConfig tempSurfaceConfig = kUnknown_GrPixelConfig;
|
||||
// GrGpu::writePixels doesn't do any sRGB conversions, so we must draw if there is one.
|
||||
switch (srgbConversion) {
|
||||
case GrSRGBConversion::kNone:
|
||||
// We support writing just A to a RGBA. In that case there is no sRGB version of the
|
||||
// src format but we still want to succeed.
|
||||
if (GrColorTypeIsAlphaOnly(srcColorType)) {
|
||||
tempSurfaceConfig = GrColorTypeToPixelConfig(srcColorType, GrSRGBEncoded::kNo);
|
||||
} else {
|
||||
tempSurfaceConfig = GrColorTypeToPixelConfig(
|
||||
srcColorType, GrPixelConfigIsSRGBEncoded(dstSurface->config()));
|
||||
}
|
||||
break;
|
||||
case GrSRGBConversion::kLinearToSRGB:
|
||||
SkASSERT(this->caps()->srgbSupport());
|
||||
// This assert goes away when we start referring to CPU data using color type.
|
||||
SkASSERT(GrSRGBEncoded::kNo == GrPixelConfigIsSRGBEncoded(srcConfig));
|
||||
tempSurfaceConfig = GrColorTypeToPixelConfig(srcColorType, GrSRGBEncoded::kNo);
|
||||
// We don't currently support storing sRGB encoded data in a surface unless it is
|
||||
// an SRGB-encoded config. That is likely to change when we need to store sRGB encoded
|
||||
// data in 101010102 and F16 textures. We'll have to provoke the caller to do the
|
||||
// conversion in a shader.
|
||||
if (GrSRGBEncoded::kNo == GrPixelConfigIsSRGBEncoded(dstSurface->config())) {
|
||||
if (!GrPixelConfigIsSRGB(dstSurface->config())) {
|
||||
return false;
|
||||
}
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
break;
|
||||
case GrSRGBConversion::kSRGBToLinear:
|
||||
SkASSERT(this->caps()->srgbSupport());
|
||||
// This assert goes away when we start referring to CPU data using color type.
|
||||
SkASSERT(GrSRGBEncoded::kYes == GrPixelConfigIsSRGBEncoded(srcConfig));
|
||||
tempSurfaceConfig = GrColorTypeToPixelConfig(srcColorType, GrSRGBEncoded::kYes);
|
||||
// Currently we don't expect to make a SRGB encoded surface and then succeed at
|
||||
// treating it as though it were linear and then convert to sRGB.
|
||||
if (GrSRGBEncoded::kYes == GrPixelConfigIsSRGBEncoded(dstSurface->config())) {
|
||||
@ -315,9 +323,23 @@ bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
break;
|
||||
}
|
||||
if (kUnknown_GrPixelConfig == tempSurfaceConfig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->onGetWritePixelsInfo(dstSurface, dstOrigin, width, height, srcConfig, drawPreference,
|
||||
tempDrawInfo)) {
|
||||
// Default values for intermediate draws. The intermediate texture config matches the dst's
|
||||
// config, is approx sized to the write rect, no swizzling or sppofing of the src config.
|
||||
tempDrawInfo->fTempSurfaceDesc.fFlags = kNone_GrSurfaceFlags;
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = tempSurfaceConfig;
|
||||
tempDrawInfo->fTempSurfaceDesc.fWidth = width;
|
||||
tempDrawInfo->fTempSurfaceDesc.fHeight = height;
|
||||
tempDrawInfo->fTempSurfaceDesc.fSampleCnt = 1;
|
||||
tempDrawInfo->fTempSurfaceDesc.fOrigin = kTopLeft_GrSurfaceOrigin; // no CPU y-flip for TL.
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
|
||||
tempDrawInfo->fWriteColorType = srcColorType;
|
||||
|
||||
if (!this->onGetWritePixelsInfo(dstSurface, dstOrigin, width, height, srcColorType,
|
||||
drawPreference, tempDrawInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -325,8 +347,8 @@ bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
|
||||
if (!dstSurface->asRenderTarget() ||
|
||||
!this->caps()->isConfigTexturable(tempDrawInfo->fTempSurfaceDesc.fConfig)) {
|
||||
// If we don't have a fallback to a straight upload then fail.
|
||||
if (kRequireDraw_DrawPreference == *drawPreference ||
|
||||
!this->caps()->isConfigTexturable(srcConfig)) {
|
||||
if (kRequireDraw_DrawPreference == *drawPreference /*TODO ||
|
||||
!this->caps()->isConfigTexturable(srcConfig)*/) {
|
||||
return false;
|
||||
}
|
||||
*drawPreference = kNoDraw_DrawPreference;
|
||||
@ -334,13 +356,11 @@ bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrGpu::readPixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, void* buffer,
|
||||
size_t rowBytes) {
|
||||
bool GrGpu::readPixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
|
||||
int height, GrColorType dstColorType, void* buffer, size_t rowBytes) {
|
||||
SkASSERT(surface);
|
||||
|
||||
size_t bpp = GrBytesPerPixel(config);
|
||||
int bpp = GrColorTypeBytesPerPixel(dstColorType);
|
||||
if (!GrSurfacePriv::AdjustReadPixelParams(surface->width(), surface->height(), bpp,
|
||||
&left, &top, &width, &height,
|
||||
&buffer,
|
||||
@ -350,15 +370,13 @@ bool GrGpu::readPixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
|
||||
this->handleDirtyContext();
|
||||
|
||||
return this->onReadPixels(surface, origin,
|
||||
left, top, width, height,
|
||||
config, buffer,
|
||||
return this->onReadPixels(surface, origin, left, top, width, height, dstColorType, buffer,
|
||||
rowBytes);
|
||||
}
|
||||
|
||||
bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const GrMipLevel texels[], int mipLevelCount) {
|
||||
bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
|
||||
int height, GrColorType srcColorType, const GrMipLevel texels[],
|
||||
int mipLevelCount) {
|
||||
SkASSERT(surface);
|
||||
if (1 == mipLevelCount) {
|
||||
// We require that if we are not mipped, then the write region is contained in the surface
|
||||
@ -379,8 +397,8 @@ bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
}
|
||||
|
||||
this->handleDirtyContext();
|
||||
if (this->onWritePixels(surface, origin, left, top, width, height, config,
|
||||
texels, mipLevelCount)) {
|
||||
if (this->onWritePixels(surface, origin, left, top, width, height, srcColorType, texels,
|
||||
mipLevelCount)) {
|
||||
SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
this->didWriteToSurface(surface, origin, &rect, mipLevelCount);
|
||||
fStats.incTextureUploads();
|
||||
@ -389,19 +407,16 @@ bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes) {
|
||||
bool GrGpu::writePixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
|
||||
int height, GrColorType srcColorType, const void* buffer, size_t rowBytes) {
|
||||
GrMipLevel mipLevel = { buffer, rowBytes };
|
||||
|
||||
return this->writePixels(surface, origin, left, top, width, height, config, &mipLevel, 1);
|
||||
return this->writePixels(surface, origin, left, top, width, height, srcColorType, &mipLevel, 1);
|
||||
}
|
||||
|
||||
bool GrGpu::transferPixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) {
|
||||
bool GrGpu::transferPixels(GrTexture* texture, int left, int top, int width, int height,
|
||||
GrColorType bufferColorType, GrBuffer* transferBuffer, size_t offset,
|
||||
size_t rowBytes) {
|
||||
SkASSERT(transferBuffer);
|
||||
|
||||
// We require that the write region is contained in the texture
|
||||
@ -412,8 +427,8 @@ bool GrGpu::transferPixels(GrTexture* texture,
|
||||
}
|
||||
|
||||
this->handleDirtyContext();
|
||||
if (this->onTransferPixels(texture, left, top, width, height, config,
|
||||
transferBuffer, offset, rowBytes)) {
|
||||
if (this->onTransferPixels(texture, left, top, width, height, bufferColorType, transferBuffer,
|
||||
offset, rowBytes)) {
|
||||
SkIRect rect = SkIRect::MakeXYWH(left, top, width, height);
|
||||
this->didWriteToSurface(texture, kTopLeft_GrSurfaceOrigin, &rect);
|
||||
fStats.incTransfersToTexture();
|
||||
|
156
src/gpu/GrGpu.h
156
src/gpu/GrGpu.h
@ -154,42 +154,56 @@ public:
|
||||
/** Info struct returned by getReadPixelsInfo about performing intermediate draws before
|
||||
reading pixels for performance or correctness. */
|
||||
struct ReadPixelTempDrawInfo {
|
||||
/** If the GrGpu is requesting that the caller do a draw to an intermediate surface then
|
||||
this is descriptor for the temp surface. The draw should always be a rect with
|
||||
dst 0,0,w,h. */
|
||||
/**
|
||||
* If the GrGpu is requesting that the caller do a draw to an intermediate surface then
|
||||
* this is descriptor for the temp surface. The draw should always be a rect with dst
|
||||
* 0,0,w,h.
|
||||
*/
|
||||
GrSurfaceDesc fTempSurfaceDesc;
|
||||
/** Indicates whether there is a performance advantage to using an exact match texture
|
||||
(in terms of width and height) for the intermediate texture instead of approximate. */
|
||||
/**
|
||||
* Indicates whether there is a performance advantage to using an exact match texture
|
||||
* (in terms of width and height) for the intermediate texture instead of approximate.
|
||||
*/
|
||||
SkBackingFit fTempSurfaceFit;
|
||||
/** Swizzle to apply during the draw. This is used to compensate for either feature or
|
||||
performance limitations in the underlying 3D API. */
|
||||
/**
|
||||
* Swizzle to apply during the draw. This is used to compensate for either feature or
|
||||
* performance limitations in the underlying 3D API.
|
||||
*/
|
||||
GrSwizzle fSwizzle;
|
||||
/** The config that should be used to read from the temp surface after the draw. This may be
|
||||
different than the original read config in order to compensate for swizzling. The
|
||||
read data will effectively be in the original read config. */
|
||||
GrPixelConfig fReadConfig;
|
||||
/**
|
||||
* The color type that should be used to read from the temp surface after the draw. This
|
||||
* may be different than the original read color type in order to compensate for swizzling.
|
||||
* The read data will effectively be in the original color type. The original gamma
|
||||
* encoding is always used.
|
||||
*/
|
||||
GrColorType fReadColorType;
|
||||
};
|
||||
|
||||
/** Describes why an intermediate draw must/should be performed before readPixels. */
|
||||
enum DrawPreference {
|
||||
/** On input means that the caller would proceed without draw if the GrGpu doesn't request
|
||||
one.
|
||||
On output means that the GrGpu is not requesting a draw. */
|
||||
/**
|
||||
* On input means that the caller would proceed without draw if the GrGpu doesn't request
|
||||
* one. On output means that the GrGpu is not requesting a draw.
|
||||
*/
|
||||
kNoDraw_DrawPreference,
|
||||
/** Means that the client would prefer a draw for performance of the readback but
|
||||
can satisfy a straight readPixels call on the inputs without an intermediate draw.
|
||||
getReadPixelsInfo will never set the draw preference to this value but may leave
|
||||
it set. */
|
||||
/**
|
||||
* Means that the client would prefer a draw for performance of the readback but
|
||||
* can satisfy a straight readPixels call on the inputs without an intermediate draw.
|
||||
* getReadPixelsInfo will never set the draw preference to this value but may leave
|
||||
* it set.
|
||||
*/
|
||||
kCallerPrefersDraw_DrawPreference,
|
||||
/** On output means that GrGpu would prefer a draw for performance of the readback but
|
||||
can satisfy a straight readPixels call on the inputs without an intermediate draw. The
|
||||
caller of getReadPixelsInfo should never specify this on intput. */
|
||||
/**
|
||||
* On output means that GrGpu would prefer a draw for performance of the readback but
|
||||
* can satisfy a straight readPixels call on the inputs without an intermediate draw. The
|
||||
* caller of getReadPixelsInfo should never specify this on intput.
|
||||
*/
|
||||
kGpuPrefersDraw_DrawPreference,
|
||||
/** On input means that the caller requires a draw to do a transformation and there is no
|
||||
CPU fallback.
|
||||
On output means that GrGpu can only satisfy the readPixels request if the intermediate
|
||||
draw is performed.
|
||||
*/
|
||||
/**
|
||||
* On input means that the caller requires a draw to do a transformation and there is no
|
||||
* CPU fallback. On output means that GrGpu can only satisfy the readPixels request if the
|
||||
* intermediate draw is performed.
|
||||
*/
|
||||
kRequireDraw_DrawPreference
|
||||
};
|
||||
|
||||
@ -199,25 +213,33 @@ public:
|
||||
* that would allow a successful readPixels call. The passed width, height, and rowBytes,
|
||||
* must be non-zero and already reflect clipping to the src bounds.
|
||||
*/
|
||||
bool getReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width,
|
||||
int height, size_t rowBytes, GrPixelConfig,
|
||||
GrSRGBConversion, DrawPreference*, ReadPixelTempDrawInfo*);
|
||||
bool getReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, size_t rowBytes,
|
||||
GrColorType, GrSRGBConversion, DrawPreference*, ReadPixelTempDrawInfo*);
|
||||
|
||||
/** Info struct returned by getWritePixelsInfo about performing an intermediate draw in order
|
||||
to write pixels to a GrSurface for either performance or correctness reasons. */
|
||||
/**
|
||||
* Info struct returned by getWritePixelsInfo about performing an intermediate draw in order
|
||||
* to write pixels to a GrSurface for either performance or correctness reasons.
|
||||
*/
|
||||
struct WritePixelTempDrawInfo {
|
||||
/** If the GrGpu is requesting that the caller upload to an intermediate surface and draw
|
||||
that to the dst then this is the descriptor for the intermediate surface. The caller
|
||||
should upload the pixels such that the upper left pixel of the upload rect is at 0,0 in
|
||||
the intermediate surface.*/
|
||||
/**
|
||||
* If the GrGpu is requesting that the caller upload to an intermediate surface and draw
|
||||
* that to the dst then this is the descriptor for the intermediate surface. The caller
|
||||
* should upload the pixels such that the upper left pixel of the upload rect is at 0,0 in
|
||||
* the intermediate surface
|
||||
*/
|
||||
GrSurfaceDesc fTempSurfaceDesc;
|
||||
/** Swizzle to apply during the draw. This is used to compensate for either feature or
|
||||
performance limitations in the underlying 3D API. */
|
||||
/**
|
||||
* Swizzle to apply during the draw. This is used to compensate for either feature or
|
||||
* performance limitations in the underlying 3D API.
|
||||
*/
|
||||
GrSwizzle fSwizzle;
|
||||
/** The config that should be specified when uploading the *original* data to the temp
|
||||
surface before the draw. This may be different than the original src data config in
|
||||
order to compensate for swizzling that will occur when drawing. */
|
||||
GrPixelConfig fWriteConfig;
|
||||
/**
|
||||
* The color type that should be specified when uploading the *original* data to the temp
|
||||
* surface before the draw. This may be different than the original src color type in
|
||||
* order to compensate for swizzling that will occur when drawing. The original gamma
|
||||
* encoding is always used.
|
||||
*/
|
||||
GrColorType fWriteColorType;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -226,9 +248,8 @@ public:
|
||||
* that would allow a successful transfer of the src pixels to the dst. The passed width,
|
||||
* height, and rowBytes, must be non-zero and already reflect clipping to the dst bounds.
|
||||
*/
|
||||
bool getWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height,
|
||||
GrPixelConfig, GrSRGBConversion, DrawPreference*,
|
||||
WritePixelTempDrawInfo*);
|
||||
bool getWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, GrColorType,
|
||||
GrSRGBConversion, DrawPreference*, WritePixelTempDrawInfo*);
|
||||
|
||||
/**
|
||||
* Reads a rectangle of pixels from a render target. No sRGB/linear conversions are performed.
|
||||
@ -238,7 +259,7 @@ public:
|
||||
* @param top top edge of the rectangle to read (inclusive)
|
||||
* @param width width of rectangle to read in pixels.
|
||||
* @param height height of rectangle to read in pixels.
|
||||
* @param dstConfig the pixel config of the destination buffer
|
||||
* @param dstColorType the color type of the destination buffer.
|
||||
* @param buffer memory to read the rectangle into.
|
||||
* @param rowBytes the number of bytes between consecutive rows. Zero
|
||||
* means rows are tightly packed.
|
||||
@ -250,7 +271,7 @@ public:
|
||||
* target is currently set.
|
||||
*/
|
||||
bool readPixels(GrSurface* surface, GrSurfaceOrigin, int left, int top, int width, int height,
|
||||
GrPixelConfig dstConfig, void* buffer, size_t rowBytes);
|
||||
GrColorType dstColorType, void* buffer, size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Updates the pixels in a rectangle of a surface. No sRGB/linear conversions are performed.
|
||||
@ -260,21 +281,20 @@ public:
|
||||
* @param top top edge of the rectangle to write (inclusive)
|
||||
* @param width width of rectangle to write in pixels.
|
||||
* @param height height of rectangle to write in pixels.
|
||||
* @param srcConfig the pixel config of the source buffer
|
||||
* @param srcColorType the color type of the source buffer.
|
||||
* @param texels array of mipmap levels containing texture data
|
||||
* @param mipLevelCount number of levels in 'texels'
|
||||
*/
|
||||
bool writePixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig srcConfig,
|
||||
const GrMipLevel texels[], int mipLevelCount);
|
||||
bool writePixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
|
||||
int height, GrColorType srcColorType, const GrMipLevel texels[],
|
||||
int mipLevelCount);
|
||||
|
||||
/**
|
||||
* This function is a shim which creates a SkTArray<GrMipLevel> of size 1.
|
||||
* It then calls writePixels with that SkTArray.
|
||||
*/
|
||||
bool writePixels(GrSurface*, GrSurfaceOrigin, int left, int top, int width,
|
||||
int height, GrPixelConfig, const void* buffer, size_t rowBytes);
|
||||
bool writePixels(GrSurface*, GrSurfaceOrigin, int left, int top, int width, int height,
|
||||
GrColorType, const void* buffer, size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Updates the pixels in a rectangle of a texture using a buffer
|
||||
@ -287,14 +307,14 @@ public:
|
||||
* @param top top edge of the rectangle to write (inclusive)
|
||||
* @param width width of rectangle to write in pixels.
|
||||
* @param height height of rectangle to write in pixels.
|
||||
* @param bufferConfig the pixel config of the source buffer
|
||||
* @param bufferColorType the color type of the transfer buffer's pixel data
|
||||
* @param transferBuffer GrBuffer to read pixels from (type must be "kXferCpuToGpu")
|
||||
* @param offset offset from the start of the buffer
|
||||
* @param rowBytes number of bytes between consecutive rows in the buffer. Zero
|
||||
* means rows are tightly packed.
|
||||
*/
|
||||
bool transferPixels(GrTexture* texture, int left, int top, int width, int height,
|
||||
GrPixelConfig bufferConfig, GrBuffer* transferBuffer, size_t offset,
|
||||
GrColorType bufferColorType, GrBuffer* transferBuffer, size_t offset,
|
||||
size_t rowBytes);
|
||||
|
||||
// After the client interacts directly with the 3D context state the GrGpu
|
||||
@ -534,30 +554,24 @@ private:
|
||||
}
|
||||
|
||||
virtual bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height,
|
||||
size_t rowBytes, GrPixelConfig, DrawPreference*,
|
||||
size_t rowBytes, GrColorType, DrawPreference*,
|
||||
ReadPixelTempDrawInfo*) = 0;
|
||||
virtual bool onGetWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height,
|
||||
GrPixelConfig, DrawPreference*, WritePixelTempDrawInfo*) = 0;
|
||||
GrColorType, DrawPreference*, WritePixelTempDrawInfo*) = 0;
|
||||
|
||||
// overridden by backend-specific derived class to perform the surface read
|
||||
virtual bool onReadPixels(GrSurface*, GrSurfaceOrigin,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig,
|
||||
void* buffer,
|
||||
size_t rowBytes) = 0;
|
||||
virtual bool onReadPixels(GrSurface*, GrSurfaceOrigin, int left, int top, int width, int height,
|
||||
GrColorType, void* buffer, size_t rowBytes) = 0;
|
||||
|
||||
// overridden by backend-specific derived class to perform the surface write
|
||||
virtual bool onWritePixels(GrSurface*, GrSurfaceOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config,
|
||||
const GrMipLevel texels[], int mipLevelCount) = 0;
|
||||
virtual bool onWritePixels(GrSurface*, GrSurfaceOrigin, int left, int top, int width,
|
||||
int height, GrColorType, const GrMipLevel texels[],
|
||||
int mipLevelCount) = 0;
|
||||
|
||||
// overridden by backend-specific derived class to perform the texture transfer
|
||||
virtual bool onTransferPixels(GrTexture*,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) = 0;
|
||||
virtual bool onTransferPixels(GrTexture*, int left, int top, int width, int height,
|
||||
GrColorType colorType, GrBuffer* transferBuffer, size_t offset,
|
||||
size_t rowBytes) = 0;
|
||||
|
||||
// overridden by backend-specific derived class to perform the resolve
|
||||
virtual void onResolveRenderTarget(GrRenderTarget* target) = 0;
|
||||
|
@ -79,22 +79,24 @@ void GrOpFlushState::reset() {
|
||||
|
||||
void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload) {
|
||||
GrDeferredTextureUploadWritePixelsFn wp = [this](GrTextureProxy* dstProxy, int left, int top,
|
||||
int width, int height, GrPixelConfig srcConfig,
|
||||
const void* buffer, size_t rowBytes) {
|
||||
int width, int height,
|
||||
GrColorType srcColorType, const void* buffer,
|
||||
size_t rowBytes) {
|
||||
// We don't allow srgb conversions via op flush state uploads.
|
||||
static constexpr auto kSRGBConversion = GrSRGBConversion::kNone;
|
||||
GrSurface* dstSurface = dstProxy->priv().peekSurface();
|
||||
GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
|
||||
GrGpu::WritePixelTempDrawInfo tempInfo;
|
||||
if (!fGpu->getWritePixelsInfo(dstSurface, dstProxy->origin(), width, height, srcConfig,
|
||||
if (!fGpu->getWritePixelsInfo(dstSurface, dstProxy->origin(), width, height, srcColorType,
|
||||
kSRGBConversion, &drawPreference, &tempInfo)) {
|
||||
return false;
|
||||
}
|
||||
if (GrGpu::kNoDraw_DrawPreference == drawPreference) {
|
||||
return this->fGpu->writePixels(dstSurface, dstProxy->origin(),
|
||||
left, top, width, height,
|
||||
srcConfig, buffer, rowBytes);
|
||||
return this->fGpu->writePixels(dstSurface, dstProxy->origin(), left, top, width, height,
|
||||
srcColorType, buffer, rowBytes);
|
||||
}
|
||||
// TODO: Shouldn't we be bailing here if a draw is really required instead of a copy?
|
||||
// e.g. if (tempInfo.fSwizzle != "RGBA") fail.
|
||||
GrSurfaceDesc desc;
|
||||
desc.fOrigin = dstProxy->origin();
|
||||
desc.fWidth = width;
|
||||
@ -105,8 +107,8 @@ void GrOpFlushState::doUpload(GrDeferredTextureUploadFn& upload) {
|
||||
if (!temp) {
|
||||
return false;
|
||||
}
|
||||
if (!fGpu->writePixels(temp.get(), dstProxy->origin(), 0, 0, width, height, desc.fConfig,
|
||||
buffer, rowBytes)) {
|
||||
if (!fGpu->writePixels(temp.get(), dstProxy->origin(), 0, 0, width, height,
|
||||
tempInfo.fWriteColorType, buffer, rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
return fGpu->copySurface(dstSurface, dstProxy->origin(), temp.get(), dstProxy->origin(),
|
||||
|
@ -48,21 +48,17 @@ bool GrSurfaceContext::readPixels(const SkImageInfo& dstInfo, void* dstBuffer,
|
||||
SkDEBUGCODE(this->validate();)
|
||||
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrSurfaceContext::readPixels");
|
||||
|
||||
// TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
|
||||
GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
|
||||
if (kUnknown_GrPixelConfig == config) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: this seems to duplicate code in SkImage_Gpu::onReadPixels
|
||||
if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
|
||||
flags |= GrContextPriv::kUnpremul_PixelOpsFlag;
|
||||
}
|
||||
|
||||
return fContext->contextPriv().readSurfacePixels(this, x, y,
|
||||
dstInfo.width(), dstInfo.height(), config,
|
||||
dstInfo.colorSpace(),
|
||||
dstBuffer, dstRowBytes, flags);
|
||||
auto colorType = SkColorTypeToGrColorType(dstInfo.colorType());
|
||||
if (GrColorType::kUnknown == colorType) {
|
||||
return false;
|
||||
}
|
||||
return fContext->contextPriv().readSurfacePixels(this, x, y, dstInfo.width(), dstInfo.height(),
|
||||
colorType, dstInfo.colorSpace(), dstBuffer,
|
||||
dstRowBytes, flags);
|
||||
}
|
||||
|
||||
bool GrSurfaceContext::writePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
|
||||
@ -72,19 +68,16 @@ bool GrSurfaceContext::writePixels(const SkImageInfo& srcInfo, const void* srcBu
|
||||
SkDEBUGCODE(this->validate();)
|
||||
GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrSurfaceContext::writePixels");
|
||||
|
||||
// TODO: teach GrRenderTarget to take ImageInfo directly to specify the src pixels
|
||||
GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
|
||||
if (kUnknown_GrPixelConfig == config) {
|
||||
return false;
|
||||
}
|
||||
if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
|
||||
flags |= GrContextPriv::kUnpremul_PixelOpsFlag;
|
||||
}
|
||||
|
||||
return fContext->contextPriv().writeSurfacePixels(this, x, y,
|
||||
srcInfo.width(), srcInfo.height(),
|
||||
config, srcInfo.colorSpace(),
|
||||
srcBuffer, srcRowBytes, flags);
|
||||
auto colorType = SkColorTypeToGrColorType(srcInfo.colorType());
|
||||
if (GrColorType::kUnknown == colorType) {
|
||||
return false;
|
||||
}
|
||||
return fContext->contextPriv().writeSurfacePixels(this, x, y, srcInfo.width(), srcInfo.height(),
|
||||
colorType, srcInfo.colorSpace(), srcBuffer,
|
||||
srcRowBytes, flags);
|
||||
}
|
||||
|
||||
bool GrSurfaceContext::copy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
|
||||
|
@ -660,17 +660,23 @@ sk_sp<GrRenderTarget> GrGLGpu::onWrapBackendTextureAsRenderTarget(const GrBacken
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
|
||||
int width, int height,
|
||||
GrPixelConfig srcConfig,
|
||||
bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin, int width,
|
||||
int height, GrColorType srcColorType,
|
||||
DrawPreference* drawPreference,
|
||||
WritePixelTempDrawInfo* tempDrawInfo) {
|
||||
// We don't want to introduce a sRGB conversion if we trigger a draw.
|
||||
auto srcConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(dstSurface->config());
|
||||
if (*drawPreference != kNoDraw_DrawPreference) {
|
||||
// We assume the base class has only inserted a draw for sRGB reasons. So the temp surface
|
||||
// has the config of the original src data. There is no swizzling nor src config spoofing.
|
||||
SkASSERT(tempDrawInfo->fWriteConfig == srcConfig);
|
||||
SkASSERT(tempDrawInfo->fTempSurfaceDesc.fConfig == srcConfig);
|
||||
SkASSERT(tempDrawInfo->fWriteColorType == srcColorType);
|
||||
SkASSERT(GrPixelConfigToColorType(tempDrawInfo->fTempSurfaceDesc.fConfig) == srcColorType);
|
||||
SkASSERT(tempDrawInfo->fSwizzle == GrSwizzle::RGBA());
|
||||
// Don't undo a sRGB conversion introduced by our caller via an intermediate draw.
|
||||
srcConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(tempDrawInfo->fTempSurfaceDesc.fConfig);
|
||||
}
|
||||
if (GrColorTypeIsAlphaOnly(srcColorType)) {
|
||||
srcConfigSRGBEncoded = GrSRGBEncoded::kNo;
|
||||
}
|
||||
|
||||
if (SkToBool(dstSurface->asRenderTarget())) {
|
||||
@ -702,20 +708,23 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOri
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
}
|
||||
|
||||
bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
|
||||
auto srcAsConfig = GrColorTypeToPixelConfig(srcColorType, srcConfigSRGBEncoded);
|
||||
SkASSERT(srcAsConfig != kUnknown_GrPixelConfig);
|
||||
auto dstColorType = GrPixelConfigToColorType(dstSurface->config());
|
||||
bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcAsConfig) == dstSurface->config();
|
||||
|
||||
if (configsAreRBSwaps) {
|
||||
if (!this->caps()->isConfigTexturable(srcConfig)) {
|
||||
if (!this->caps()->isConfigTexturable(srcAsConfig)) {
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fWriteConfig = dstSurface->config();
|
||||
tempDrawInfo->fWriteColorType = dstColorType;
|
||||
} else if (this->glCaps().rgba8888PixelsOpsAreSlow() &&
|
||||
kRGBA_8888_GrPixelConfig == srcConfig) {
|
||||
kRGBA_8888_GrPixelConfig == srcAsConfig) {
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fWriteConfig = dstSurface->config();
|
||||
tempDrawInfo->fWriteColorType = dstColorType;
|
||||
} else if (kGLES_GrGLStandard == this->glStandard() &&
|
||||
this->glCaps().bgraIsInternalFormat()) {
|
||||
// The internal format and external formats must match texture uploads so we can't
|
||||
@ -723,7 +732,7 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOri
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fWriteConfig = dstSurface->config();
|
||||
tempDrawInfo->fWriteColorType = dstColorType;
|
||||
}
|
||||
}
|
||||
|
||||
@ -734,8 +743,7 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOri
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check_write_and_transfer_input(GrGLTexture* glTex, GrSurface* surface,
|
||||
GrPixelConfig config) {
|
||||
static bool check_write_and_transfer_input(GrGLTexture* glTex) {
|
||||
if (!glTex) {
|
||||
return false;
|
||||
}
|
||||
@ -749,20 +757,27 @@ static bool check_write_and_transfer_input(GrGLTexture* glTex, GrSurface* surfac
|
||||
}
|
||||
|
||||
bool GrGLGpu::onWritePixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top,
|
||||
int width, int height, GrPixelConfig dstConfig,
|
||||
int width, int height, GrColorType srcColorType,
|
||||
const GrMipLevel texels[], int mipLevelCount) {
|
||||
GrGLTexture* glTex = static_cast<GrGLTexture*>(surface->asTexture());
|
||||
auto glTex = static_cast<GrGLTexture*>(surface->asTexture());
|
||||
|
||||
if (!check_write_and_transfer_input(glTex, surface, dstConfig)) {
|
||||
if (!check_write_and_transfer_input(glTex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->setScratchTextureUnit();
|
||||
GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
|
||||
|
||||
// No sRGB transformation occurs in uploadTexData. We choose to make the src config match the
|
||||
// srgb-ness of the surface to avoid issues in ES2 where internal/external formats must match.
|
||||
// When we're on ES2 and the dst is GL_SRGB_ALPHA by making the config be kSRGB_8888 we know
|
||||
// that our caps will choose GL_SRGB_ALPHA as the external format, too. On ES3 or regular GL our
|
||||
// caps knows to make the external format be GL_RGBA.
|
||||
auto srgbEncoded = GrPixelConfigIsSRGBEncoded(surface->config());
|
||||
auto srcAsConfig = GrColorTypeToPixelConfig(srcColorType, srgbEncoded);
|
||||
return this->uploadTexData(glTex->config(), glTex->width(), glTex->height(), origin,
|
||||
glTex->target(), kWrite_UploadType, left, top, width, height,
|
||||
dstConfig, texels, mipLevelCount);
|
||||
srcAsConfig, texels, mipLevelCount);
|
||||
}
|
||||
|
||||
// For GL_[UN]PACK_ALIGNMENT.
|
||||
@ -796,13 +811,13 @@ static inline GrGLint config_alignment(GrPixelConfig config) {
|
||||
}
|
||||
|
||||
bool GrGLGpu::onTransferPixels(GrTexture* texture, int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer, size_t offset,
|
||||
GrColorType bufferColorType, GrBuffer* transferBuffer, size_t offset,
|
||||
size_t rowBytes) {
|
||||
GrGLTexture* glTex = static_cast<GrGLTexture*>(texture);
|
||||
GrPixelConfig texConfig = glTex->config();
|
||||
SkASSERT(this->caps()->isConfigTexturable(texConfig));
|
||||
|
||||
if (!check_write_and_transfer_input(glTex, texture, config)) {
|
||||
if (!check_write_and_transfer_input(glTex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -824,7 +839,7 @@ bool GrGLGpu::onTransferPixels(GrTexture* texture, int left, int top, int width,
|
||||
SkASSERT(bounds.contains(subRect));
|
||||
)
|
||||
|
||||
size_t bpp = GrBytesPerPixel(config);
|
||||
int bpp = GrColorTypeBytesPerPixel(bufferColorType);
|
||||
const size_t trimRowBytes = width * bpp;
|
||||
if (!rowBytes) {
|
||||
rowBytes = trimRowBytes;
|
||||
@ -847,7 +862,8 @@ bool GrGLGpu::onTransferPixels(GrTexture* texture, int left, int top, int width,
|
||||
// External format and type come from the upload data.
|
||||
GrGLenum externalFormat;
|
||||
GrGLenum externalType;
|
||||
if (!this->glCaps().getTexImageFormats(texConfig, config, &internalFormat,
|
||||
auto bufferAsConfig = GrColorTypeToPixelConfig(bufferColorType, GrSRGBEncoded::kNo);
|
||||
if (!this->glCaps().getTexImageFormats(texConfig, bufferAsConfig, &internalFormat,
|
||||
&externalFormat, &externalType)) {
|
||||
return false;
|
||||
}
|
||||
@ -1003,6 +1019,8 @@ void GrGLGpu::unbindCpuToGpuXferBuffer() {
|
||||
|
||||
}
|
||||
|
||||
// TODO: Make this take a GrColorType instead of dataConfig. This requires updating GrGLCaps to
|
||||
// convert from GrColorType to externalFormat/externalType GLenum values.
|
||||
bool GrGLGpu::uploadTexData(GrPixelConfig texConfig, int texWidth, int texHeight,
|
||||
GrSurfaceOrigin texOrigin, GrGLenum target, UploadType uploadType,
|
||||
int left, int top, int width, int height, GrPixelConfig dataConfig,
|
||||
@ -2160,39 +2178,50 @@ bool GrGLGpu::readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig rea
|
||||
}
|
||||
|
||||
bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin, int width,
|
||||
int height, size_t rowBytes, GrPixelConfig dstConfig,
|
||||
int height, size_t rowBytes, GrColorType dstColorType,
|
||||
DrawPreference* drawPreference,
|
||||
ReadPixelTempDrawInfo* tempDrawInfo) {
|
||||
// We don't want to introduce a sRGB conversion if we trigger a draw.
|
||||
auto dstConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(srcSurface->config());
|
||||
if (*drawPreference != kNoDraw_DrawPreference) {
|
||||
// We assume the base class has only inserted a draw for sRGB reasons. So the
|
||||
// the temp surface has the config of the dst data. There is no swizzling, nor dst config
|
||||
// spoofing.
|
||||
SkASSERT(tempDrawInfo->fReadConfig == dstConfig);
|
||||
SkASSERT(tempDrawInfo->fTempSurfaceDesc.fConfig == dstConfig);
|
||||
SkASSERT(tempDrawInfo->fReadColorType == dstColorType);
|
||||
SkASSERT(GrPixelConfigToColorType(tempDrawInfo->fTempSurfaceDesc.fConfig) == dstColorType);
|
||||
SkASSERT(tempDrawInfo->fSwizzle == GrSwizzle::RGBA());
|
||||
// Don't undo a sRGB conversion introduced by our caller via an intermediate draw.
|
||||
dstConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(tempDrawInfo->fTempSurfaceDesc.fConfig);
|
||||
}
|
||||
if (GrColorTypeIsAlphaOnly(dstColorType)) {
|
||||
dstConfigSRGBEncoded = GrSRGBEncoded::kNo;
|
||||
}
|
||||
GrPixelConfig srcConfig = srcSurface->config();
|
||||
|
||||
tempDrawInfo->fTempSurfaceFit = this->glCaps().partialFBOReadIsSlow() ? SkBackingFit::kExact
|
||||
: SkBackingFit::kApprox;
|
||||
|
||||
if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == dstConfig &&
|
||||
// TODO: Update this logic to use color type.
|
||||
auto dstAsConfig = GrColorTypeToPixelConfig(dstColorType, dstConfigSRGBEncoded);
|
||||
|
||||
if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == dstAsConfig &&
|
||||
this->readPixelsSupported(kBGRA_8888_GrPixelConfig, kBGRA_8888_GrPixelConfig)) {
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fReadColorType = GrColorType::kBGRA_8888;
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
} else if (this->glCaps().rgbaToBgraReadbackConversionsAreSlow() &&
|
||||
GrBytesPerPixel(dstConfig) == 4 && GrPixelConfigSwapRAndB(dstConfig) == srcConfig &&
|
||||
GrBytesPerPixel(dstAsConfig) == 4 &&
|
||||
GrPixelConfigSwapRAndB(dstAsConfig) == srcConfig &&
|
||||
this->readPixelsSupported(srcSurface, srcConfig)) {
|
||||
// Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa.
|
||||
// Better to do a draw with a R/B swap and then read as the original config.
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = srcConfig;
|
||||
tempDrawInfo->fReadColorType = GrPixelConfigToColorType(srcConfig);
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
} else if (!this->readPixelsSupported(srcSurface, dstConfig)) {
|
||||
if (dstConfig == kBGRA_8888_GrPixelConfig &&
|
||||
} else if (!this->readPixelsSupported(srcSurface, dstAsConfig)) {
|
||||
if (kBGRA_8888_GrPixelConfig == dstAsConfig &&
|
||||
this->glCaps().canConfigBeFBOColorAttachment(kRGBA_8888_GrPixelConfig) &&
|
||||
this->readPixelsSupported(kRGBA_8888_GrPixelConfig, kRGBA_8888_GrPixelConfig)) {
|
||||
// We're trying to read BGRA but it's not supported. If RGBA is renderable and
|
||||
@ -2200,9 +2229,9 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrig
|
||||
// will effectively be BGRA).
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fReadColorType = GrColorType::kRGBA_8888;
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
} else if (dstConfig == kSBGRA_8888_GrPixelConfig &&
|
||||
} else if (kSBGRA_8888_GrPixelConfig == dstAsConfig &&
|
||||
this->glCaps().canConfigBeFBOColorAttachment(kSRGBA_8888_GrPixelConfig) &&
|
||||
this->readPixelsSupported(kSRGBA_8888_GrPixelConfig,
|
||||
kSRGBA_8888_GrPixelConfig)) {
|
||||
@ -2211,9 +2240,9 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrig
|
||||
// will effectively be sBGRA).
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kSRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = kSRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fReadColorType = GrColorType::kRGBA_8888;
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
} else if (dstConfig == kAlpha_8_GrPixelConfig) {
|
||||
} else if (kAlpha_8_GrPixelConfig == dstAsConfig) {
|
||||
// onReadPixels implements a fallback for cases where we want to read kAlpha_8,
|
||||
// it's unsupported, but 32bit RGBA reads are supported.
|
||||
if (!this->readPixelsSupported(srcSurface, kRGBA_8888_GrPixelConfig)) {
|
||||
@ -2222,31 +2251,31 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrig
|
||||
if (this->glCaps().canConfigBeFBOColorAttachment(kRGBA_8888_GrPixelConfig)) {
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fReadConfig = kAlpha_8_GrPixelConfig;
|
||||
tempDrawInfo->fReadColorType = GrColorType::kAlpha_8;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
||||
SkASSERT(tempDrawInfo->fReadConfig == kAlpha_8_GrPixelConfig);
|
||||
SkASSERT(tempDrawInfo->fReadColorType == GrColorType::kAlpha_8);
|
||||
}
|
||||
} else if (dstConfig == kRGBA_half_GrPixelConfig &&
|
||||
} else if (kRGBA_half_GrPixelConfig == dstAsConfig &&
|
||||
this->readPixelsSupported(srcSurface, kRGBA_float_GrPixelConfig)) {
|
||||
// If reading in half float format is not supported, then read in float format.
|
||||
return true;
|
||||
} else if (this->glCaps().canConfigBeFBOColorAttachment(dstConfig) &&
|
||||
this->readPixelsSupported(dstConfig, dstConfig)) {
|
||||
} else if (this->glCaps().canConfigBeFBOColorAttachment(dstAsConfig) &&
|
||||
this->readPixelsSupported(dstAsConfig, dstAsConfig)) {
|
||||
// Do a draw to convert from the src config to the read config.
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstConfig;
|
||||
tempDrawInfo->fReadConfig = dstConfig;
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstAsConfig;
|
||||
tempDrawInfo->fReadColorType = dstColorType;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((srcSurface->asRenderTarget() || this->glCaps().canConfigBeFBOColorAttachment(srcConfig)) &&
|
||||
read_pixels_pays_for_y_flip(srcOrigin, this->glCaps(), width, height, dstConfig,
|
||||
read_pixels_pays_for_y_flip(srcOrigin, this->glCaps(), width, height, dstAsConfig,
|
||||
rowBytes)) {
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
}
|
||||
@ -2254,12 +2283,8 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrig
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig config,
|
||||
void* buffer,
|
||||
size_t rowBytes) {
|
||||
bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
|
||||
int height, GrColorType dstColorType, void* buffer, size_t rowBytes) {
|
||||
SkASSERT(surface);
|
||||
|
||||
GrGLRenderTarget* renderTarget = static_cast<GrGLRenderTarget*>(surface->asRenderTarget());
|
||||
@ -2267,15 +2292,17 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Avoid this conversion by making GrGLCaps work with color types.
|
||||
auto dstAsConfig = GrColorTypeToPixelConfig(dstColorType, GrSRGBEncoded::kNo);
|
||||
|
||||
// We have a special case fallback for reading eight bit alpha. We will read back all four 8
|
||||
// bit channels as RGBA and then extract A.
|
||||
if (!this->readPixelsSupported(surface, config)) {
|
||||
GrPixelConfig tempConfig = kRGBA_8888_GrPixelConfig;
|
||||
if (kAlpha_8_GrPixelConfig == config &&
|
||||
this->readPixelsSupported(surface, tempConfig)) {
|
||||
if (!this->readPixelsSupported(surface, dstAsConfig)) {
|
||||
if (kAlpha_8_GrPixelConfig == dstAsConfig &&
|
||||
this->readPixelsSupported(surface, kRGBA_8888_GrPixelConfig)) {
|
||||
std::unique_ptr<uint32_t[]> temp(new uint32_t[width * height * 4]);
|
||||
if (this->onReadPixels(surface, origin, left, top, width, height,
|
||||
tempConfig, temp.get(), width*4)) {
|
||||
GrColorType::kRGBA_8888, temp.get(), width * 4)) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);
|
||||
for (int j = 0; j < height; ++j) {
|
||||
for (int i = 0; i < width; ++i) {
|
||||
@ -2288,12 +2315,11 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
|
||||
// If reading in half float format is not supported, then read in a temporary float buffer
|
||||
// and convert to half float.
|
||||
if (kRGBA_half_GrPixelConfig == config &&
|
||||
if (kRGBA_half_GrPixelConfig == dstAsConfig &&
|
||||
this->readPixelsSupported(surface, kRGBA_float_GrPixelConfig)) {
|
||||
std::unique_ptr<float[]> temp(new float[width * height * 4]);
|
||||
if (this->onReadPixels(surface, origin, left, top, width, height,
|
||||
kRGBA_float_GrPixelConfig, temp.get(),
|
||||
width*sizeof(float)*4)) {
|
||||
GrColorType::kRGBA_F32, temp.get(), width * sizeof(float) * 4)) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(buffer);
|
||||
float* src = temp.get();
|
||||
for (int j = 0; j < height; ++j) {
|
||||
@ -2313,7 +2339,7 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
|
||||
GrGLenum externalFormat;
|
||||
GrGLenum externalType;
|
||||
if (!this->glCaps().getReadPixelsFormat(surface->config(), config, &externalFormat,
|
||||
if (!this->glCaps().getReadPixelsFormat(surface->config(), dstAsConfig, &externalFormat,
|
||||
&externalType)) {
|
||||
return false;
|
||||
}
|
||||
@ -2348,7 +2374,7 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
GrGLIRect readRect;
|
||||
readRect.setRelativeTo(glvp, left, top, width, height, origin);
|
||||
|
||||
size_t bytesPerPixel = GrBytesPerPixel(config);
|
||||
int bytesPerPixel = GrBytesPerPixel(dstAsConfig);
|
||||
size_t tightRowBytes = bytesPerPixel * width;
|
||||
|
||||
size_t readDstRowBytes = tightRowBytes;
|
||||
@ -2370,7 +2396,7 @@ bool GrGLGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
if (flipY && this->glCaps().packFlipYSupport()) {
|
||||
GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, 1));
|
||||
}
|
||||
GL_CALL(PixelStorei(GR_GL_PACK_ALIGNMENT, config_alignment(config)));
|
||||
GL_CALL(PixelStorei(GR_GL_PACK_ALIGNMENT, config_alignment(dstAsConfig)));
|
||||
|
||||
GL_CALL(ReadPixels(readRect.fLeft, readRect.fBottom,
|
||||
readRect.fWidth, readRect.fHeight,
|
||||
|
@ -231,27 +231,19 @@ private:
|
||||
bool readPixelsSupported(GrSurface* surfaceForConfig, GrPixelConfig readConfig);
|
||||
|
||||
bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig, DrawPreference*, ReadPixelTempDrawInfo*) override;
|
||||
GrColorType, DrawPreference*, ReadPixelTempDrawInfo*) override;
|
||||
|
||||
bool onGetWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, GrPixelConfig,
|
||||
bool onGetWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, GrColorType,
|
||||
DrawPreference*, WritePixelTempDrawInfo*) override;
|
||||
|
||||
bool onReadPixels(GrSurface*, GrSurfaceOrigin,
|
||||
int left, int top,
|
||||
int width, int height,
|
||||
GrPixelConfig,
|
||||
void* buffer,
|
||||
size_t rowBytes) override;
|
||||
bool onReadPixels(GrSurface*, GrSurfaceOrigin, int left, int top, int width, int height,
|
||||
GrColorType, void* buffer, size_t rowBytes) override;
|
||||
|
||||
bool onWritePixels(GrSurface*, GrSurfaceOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config,
|
||||
const GrMipLevel texels[], int mipLevelCount) override;
|
||||
bool onWritePixels(GrSurface*, GrSurfaceOrigin, int left, int top, int width, int height,
|
||||
GrColorType, const GrMipLevel texels[], int mipLevelCount) override;
|
||||
|
||||
bool onTransferPixels(GrTexture*,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) override;
|
||||
bool onTransferPixels(GrTexture*, int left, int top, int width, int height, GrColorType,
|
||||
GrBuffer* transferBuffer, size_t offset, size_t rowBytes) override;
|
||||
|
||||
// Before calling any variation of TexImage, TexSubImage, etc..., call this to ensure that the
|
||||
// PIXEL_UNPACK_BUFFER is unbound.
|
||||
|
@ -80,37 +80,29 @@ private:
|
||||
GrBuffer* onCreateBuffer(size_t sizeInBytes, GrBufferType, GrAccessPattern,
|
||||
const void*) override;
|
||||
|
||||
bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height,
|
||||
size_t rowBytes, GrPixelConfig, DrawPreference*,
|
||||
ReadPixelTempDrawInfo*) override {
|
||||
bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, size_t rowBytes,
|
||||
GrColorType, DrawPreference*, ReadPixelTempDrawInfo*) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin, int width,
|
||||
int height, GrPixelConfig, DrawPreference*,
|
||||
WritePixelTempDrawInfo*) override {
|
||||
bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin, int width, int height,
|
||||
GrColorType, DrawPreference*, WritePixelTempDrawInfo*) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onReadPixels(GrSurface* surface, GrSurfaceOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig,
|
||||
void* buffer,
|
||||
size_t rowBytes) override {
|
||||
bool onReadPixels(GrSurface* surface, GrSurfaceOrigin, int left, int top, int width, int height,
|
||||
GrColorType, void* buffer, size_t rowBytes) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onWritePixels(GrSurface* surface, GrSurfaceOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config,
|
||||
const GrMipLevel texels[], int mipLevelCount) override {
|
||||
bool onWritePixels(GrSurface* surface, GrSurfaceOrigin, int left, int top, int width,
|
||||
int height, GrColorType, const GrMipLevel texels[],
|
||||
int mipLevelCount) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onTransferPixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) override {
|
||||
bool onTransferPixels(GrTexture* texture, int left, int top, int width, int height, GrColorType,
|
||||
GrBuffer* transferBuffer, size_t offset, size_t rowBytes) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -31,15 +31,17 @@ public:
|
||||
|
||||
id<MTLDevice> device() const { return fDevice; }
|
||||
|
||||
bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin origin,
|
||||
int readWidth, int readHeight, size_t rowBytes,
|
||||
GrPixelConfig readConfig, DrawPreference*,
|
||||
ReadPixelTempDrawInfo*) override { return false; }
|
||||
bool onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin origin, int readWidth,
|
||||
int readHeight, size_t rowBytes, GrColorType readConfig,
|
||||
DrawPreference*, ReadPixelTempDrawInfo*) override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
|
||||
int width, int height,
|
||||
GrPixelConfig srcConfig, DrawPreference*,
|
||||
WritePixelTempDrawInfo*) override { return false; }
|
||||
bool onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin, int width,
|
||||
int height, GrColorType srcColorType, DrawPreference*,
|
||||
WritePixelTempDrawInfo*) override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||
@ -105,24 +107,20 @@ private:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool onReadPixels(GrSurface* surface, GrSurfaceOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig,
|
||||
void* buffer,
|
||||
size_t rowBytes) override {
|
||||
bool onReadPixels(GrSurface* surface, GrSurfaceOrigin, int left, int top, int width, int height,
|
||||
GrColorType, void* buffer, size_t rowBytes) override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onWritePixels(GrSurface* surface, GrSurfaceOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config,
|
||||
const GrMipLevel texels[], int mipLevelCount) override {
|
||||
bool onWritePixels(GrSurface*, GrSurfaceOrigin, int left, int top, int width,
|
||||
int height, GrColorType, const GrMipLevel[],
|
||||
int) override {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool onTransferPixels(GrTexture* texture,
|
||||
bool onTransferPixels(GrTexture*,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
GrColorType, GrBuffer*,
|
||||
size_t offset, size_t rowBytes) override {
|
||||
return false;
|
||||
}
|
||||
|
@ -336,21 +336,27 @@ GrBuffer* GrVkGpu::onCreateBuffer(size_t size, GrBufferType type, GrAccessPatter
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin,
|
||||
int width, int height,
|
||||
GrPixelConfig srcConfig, DrawPreference* drawPreference,
|
||||
bool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOrigin, int width,
|
||||
int height, GrColorType srcColorType,
|
||||
DrawPreference* drawPreference,
|
||||
WritePixelTempDrawInfo* tempDrawInfo) {
|
||||
// We don't want to introduce a sRGB conversion if we trigger a draw.
|
||||
auto srcConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(dstSurface->config());
|
||||
if (*drawPreference != kNoDraw_DrawPreference) {
|
||||
// We assume the base class has only inserted a draw for sRGB reasons. So the temp surface
|
||||
// has the config of the original src data. There is no swizzling nor src config spoofing.
|
||||
SkASSERT(tempDrawInfo->fWriteConfig == srcConfig);
|
||||
SkASSERT(tempDrawInfo->fTempSurfaceDesc.fConfig == srcConfig);
|
||||
SkASSERT(tempDrawInfo->fWriteColorType == srcColorType);
|
||||
SkASSERT(GrPixelConfigToColorType(tempDrawInfo->fTempSurfaceDesc.fConfig) == srcColorType);
|
||||
SkASSERT(tempDrawInfo->fSwizzle == GrSwizzle::RGBA());
|
||||
// Don't undo a sRGB conversion introduced by our caller via an intermediate draw.
|
||||
srcConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(tempDrawInfo->fTempSurfaceDesc.fConfig);
|
||||
}
|
||||
if (GrColorTypeIsAlphaOnly(srcColorType)) {
|
||||
srcConfigSRGBEncoded = GrSRGBEncoded::kNo;
|
||||
}
|
||||
|
||||
GrRenderTarget* renderTarget = dstSurface->asRenderTarget();
|
||||
|
||||
if (dstSurface->config() == srcConfig) {
|
||||
if (GrPixelConfigToColorType(dstSurface->config()) == srcColorType) {
|
||||
// We only support writing pixels to textures. Forcing a draw lets us write to pure RTs.
|
||||
if (!dstSurface->asTexture()) {
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
@ -362,22 +368,23 @@ bool GrVkGpu::onGetWritePixelsInfo(GrSurface* dstSurface, GrSurfaceOrigin dstOri
|
||||
return true;
|
||||
}
|
||||
|
||||
// Any config change requires a draw
|
||||
// Any color type change requires a draw
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
|
||||
bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcConfig) == dstSurface->config();
|
||||
auto srcAsConfig = GrColorTypeToPixelConfig(srcColorType, srcConfigSRGBEncoded);
|
||||
SkASSERT(srcAsConfig != kUnknown_GrPixelConfig);
|
||||
bool configsAreRBSwaps = GrPixelConfigSwapRAndB(srcAsConfig) == dstSurface->config();
|
||||
|
||||
if (!this->vkCaps().isConfigTexturable(srcConfig) && configsAreRBSwaps) {
|
||||
if (!this->vkCaps().isConfigTexturable(srcAsConfig) && configsAreRBSwaps) {
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fWriteConfig = dstSurface->config();
|
||||
tempDrawInfo->fWriteColorType = GrPixelConfigToColorType(dstSurface->config());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrVkGpu::onWritePixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config,
|
||||
bool GrVkGpu::onWritePixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top,
|
||||
int width, int height, GrColorType srcColorType,
|
||||
const GrMipLevel texels[], int mipLevelCount) {
|
||||
GrVkTexture* vkTex = static_cast<GrVkTexture*>(surface->asTexture());
|
||||
if (!vkTex) {
|
||||
@ -405,7 +412,7 @@ bool GrVkGpu::onWritePixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
false);
|
||||
this->submitCommandBuffer(kForce_SyncQueue);
|
||||
}
|
||||
success = this->uploadTexDataLinear(vkTex, origin, left, top, width, height, config,
|
||||
success = this->uploadTexDataLinear(vkTex, origin, left, top, width, height, srcColorType,
|
||||
texels[0].fPixels, texels[0].fRowBytes);
|
||||
} else {
|
||||
int currentMipLevels = vkTex->texturePriv().maxMipMapLevel() + 1;
|
||||
@ -414,16 +421,15 @@ bool GrVkGpu::onWritePixels(GrSurface* surface, GrSurfaceOrigin origin,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
success = this->uploadTexDataOptimal(vkTex, origin, left, top, width, height, config,
|
||||
success = this->uploadTexDataOptimal(vkTex, origin, left, top, width, height, srcColorType,
|
||||
texels, mipLevelCount);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool GrVkGpu::onTransferPixels(GrTexture* texture,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
bool GrVkGpu::onTransferPixels(GrTexture* texture, int left, int top, int width, int height,
|
||||
GrColorType bufferColorType, GrBuffer* transferBuffer,
|
||||
size_t bufferOffset, size_t rowBytes) {
|
||||
// Vulkan only supports 4-byte aligned offsets
|
||||
if (SkToBool(bufferOffset & 0x2)) {
|
||||
@ -443,9 +449,9 @@ bool GrVkGpu::onTransferPixels(GrTexture* texture,
|
||||
SkIRect bounds = SkIRect::MakeWH(texture->width(), texture->height());
|
||||
SkASSERT(bounds.contains(subRect));
|
||||
)
|
||||
size_t bpp = GrBytesPerPixel(config);
|
||||
int bpp = GrColorTypeBytesPerPixel(bufferColorType);
|
||||
if (rowBytes == 0) {
|
||||
rowBytes = bpp*width;
|
||||
rowBytes = bpp * width;
|
||||
}
|
||||
|
||||
// Set up copy region
|
||||
@ -535,11 +541,9 @@ void GrVkGpu::internalResolveRenderTarget(GrRenderTarget* target, bool requiresS
|
||||
}
|
||||
}
|
||||
|
||||
bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dataConfig,
|
||||
const void* data,
|
||||
size_t rowBytes) {
|
||||
bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, GrSurfaceOrigin texOrigin, int left, int top,
|
||||
int width, int height, GrColorType dataColorType,
|
||||
const void* data, size_t rowBytes) {
|
||||
SkASSERT(data);
|
||||
SkASSERT(tex->isLinearTiled());
|
||||
|
||||
@ -548,7 +552,7 @@ bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
SkIRect bounds = SkIRect::MakeWH(tex->width(), tex->height());
|
||||
SkASSERT(bounds.contains(subRect));
|
||||
)
|
||||
size_t bpp = GrBytesPerPixel(dataConfig);
|
||||
int bpp = GrColorTypeBytesPerPixel(dataColorType);
|
||||
size_t trimRowBytes = width * bpp;
|
||||
if (!rowBytes) {
|
||||
rowBytes = trimRowBytes;
|
||||
@ -601,9 +605,8 @@ bool GrVkGpu::uploadTexDataLinear(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dataConfig,
|
||||
bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin, int left, int top,
|
||||
int width, int height, GrColorType dataColorType,
|
||||
const GrMipLevel texels[], int mipLevelCount) {
|
||||
SkASSERT(!tex->isLinearTiled());
|
||||
// The assumption is either that we have no mipmaps, or that our rect is the entire texture
|
||||
@ -619,7 +622,7 @@ bool GrVkGpu::uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
}
|
||||
|
||||
SkASSERT(this->caps()->isConfigTexturable(tex->config()));
|
||||
size_t bpp = GrBytesPerPixel(dataConfig);
|
||||
int bpp = GrColorTypeBytesPerPixel(dataColorType);
|
||||
|
||||
// texels is const.
|
||||
// But we may need to adjust the fPixels ptr based on the copyRect, or fRowBytes.
|
||||
@ -803,9 +806,10 @@ sk_sp<GrTexture> GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto colorType = GrPixelConfigToColorType(desc.fConfig);
|
||||
if (mipLevelCount) {
|
||||
if (!this->uploadTexDataOptimal(tex.get(), desc.fOrigin, 0, 0, desc.fWidth, desc.fHeight,
|
||||
desc.fConfig, texels, mipLevelCount)) {
|
||||
colorType, texels, mipLevelCount)) {
|
||||
tex->unref();
|
||||
return nullptr;
|
||||
}
|
||||
@ -1851,34 +1855,41 @@ bool GrVkGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
}
|
||||
|
||||
bool GrVkGpu::onGetReadPixelsInfo(GrSurface* srcSurface, GrSurfaceOrigin srcOrigin, int width,
|
||||
int height, size_t rowBytes, GrPixelConfig dstConfig,
|
||||
int height, size_t rowBytes, GrColorType dstColorType,
|
||||
DrawPreference* drawPreference,
|
||||
ReadPixelTempDrawInfo* tempDrawInfo) {
|
||||
// We don't want to introduce a sRGB conversion if we trigger a draw.
|
||||
auto dstConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(srcSurface->config());
|
||||
if (*drawPreference != kNoDraw_DrawPreference) {
|
||||
// We assume the base class has only inserted a draw for sRGB reasons. So the
|
||||
// the temp surface has the config of the dst data. There is no swizzling nor dst config.
|
||||
// spoofing.
|
||||
SkASSERT(tempDrawInfo->fReadConfig == dstConfig);
|
||||
SkASSERT(tempDrawInfo->fTempSurfaceDesc.fConfig == dstConfig);
|
||||
SkASSERT(tempDrawInfo->fReadColorType == dstColorType);
|
||||
SkASSERT(GrPixelConfigToColorType(tempDrawInfo->fTempSurfaceDesc.fConfig) == dstColorType);
|
||||
SkASSERT(tempDrawInfo->fSwizzle == GrSwizzle::RGBA());
|
||||
// Don't undo a sRGB conversion introduced by our caller via an intermediate draw.
|
||||
dstConfigSRGBEncoded = GrPixelConfigIsSRGBEncoded(tempDrawInfo->fTempSurfaceDesc.fConfig);
|
||||
}
|
||||
if (GrColorTypeIsAlphaOnly(dstColorType)) {
|
||||
dstConfigSRGBEncoded = GrSRGBEncoded::kNo;
|
||||
}
|
||||
|
||||
if (srcSurface->config() == dstConfig) {
|
||||
if (GrPixelConfigToColorType(srcSurface->config()) == dstColorType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Any config change requires a draw
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstConfig;
|
||||
tempDrawInfo->fReadConfig = dstConfig;
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig =
|
||||
GrColorTypeToPixelConfig(dstColorType, dstConfigSRGBEncoded);
|
||||
tempDrawInfo->fReadColorType = dstColorType;
|
||||
|
||||
return true;
|
||||
return kUnknown_GrPixelConfig != tempDrawInfo->fTempSurfaceDesc.fConfig;
|
||||
}
|
||||
|
||||
bool GrVkGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin, int left, int top, int width,
|
||||
int height, GrPixelConfig dstConfig, void* buffer, size_t rowBytes) {
|
||||
VkFormat pixelFormat;
|
||||
if (!GrPixelConfigToVkFormat(dstConfig, &pixelFormat)) {
|
||||
int height, GrColorType dstColorType, void* buffer, size_t rowBytes) {
|
||||
if (GrPixelConfigToColorType(surface->config()) != dstColorType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1913,7 +1924,7 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, GrSurfaceOrigin origin, int left,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
false);
|
||||
|
||||
size_t bpp = GrBytesPerPixel(dstConfig);
|
||||
int bpp = GrColorTypeBytesPerPixel(dstColorType);
|
||||
size_t tightRowBytes = bpp * width;
|
||||
bool flipY = kBottomLeft_GrSurfaceOrigin == origin;
|
||||
|
||||
|
@ -177,22 +177,20 @@ private:
|
||||
const void* data) override;
|
||||
|
||||
bool onGetReadPixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, size_t rowBytes,
|
||||
GrPixelConfig, DrawPreference*, ReadPixelTempDrawInfo*) override;
|
||||
GrColorType, DrawPreference*, ReadPixelTempDrawInfo*) override;
|
||||
|
||||
bool onGetWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, GrPixelConfig,
|
||||
bool onGetWritePixelsInfo(GrSurface*, GrSurfaceOrigin, int width, int height, GrColorType,
|
||||
DrawPreference*, WritePixelTempDrawInfo*) override;
|
||||
|
||||
bool onReadPixels(GrSurface* surface, GrSurfaceOrigin, int left, int top, int width, int height,
|
||||
GrPixelConfig, void* buffer, size_t rowBytes) override;
|
||||
GrColorType, void* buffer, size_t rowBytes) override;
|
||||
|
||||
bool onWritePixels(GrSurface* surface, GrSurfaceOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, const GrMipLevel texels[], int mipLevelCount) override;
|
||||
bool onWritePixels(GrSurface* surface, GrSurfaceOrigin, int left, int top, int width,
|
||||
int height, GrColorType, const GrMipLevel texels[],
|
||||
int mipLevelCount) override;
|
||||
|
||||
bool onTransferPixels(GrTexture*,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig config, GrBuffer* transferBuffer,
|
||||
size_t offset, size_t rowBytes) override;
|
||||
bool onTransferPixels(GrTexture*, int left, int top, int width, int height, GrColorType,
|
||||
GrBuffer* transferBuffer, size_t offset, size_t rowBytes) override;
|
||||
|
||||
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, GrSurface* src,
|
||||
GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
|
||||
@ -228,14 +226,11 @@ private:
|
||||
const SkIPoint& dstPoint);
|
||||
|
||||
// helpers for onCreateTexture and writeTexturePixels
|
||||
bool uploadTexDataLinear(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dataConfig,
|
||||
const void* data,
|
||||
bool uploadTexDataLinear(GrVkTexture* tex, GrSurfaceOrigin texOrigin, int left, int top,
|
||||
int width, int height, GrColorType colorType, const void* data,
|
||||
size_t rowBytes);
|
||||
bool uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin,
|
||||
int left, int top, int width, int height,
|
||||
GrPixelConfig dataConfig,
|
||||
bool uploadTexDataOptimal(GrVkTexture* tex, GrSurfaceOrigin texOrigin, int left, int top,
|
||||
int width, int height, GrColorType colorType,
|
||||
const GrMipLevel texels[], int mipLevelCount);
|
||||
|
||||
void resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
|
||||
|
@ -25,8 +25,8 @@
|
||||
static const int DEV_W = 100, DEV_H = 100;
|
||||
|
||||
template <typename T>
|
||||
void runFPTest(skiatest::Reporter* reporter, GrContext* context,
|
||||
T min, T max, T epsilon, T maxInt, int arraySize, GrPixelConfig config) {
|
||||
void runFPTest(skiatest::Reporter* reporter, GrContext* context, T min, T max, T epsilon, T maxInt,
|
||||
int arraySize, GrColorType colorType) {
|
||||
if (0 != arraySize % 4) {
|
||||
REPORT_FAILURE(reporter, "(0 != arraySize % 4)",
|
||||
SkString("arraySize must be divisible by 4."));
|
||||
@ -51,7 +51,7 @@ void runFPTest(skiatest::Reporter* reporter, GrContext* context,
|
||||
desc.fOrigin = 0 == origin ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin;
|
||||
desc.fWidth = DEV_W;
|
||||
desc.fHeight = DEV_H;
|
||||
desc.fConfig = config;
|
||||
desc.fConfig = GrColorTypeToPixelConfig(colorType, GrSRGBEncoded::kNo);
|
||||
|
||||
sk_sp<GrTextureProxy> fpProxy = proxyProvider->createTextureProxy(
|
||||
desc, SkBudgeted::kNo, controlPixelData.begin(), 0);
|
||||
@ -64,10 +64,8 @@ void runFPTest(skiatest::Reporter* reporter, GrContext* context,
|
||||
std::move(fpProxy));
|
||||
REPORTER_ASSERT(reporter, sContext);
|
||||
|
||||
bool result = context->contextPriv().readSurfacePixels(sContext.get(),
|
||||
0, 0, DEV_W, DEV_H,
|
||||
desc.fConfig, nullptr,
|
||||
readBuffer.begin(), 0);
|
||||
bool result = context->contextPriv().readSurfacePixels(
|
||||
sContext.get(), 0, 0, DEV_W, DEV_H, colorType, nullptr, readBuffer.begin(), 0);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
REPORTER_ASSERT(reporter,
|
||||
0 == memcmp(readBuffer.begin(), controlPixelData.begin(), readBuffer.bytes()));
|
||||
@ -79,16 +77,16 @@ static const float kMaxIntegerRepresentableInSPFloatingPoint = 16777216; // 2 ^
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(FloatingPointTextureTest, reporter, ctxInfo) {
|
||||
runFPTest<float>(reporter, ctxInfo.grContext(), FLT_MIN, FLT_MAX, FLT_EPSILON,
|
||||
kMaxIntegerRepresentableInSPFloatingPoint,
|
||||
RGBA32F_CONTROL_ARRAY_SIZE, kRGBA_float_GrPixelConfig);
|
||||
kMaxIntegerRepresentableInSPFloatingPoint, RGBA32F_CONTROL_ARRAY_SIZE,
|
||||
GrColorType::kRGBA_F32);
|
||||
}
|
||||
|
||||
static const int RG32F_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 2;
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(FloatingPointTextureTest_RG, reporter, ctxInfo) {
|
||||
runFPTest<float>(reporter, ctxInfo.grContext(), FLT_MIN, FLT_MAX, FLT_EPSILON,
|
||||
kMaxIntegerRepresentableInSPFloatingPoint,
|
||||
RG32F_CONTROL_ARRAY_SIZE, kRG_float_GrPixelConfig);
|
||||
kMaxIntegerRepresentableInSPFloatingPoint, RG32F_CONTROL_ARRAY_SIZE,
|
||||
GrColorType::kRG_F32);
|
||||
}
|
||||
|
||||
static const int HALF_ALPHA_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 1 /*alpha-only*/;
|
||||
@ -96,16 +94,16 @@ static const SkHalf kMaxIntegerRepresentableInHalfFloatingPoint = 0x6800; // 2
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(HalfFloatAlphaTextureTest, reporter, ctxInfo) {
|
||||
runFPTest<SkHalf>(reporter, ctxInfo.grContext(), SK_HalfMin, SK_HalfMax, SK_HalfEpsilon,
|
||||
kMaxIntegerRepresentableInHalfFloatingPoint,
|
||||
HALF_ALPHA_CONTROL_ARRAY_SIZE, kAlpha_half_GrPixelConfig);
|
||||
kMaxIntegerRepresentableInHalfFloatingPoint, HALF_ALPHA_CONTROL_ARRAY_SIZE,
|
||||
GrColorType::kAlpha_F16);
|
||||
}
|
||||
|
||||
static const int HALF_RGBA_CONTROL_ARRAY_SIZE = DEV_W * DEV_H * 4 /*RGBA*/;
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(HalfFloatRGBATextureTest, reporter, ctxInfo) {
|
||||
runFPTest<SkHalf>(reporter, ctxInfo.grContext(), SK_HalfMin, SK_HalfMax, SK_HalfEpsilon,
|
||||
kMaxIntegerRepresentableInHalfFloatingPoint,
|
||||
HALF_RGBA_CONTROL_ARRAY_SIZE, kRGBA_half_GrPixelConfig);
|
||||
kMaxIntegerRepresentableInHalfFloatingPoint, HALF_RGBA_CONTROL_ARRAY_SIZE,
|
||||
GrColorType::kRGBA_F16);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -289,10 +289,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SRGBReadWritePixels, reporter, ctxInfo) {
|
||||
// Write data to an untagged context. The write does no conversion no matter what encoding the
|
||||
// src data has.
|
||||
for (auto writeEncoding : {Encoding::kSRGB, Encoding::kUntagged, Encoding::kLinear}) {
|
||||
// Currently this converts to sRGB when we read. TODO: Should reading from an untagged
|
||||
// context to sRGB fail or do no conversion?
|
||||
do_test(Encoding::kUntagged, writeEncoding, Encoding::kSRGB, error,
|
||||
check_linear_to_srgb_conversion, context, reporter);
|
||||
// The read from untagged to sRGB also does no conversion. TODO: Should it just fail?
|
||||
do_test(Encoding::kUntagged, writeEncoding, Encoding::kSRGB, error, check_no_conversion,
|
||||
context, reporter);
|
||||
// Reading untagged back as untagged should do no conversion.
|
||||
do_test(Encoding::kUntagged, writeEncoding, Encoding::kUntagged, error, check_no_conversion,
|
||||
context, reporter);
|
||||
|
@ -62,7 +62,7 @@ bool does_full_buffer_contain_correct_values(GrColor* srcBuffer,
|
||||
return true;
|
||||
}
|
||||
|
||||
void basic_transfer_test(skiatest::Reporter* reporter, GrContext* context, GrPixelConfig config,
|
||||
void basic_transfer_test(skiatest::Reporter* reporter, GrContext* context, GrColorType colorType,
|
||||
GrSurfaceOrigin origin, bool renderTarget) {
|
||||
if (GrCaps::kNone_MapFlags == context->caps()->mapBufferFlags()) {
|
||||
return;
|
||||
@ -97,89 +97,102 @@ void basic_transfer_test(skiatest::Reporter* reporter, GrContext* context, GrPix
|
||||
memcpy(data, srcBuffer.get(), size);
|
||||
buffer->unmap();
|
||||
|
||||
// create texture
|
||||
GrSurfaceDesc desc;
|
||||
desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
|
||||
desc.fOrigin = origin;
|
||||
desc.fWidth = kTextureWidth;
|
||||
desc.fHeight = kTextureHeight;
|
||||
desc.fConfig = config;
|
||||
desc.fSampleCnt = 1;
|
||||
sk_sp<GrTexture> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
|
||||
for (auto srgbEncoding : {GrSRGBEncoded::kNo, GrSRGBEncoded::kYes}) {
|
||||
// create texture
|
||||
GrSurfaceDesc desc;
|
||||
desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
|
||||
desc.fOrigin = origin;
|
||||
desc.fWidth = kTextureWidth;
|
||||
desc.fHeight = kTextureHeight;
|
||||
desc.fConfig = GrColorTypeToPixelConfig(colorType, srgbEncoding);
|
||||
desc.fSampleCnt = 1;
|
||||
|
||||
//////////////////////////
|
||||
// transfer full data
|
||||
if (kUnknown_GrPixelConfig == desc.fConfig) {
|
||||
SkASSERT(GrSRGBEncoded::kYes == srgbEncoding);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool result;
|
||||
result = gpu->transferPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight,
|
||||
config, buffer.get(), 0, rowBytes);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
if (!context->caps()->isConfigTexturable(desc.fConfig) ||
|
||||
(renderTarget && !context->caps()->isConfigRenderable(desc.fConfig))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(dstBuffer.get(), 0xCDCD, size);
|
||||
result = gpu->readPixels(tex.get(), origin, 0, 0, kTextureWidth, kTextureHeight,
|
||||
config, dstBuffer.get(), rowBytes);
|
||||
if (result) {
|
||||
REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
|
||||
dstBuffer,
|
||||
kTextureWidth,
|
||||
kTextureHeight,
|
||||
kBufferWidth,
|
||||
kBufferHeight,
|
||||
origin));
|
||||
}
|
||||
sk_sp<GrTexture> tex = resourceProvider->createTexture(desc, SkBudgeted::kNo);
|
||||
|
||||
//////////////////////////
|
||||
// transfer partial data
|
||||
//////////////////////////
|
||||
// transfer full data
|
||||
|
||||
const int kLeft = 2;
|
||||
const int kTop = 10;
|
||||
const int kWidth = 10;
|
||||
const int kHeight = 2;
|
||||
bool result;
|
||||
result = gpu->transferPixels(tex.get(), 0, 0, kTextureWidth, kTextureHeight, colorType,
|
||||
buffer.get(), 0, rowBytes);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
|
||||
// change color of subrectangle
|
||||
fill_transfer_data(kLeft, kTop, kWidth, kHeight, kBufferWidth, srcBuffer.get());
|
||||
data = buffer->map();
|
||||
memcpy(data, srcBuffer.get(), size);
|
||||
buffer->unmap();
|
||||
memset(dstBuffer.get(), 0xCDCD, size);
|
||||
result = gpu->readPixels(tex.get(), origin, 0, 0, kTextureWidth, kTextureHeight, colorType,
|
||||
dstBuffer.get(), rowBytes);
|
||||
if (result) {
|
||||
REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
|
||||
dstBuffer,
|
||||
kTextureWidth,
|
||||
kTextureHeight,
|
||||
kBufferWidth,
|
||||
kBufferHeight,
|
||||
origin));
|
||||
}
|
||||
|
||||
size_t offset = sizeof(GrColor)*(kTop*kBufferWidth + kLeft);
|
||||
result = gpu->transferPixels(tex.get(), kLeft, kTop, kWidth, kHeight, config,
|
||||
buffer.get(), offset, rowBytes);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
//////////////////////////
|
||||
// transfer partial data
|
||||
|
||||
memset(dstBuffer.get(), 0xCDCD, size);
|
||||
result = gpu->readPixels(tex.get(), origin, 0, 0, kTextureWidth, kTextureHeight,
|
||||
config, dstBuffer.get(), rowBytes);
|
||||
if (result) {
|
||||
REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
|
||||
dstBuffer,
|
||||
kTextureWidth,
|
||||
kTextureHeight,
|
||||
kBufferWidth,
|
||||
kBufferHeight,
|
||||
origin));
|
||||
const int kLeft = 2;
|
||||
const int kTop = 10;
|
||||
const int kWidth = 10;
|
||||
const int kHeight = 2;
|
||||
|
||||
// change color of subrectangle
|
||||
fill_transfer_data(kLeft, kTop, kWidth, kHeight, kBufferWidth, srcBuffer.get());
|
||||
data = buffer->map();
|
||||
memcpy(data, srcBuffer.get(), size);
|
||||
buffer->unmap();
|
||||
|
||||
size_t offset = sizeof(GrColor) * (kTop * kBufferWidth + kLeft);
|
||||
result = gpu->transferPixels(tex.get(), kLeft, kTop, kWidth, kHeight, colorType,
|
||||
buffer.get(), offset, rowBytes);
|
||||
REPORTER_ASSERT(reporter, result);
|
||||
|
||||
memset(dstBuffer.get(), 0xCDCD, size);
|
||||
result = gpu->readPixels(tex.get(), origin, 0, 0, kTextureWidth, kTextureHeight, colorType,
|
||||
dstBuffer.get(), rowBytes);
|
||||
if (result) {
|
||||
REPORTER_ASSERT(reporter, does_full_buffer_contain_correct_values(srcBuffer,
|
||||
dstBuffer,
|
||||
kTextureWidth,
|
||||
kTextureHeight,
|
||||
kBufferWidth,
|
||||
kBufferHeight,
|
||||
origin));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(TransferPixelsTest, reporter, ctxInfo) {
|
||||
// RGBA
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kRGBA_8888,
|
||||
kTopLeft_GrSurfaceOrigin, false);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kRGBA_8888,
|
||||
kTopLeft_GrSurfaceOrigin, true);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kRGBA_8888,
|
||||
kBottomLeft_GrSurfaceOrigin, false);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kRGBA_8888_GrPixelConfig,
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kRGBA_8888,
|
||||
kBottomLeft_GrSurfaceOrigin, true);
|
||||
|
||||
// BGRA
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kBGRA_8888,
|
||||
kTopLeft_GrSurfaceOrigin, false);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kBGRA_8888,
|
||||
kTopLeft_GrSurfaceOrigin, true);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kBGRA_8888,
|
||||
kBottomLeft_GrSurfaceOrigin, false);
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), kBGRA_8888_GrPixelConfig,
|
||||
basic_transfer_test(reporter, ctxInfo.grContext(), GrColorType::kBGRA_8888,
|
||||
kBottomLeft_GrSurfaceOrigin, true);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user