SkBlitter_RGB565.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright 2017 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/core/SkShader.h"
  8. #include "include/private/SkColorData.h"
  9. #include "include/private/SkColorData.h"
  10. #include "src/core/SkCoreBlitters.h"
  11. #include "src/core/SkXfermodePriv.h"
  12. #include "src/utils/SkUTF.h"
  13. #include "include/private/SkNx.h"
  14. static void D16_S32X_src(uint16_t dst[], const SkPMColor src[], int count, uint8_t coverage) {
  15. SkASSERT(coverage == 0xFF);
  16. for (int i = 0; i < count; ++i) {
  17. dst[i] = SkPixel32ToPixel16(src[i]);
  18. }
  19. }
  20. static void D16_S32X_src_coverage(uint16_t dst[], const SkPMColor src[], int count,
  21. uint8_t coverage) {
  22. switch (coverage) {
  23. case 0: break;
  24. case 0xFF:
  25. for (int i = 0; i < count; ++i) {
  26. dst[i] = SkPixel32ToPixel16(src[i]);
  27. }
  28. break;
  29. default:
  30. unsigned scale = coverage + (coverage >> 7);
  31. for (int i = 0; i < count; ++i) {
  32. dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]);
  33. }
  34. break;
  35. }
  36. }
  37. static void D16_S32A_srcover(uint16_t dst[], const SkPMColor src[], int count, uint8_t coverage) {
  38. SkASSERT(coverage == 0xFF);
  39. for (int i = 0; i < count; ++i) {
  40. dst[i] = SkSrcOver32To16(src[i], dst[i]);
  41. }
  42. }
  43. static void D16_S32A_srcover_coverage(uint16_t dst[], const SkPMColor src[], int count,
  44. uint8_t coverage) {
  45. switch (coverage) {
  46. case 0: break;
  47. case 0xFF:
  48. for (int i = 0; i < count; ++i) {
  49. dst[i] = SkSrcOver32To16(src[i], dst[i]);
  50. }
  51. break;
  52. default:
  53. unsigned scale = coverage + (coverage >> 7);
  54. for (int i = 0; i < count; ++i) {
  55. dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]);
  56. }
  57. break;
  58. }
  59. }
  60. bool SkRGB565_Shader_Blitter::Supports(const SkPixmap& device, const SkPaint& paint) {
  61. if (device.colorType() != kRGB_565_SkColorType) {
  62. return false;
  63. }
  64. if (device.colorSpace()) {
  65. return false;
  66. }
  67. if (paint.getBlendMode() != SkBlendMode::kSrcOver &&
  68. paint.getBlendMode() != SkBlendMode::kSrc) {
  69. return false;
  70. }
  71. if (paint.isDither()) {
  72. return false;
  73. }
  74. return true;
  75. }
  76. SkRGB565_Shader_Blitter::SkRGB565_Shader_Blitter(const SkPixmap& device,
  77. const SkPaint& paint, SkShaderBase::Context* shaderContext)
  78. : INHERITED(device, paint, shaderContext)
  79. {
  80. SkASSERT(shaderContext);
  81. SkASSERT(Supports(device, paint));
  82. fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
  83. bool isOpaque = SkToBool(shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag);
  84. if (paint.getBlendMode() == SkBlendMode::kSrc || isOpaque) {
  85. fBlend = D16_S32X_src;
  86. fBlendCoverage = D16_S32X_src_coverage;
  87. } else { // srcover
  88. fBlend = isOpaque ? D16_S32X_src : D16_S32A_srcover;
  89. fBlendCoverage = isOpaque ? D16_S32X_src_coverage : D16_S32A_srcover_coverage;
  90. }
  91. }
  92. SkRGB565_Shader_Blitter::~SkRGB565_Shader_Blitter() {
  93. sk_free(fBuffer);
  94. }
  95. void SkRGB565_Shader_Blitter::blitH(int x, int y, int width) {
  96. SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
  97. uint16_t* device = fDevice.writable_addr16(x, y);
  98. SkPMColor* span = fBuffer;
  99. fShaderContext->shadeSpan(x, y, span, width);
  100. fBlend(device, span, width, 0xFF);
  101. }
  102. void SkRGB565_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha coverage[],
  103. const int16_t runs[]) {
  104. SkPMColor* span = fBuffer;
  105. uint16_t* device = fDevice.writable_addr16(x, y);
  106. auto* shaderContext = fShaderContext;
  107. for (;;) {
  108. int count = *runs;
  109. if (count <= 0) {
  110. break;
  111. }
  112. int aa = *coverage;
  113. if (aa) {
  114. shaderContext->shadeSpan(x, y, span, count);
  115. fBlendCoverage(device, span, count, aa);
  116. }
  117. device += count;
  118. runs += count;
  119. coverage += count;
  120. x += count;
  121. }
  122. }