Skip to content

Commit

Permalink
Update SkColorType docs with bit patterns
Browse files Browse the repository at this point in the history
This helps alleviate the differences between some of the naming
conventions followed over the history of the enum and explicitly
calls out two names that differ from the primary convention of LE
bit ordering of channels.

Bug: b/390473370
Change-Id: I0cefbb93bfafb42e8393a5753ca2016072460028
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/941818
Commit-Queue: Michael Ludwig <[email protected]>
Reviewed-by: Robert Phillips <[email protected]>
  • Loading branch information
lhkbob authored and SkCQ committed Jan 24, 2025
1 parent a5c42ae commit 0f2833b
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 35 deletions.
146 changes: 114 additions & 32 deletions include/core/SkColorType.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,125 @@
kN32_SkColorType selects the native 32-bit ARGB format for the current configuration. This can
lead to inconsistent results across platforms, so use with caution.
*/
enum SkColorType : int {
kUnknown_SkColorType, //!< uninitialized
kAlpha_8_SkColorType, //!< pixel with alpha in 8-bit byte
kRGB_565_SkColorType, //!< pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
kARGB_4444_SkColorType, //!< pixel with 4 bits for alpha, red, green, blue; in 16-bit word
kRGBA_8888_SkColorType, //!< pixel with 8 bits for red, green, blue, alpha; in 32-bit word
kRGB_888x_SkColorType, //!< pixel with 8 bits each for red, green, blue; in 32-bit word
kBGRA_8888_SkColorType, //!< pixel with 8 bits for blue, green, red, alpha; in 32-bit word
kRGBA_1010102_SkColorType, //!< 10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
kBGRA_1010102_SkColorType, //!< 10 bits for blue, green, red; 2 bits for alpha; in 32-bit word
kRGB_101010x_SkColorType, //!< pixel with 10 bits each for red, green, blue; in 32-bit word
kBGR_101010x_SkColorType, //!< pixel with 10 bits each for blue, green, red; in 32-bit word
kBGR_101010x_XR_SkColorType, //!< pixel with 10 bits each for blue, green, red; in 32-bit word, extended range
kBGRA_10101010_XR_SkColorType, //!< pixel with 10 bits each for blue, green, red, alpha; in 64-bit word, extended range
kRGBA_10x6_SkColorType, //!< pixel with 10 used bits (most significant) followed by 6 unused
// bits for red, green, blue, alpha; in 64-bit word
kGray_8_SkColorType, //!< pixel with grayscale level in 8-bit byte
kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha;
// in 64-bit word
kRGBA_F16_SkColorType, //!< pixel with half floats for red, green, blue, alpha;
// in 64-bit word
kRGB_F16F16F16x_SkColorType, //!< pixel with half floats for red, green, blue; in 64-bit word
kRGBA_F32_SkColorType, //!< pixel using C float for red, green, blue, alpha; in 128-bit word
// The following 6 colortypes are just for reading from - not for rendering to
kR8G8_unorm_SkColorType, //!< pixel with a uint8_t for red and green
By default, Skia operates with the assumption of a little-Endian system. The names of each
SkColorType implicitly define the channel ordering and size in memory. Due to historical reasons
the names do not follow 100% identical convention, but are typically labeled from least
significant to most significant. To help clarify when the actual data layout differs from the
default convention, every SkColorType's comment includes a bit-labeled description of a pixel
in that color type on a LE system.
kA16_float_SkColorType, //!< pixel with a half float for alpha
kR16G16_float_SkColorType, //!< pixel with a half float for red and green
Unless specified otherwise, a channel's value is treated as an unsigned integer with a range of
of [0, 2^N-1] and this is mapped uniformly to a floating point value of [0.0, 1.0]. Some color
types instead store data directly in 32-bit floating point (assumed to be IEEE), or in 16-bit
"half" floating point values. A half float, or F16/float16, is interpreted as FP 1-5-10 or
Bits: [sign:15 exp:14..10 man:9..0]
*/
enum SkColorType : int {
// Unknown or unrepresentable as an SkColorType.
kUnknown_SkColorType,
// Single channel data (8-bit) interpreted as an alpha value. RGB are 0.
// Bits: [A:7..0]
kAlpha_8_SkColorType,
// Three channel BGR data (5 bits red, 6 bits green, 5 bits blue) packed into a LE 16-bit word.
// NOTE: The name of this enum value does not match the standard convention for SkColorType.
// Bits: [R:15..11 G:10..5 B:4..0]
kRGB_565_SkColorType,
// Four channel ABGR data (4 bits per channel) packed into a LE 16-bit word.
// NOTE: The name of this enum value does not match the standard convention for SkColorType.
// Bits: [R:15..12 G:11..8 B:7..4 A:3..0]
kARGB_4444_SkColorType,
// Four channel RGBA data (8 bits per channel) packed into a LE 32-bit word.
// Bits: [A:31..24 B:23..16 G:15..8 R:7..0]
kRGBA_8888_SkColorType,
// Three channel RGB data (8 bits per channel) packed into a LE 32-bit word. The remaining bits
// are ignored and alpha is forced to opaque.
// Bits: [x:31..24 B:23..16 G:15..8 R:7..0]
kRGB_888x_SkColorType,
// Four channel BGRA data (8 bits per channel) packed into a LE 32-bit word. R and B are swapped
// relative to kRGBA_8888.
// Bits: [A:31..24 R:23..16 G:15..8 B:7..0]
kBGRA_8888_SkColorType,
// Four channel RGBA data (10 bits per color, 2 bits for alpha) packed into a LE 32-bit word.
// Bits: [A:31..30 B:29..20 G:19..10 R:9..0]
kRGBA_1010102_SkColorType,
// Four channel BGRA data (10 bits per color, 2 bits for alpha) packed into a LE 32-bit word.
// R and B are swapped relative to kRGBA_1010102.
// Bits: [A:31..30 R:29..20 G:19..10 B:9..0]
kBGRA_1010102_SkColorType,
// Three channel RGB data (10 bits per channel) packed into a LE 32-bit word. The remaining bits
// are ignored and alpha is forced to opaque.
// Bits: [x:31..30 B:29..20 G:19..10 R:9..0]
kRGB_101010x_SkColorType,
// Three channel BGR data (10 bits per channel) packed into a LE 32-bit word. The remaining bits
// are ignored and alpha is forced to opaque. R and B are swapped relative to kRGB_101010x.
// Bits: [x:31..30 R:29..20 G:19..10 B:9..0]
kBGR_101010x_SkColorType,
// Three channel BGR data (10 bits per channel) packed into a LE 32-bit word. The remaining bits
// are ignored and alpha is forced to opaque. Instead of normalizing [0, 1023] to [0.0, 1.0] the
// color channels map to an extended range of [-0.752941, 1.25098], compatible with
// MTLPixelFormatBGR10_XR.
// Bits: [x:31..30 R:29..20 G:19..10 B:9..0]
kBGR_101010x_XR_SkColorType,
// Four channel BGRA data (10 bits per channel) packed into a LE 64-bit word. Each channel is
// preceded by 6 bits of padding. Instead of normalizing [0, 1023] to [0.0, 1.0] the color and
// alpha channels map to an extended range of [-0.752941, 1.25098], compatible with
// MTLPixelFormatBGRA10_XR.
// Bits: [A:63..54 x:53..48 R:47..38 x:37..32 G:31..22 x:21..16 B:15..6 x:5..0]
kBGRA_10101010_XR_SkColorType,
// Four channel RGBA data (10 bits per channel) packed into a LE 64-bit word. Each channel is
// preceded by 6 bits of padding.
// Bits: [A:63..54 x:53..48 B:47..38 x:37..32 G:31..22 x:21..16 R:15..6 x:5..0]
kRGBA_10x6_SkColorType,
// Single channel data (8-bit) interpreted as a grayscale value (e.g. replicated to RGB).
// Bits: [G:7..0]
kGray_8_SkColorType,
// Four channel RGBA data (16-bit half-float per channel) packed into a LE 64-bit word. Values
// are assumed to be in [0.0,1.0] range, unlike kRGBA_F16.
// Bits: [A:63..48 B:47..32 G:31..16 R:15..0]
kRGBA_F16Norm_SkColorType,
// Four channel RGBA data (16-bit half-float per channel) packed into a LE 64-bit word.
// This has extended range compared to kRGBA_F16Norm.
// Bits: [A:63..48 B:47..32 G:31..16 R:15..0]
kRGBA_F16_SkColorType,
// Three channel RGB data (16-bit half-float per channel) packed into a LE 64-bit word. The last
// 16 bits are ignored and alpha is forced to opaque.
// Bits: [x:63..48 B:47..32 G:31..16 R:15..0]
kRGB_F16F16F16x_SkColorType,
// Four channel RGBA data (32-bit float per channel) packed into a LE 128-bit word.
// Bits: [A:127..96 B:95..64 G:63..32 R:31..0]
kRGBA_F32_SkColorType,

kA16_unorm_SkColorType, //!< pixel with a little endian uint16_t for alpha
kR16G16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red and green
kR16G16B16A16_unorm_SkColorType, //!< pixel with a little endian uint16_t for red, green, blue
// and alpha
// The following 8 colortypes are just for reading from - not for rendering to

// Two channel RG data (8 bits per channel). Blue is forced to 0, alpha is forced to opaque.
// Bits: [G:15..8 R:7..0]
kR8G8_unorm_SkColorType,
// Single channel data (16-bit half-float) interpreted as alpha. RGB are 0.
// Bits: [A:15..0]
kA16_float_SkColorType,
// Two channel RG data (16-bit half-float per channel) packed into a LE 32-bit word.
// Blue is forced to 0, alpha is forced to opaque.
// Bits: [G:31..16 R:15..0]
kR16G16_float_SkColorType,
// Single channel data (16 bits) interpreted as alpha. RGB are 0.
// Bits: [A:15..0]
kA16_unorm_SkColorType,
// Two channel RG data (16 bits per channel) packed into a LE 32-bit word. B is forced to 0,
// alpha is forced to opaque.
// Bits: [G:31..16 R:15..0]
kR16G16_unorm_SkColorType,
// Four channel RGBA data (16 bits per channel) packed into a LE 64-bit word.
// Bits: [A:63..48 B:47..32 G:31..16 R:15..0]
kR16G16B16A16_unorm_SkColorType,
// Four channel RGBA data (8 bits per channel) packed into a LE 32-bit word. The RGB values are
// assumed to be encoded with the sRGB transfer function, which can be decoded automatically
// by GPU hardware with certain texture formats.
// Bits: [A:31..24 B:23..16 G:15..8 R:7..0]
kSRGBA_8888_SkColorType,
// Single channel data (8 bits) interpreted as red. G and B are forced to 0, alpha is forced to
// opaque.
// Bits: [R:7..0]
kR8_unorm_SkColorType,

kLastEnum_SkColorType = kR8_unorm_SkColorType, //!< last valid value
Expand Down
2 changes: 1 addition & 1 deletion include/private/gpu/ganesh/GrTypesPriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ SK_MAKE_BITFIELD_CLASS_OPS(GpuPathRenderers)
enum class GrColorType {
kUnknown,
kAlpha_8,
kBGR_565,
kBGR_565, // This corresponds to kRGB_565_SkColorType, which is misnamed.
kRGB_565,
kABGR_4444, // This name differs from SkColorType. kARGB_4444_SkColorType is misnamed.
kRGBA_8888,
Expand Down
2 changes: 2 additions & 0 deletions src/gpu/graphite/dawn/DawnCaps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ void DawnCaps::initShaderCaps(const wgpu::Device& device) {
}

void DawnCaps::initFormatTable(const wgpu::Device& device) {
// NOTE: wgpu::TextureFormat's naming convention orders channels from least significant to most,
// matching the data address ordering of a little endian system.
FormatInfo* info;
// Format: RGBA8Unorm
{
Expand Down
7 changes: 5 additions & 2 deletions src/gpu/graphite/mtl/MtlCaps.mm
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@
}
}

// NOTE: MTLPixelFormat's naming convention orders channels from least significant to most,
// matching the data address ordering of a little endian system.

// Format: RGBA8Unorm
{
info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm)];
Expand Down Expand Up @@ -391,7 +394,7 @@
info->fColorTypeInfos =
std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
int ctIdx = 0;
// Format: B5G6R5Unorm, Surface: kBGR_565
// Format: B5G6R5Unorm, Surface: kRGB_565; misnamed SkColorType is really BGR data
{
auto& ctInfo = info->fColorTypeInfos[ctIdx++];
ctInfo.fColorType = kRGB_565_SkColorType;
Expand All @@ -409,7 +412,7 @@
info->fColorTypeInfos =
std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
int ctIdx = 0;
// Format: ABGR4Unorm, Surface: kABGR_4444
// Format: ABGR4Unorm, Surface: kARGB_4444; misnamed SkColorType is really ABGR data
{
auto& ctInfo = info->fColorTypeInfos[ctIdx++];
ctInfo.fColorType = kARGB_4444_SkColorType;
Expand Down
9 changes: 9 additions & 0 deletions src/gpu/graphite/vk/VulkanCaps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ void VulkanCaps::initFormatTable(const skgpu::VulkanInterface* interface,

std::fill_n(fColorTypeToFormatTable, kSkColorTypeCnt, VK_FORMAT_UNDEFINED);

// NOTE: VkFormat's naming convention orders channels from low address to high address when
// interpreting unpacked formats. For packed formats, the channels are ordered most significant
// to least significant (making them opposite of the unpacked).

// Go through all the formats and init their support surface and data ColorTypes.
// Format: VK_FORMAT_R8G8B8A8_UNORM
{
Expand Down Expand Up @@ -722,6 +726,11 @@ void VulkanCaps::initFormatTable(const skgpu::VulkanInterface* interface,
ctInfo.fColorType = ct;
ctInfo.fTransferColorType = ct;
ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag;
// The color type is misnamed and really stores ABGR data, but there is no
// SkColorType that matches this actual ARGB VkFormat data. Swapping R and B when
// rendering into it has it match the reported transfer color type, but we have to
// swap R and B when sampling as well. This only works so long as we don't present
// textures of this format to a screen that would not know about this swap.
ctInfo.fReadSwizzle = skgpu::Swizzle::BGRA();
ctInfo.fWriteSwizzle = skgpu::Swizzle::BGRA();
}
Expand Down

0 comments on commit 0f2833b

Please sign in to comment.