blob: 60864487b4371141b47d2fd9f906909ef5217a41 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/DitherUtils.h"
#ifndef SK_IGNORE_GPU_DITHER
#include "include/core/SkBitmap.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include <cstdint>
namespace skgpu {
float DitherRangeForConfig(SkColorType dstColorType) {
SkASSERT(dstColorType != kUnknown_SkColorType);
// We use 1 / (2^bitdepth-1) as the range since each channel can hold 2^bitdepth values
switch (dstColorType) {
// 4 bit
case kARGB_4444_SkColorType:
return 1 / 15.f;
// 6 bit
case kRGB_565_SkColorType:
return 1 / 63.f;
// 8 bit
case kAlpha_8_SkColorType:
case kGray_8_SkColorType:
case kR8_unorm_SkColorType:
case kR8G8_unorm_SkColorType:
case kRGB_888x_SkColorType:
case kRGBA_8888_SkColorType:
case kSRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
return 1 / 255.f;
// 10 bit
case kRGBA_1010102_SkColorType:
case kBGRA_1010102_SkColorType:
case kRGB_101010x_SkColorType:
case kBGR_101010x_SkColorType:
case kBGR_101010x_XR_SkColorType:
case kBGRA_10101010_XR_SkColorType:
case kRGBA_10x6_SkColorType:
return 1 / 1023.f;
// 16 bit
case kA16_unorm_SkColorType:
case kR16G16_unorm_SkColorType:
case kR16G16B16A16_unorm_SkColorType:
return 1 / 32767.f;
// Unknown
case kUnknown_SkColorType:
// Half
case kA16_float_SkColorType:
case kR16G16_float_SkColorType:
case kRGBA_F16_SkColorType:
case kRGB_F16F16F16x_SkColorType:
case kRGBA_F16Norm_SkColorType:
// Float
case kRGBA_F32_SkColorType:
return 0.f; // no dithering
}
SkUNREACHABLE;
}
SkBitmap MakeDitherLUT() {
static constexpr struct DitherTable {
constexpr DitherTable() : data() {
constexpr int kImgSize = 8; // if changed, also change value in sk_dither_shader
for (int x = 0; x < kImgSize; ++x) {
for (int y = 0; y < kImgSize; ++y) {
// The computation of 'm' and 'value' is lifted from CPU backend.
unsigned int m = (y & 1) << 5 | (x & 1) << 4 |
(y & 2) << 2 | (x & 2) << 1 |
(y & 4) >> 1 | (x & 4) >> 2;
float value = float(m) * 1.0 / 64.0 - 63.0 / 128.0;
// Bias by 0.5 to be in 0..1, mul by 255 and round to nearest int to make byte.
data[y * 8 + x] = (uint8_t)((value + 0.5) * 255.f + 0.5f);
}
}
}
uint8_t data[64];
} gTable;
SkBitmap bmp;
bmp.setInfo(SkImageInfo::MakeA8(8, 8));
bmp.setPixels(const_cast<uint8_t*>(gTable.data));
bmp.setImmutable();
return bmp;
}
} // namespace skgpu
#endif // SK_IGNORE_GPU_DITHER