1ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed/* 2ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed * Copyright 2017 Google Inc. 3ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed * 4ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed * Use of this source code is governed by a BSD-style license that can be 5ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed * found in the LICENSE file. 6ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed */ 7ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 8ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkSpriteBlitter.h" 9ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkArenaAlloc.h" 10ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkBlitRow.h" 11ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkColorFilter.h" 12ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkColorData.h" 1375ae421c24ee7ab5a86334e43404b24a6a6fb1f4Mike Reed#include "SkPaint.h" 14ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkTemplates.h" 15ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkUtils.h" 16ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed#include "SkXfermodePriv.h" 17ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 18ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed/////////////////////////////////////////////////////////////////////////////// 19ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 20ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic void S32_src(uint16_t dst[], const SkPMColor src[], int count) { 21ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed for (int i = 0; i < count; ++i) { 22ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed dst[i] = SkPixel32ToPixel16(src[i]); 23ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 24ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed} 25ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 26ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic void S32_srcover(uint16_t dst[], const SkPMColor src[], int count) { 27ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed for (int i = 0; i < count; ++i) { 28ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed dst[i] = SkSrcOver32To16(src[i], dst[i]); 29ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 30ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed} 31ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 32ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedclass Sprite_D16_S32 : public SkSpriteBlitter { 33ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedpublic: 34ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed Sprite_D16_S32(const SkPixmap& src, SkBlendMode mode) : INHERITED(src) { 35ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkASSERT(src.colorType() == kN32_SkColorType); 36ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver); 37ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 38ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed fUseSrcOver = (mode == SkBlendMode::kSrcOver) && !src.isOpaque(); 39ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 40ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 41ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed void blitRect(int x, int y, int width, int height) override { 42ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkASSERT(width > 0 && height > 0); 43ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed uint16_t* SK_RESTRICT dst = fDst.writable_addr16(x, y); 44ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); 45ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed size_t dstRB = fDst.rowBytes(); 46ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed size_t srcRB = fSource.rowBytes(); 47ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 48ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed do { 49ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (fUseSrcOver) { 50ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed S32_srcover(dst, src, width); 51ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } else { 52ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed S32_src(dst, src, width); 53ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 54ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 55ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed dst = (uint16_t* SK_RESTRICT)((char*)dst + dstRB); 56ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 57ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } while (--height != 0); 58ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 59ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 60ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedprivate: 61ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed bool fUseSrcOver; 62ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 63ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed typedef SkSpriteBlitter INHERITED; 64ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}; 65ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 66ef8ce2858b7692c9ec9874c43656e603f304c760Mike ReedSkSpriteBlitter* SkSpriteBlitter::ChooseL565(const SkPixmap& source, const SkPaint& paint, 67ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkArenaAlloc* allocator) { 68ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkASSERT(allocator != nullptr); 69ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 70ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (paint.getColorFilter() != nullptr) { 71ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return nullptr; 72ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 73ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (paint.getMaskFilter() != nullptr) { 74ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return nullptr; 75ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 76ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 77ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed U8CPU alpha = paint.getAlpha(); 78ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (alpha != 0xFF) { 79ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return nullptr; 80ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 81ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 82ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (source.colorType() == kN32_SkColorType) { 83ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed switch (paint.getBlendMode()) { 84ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed case SkBlendMode::kSrc: 85ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed case SkBlendMode::kSrcOver: 86ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return allocator->make<Sprite_D16_S32>(source, paint.getBlendMode()); 87ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed default: 88ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed break; 89ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 90ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 91ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return nullptr; 92ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed} 93ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 94ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed////////////////////////////////////////////////////////////////////////////////////////////////// 95ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 96ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic unsigned div255(unsigned a, unsigned b) { 97ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return (a * b * 257 + 127) >> 16; 98ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed} 99ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 100ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic void S32_src_da8(uint8_t dst[], const SkPMColor src[], int count) { 101ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed for (int i = 0; i < count; ++i) { 102ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed dst[i] = SkGetPackedA32(src[i]); 103ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 104ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed} 105ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 106ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedstatic void S32_srcover_da8(uint8_t dst[], const SkPMColor src[], int count) { 107ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed for (int i = 0; i < count; ++i) { 108ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkPMColor c = src[i]; 109ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (c) { 110ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed unsigned a = SkGetPackedA32(c); 111ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (a == 0xFF) { 112ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed dst[i] = 0xFF; 113ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } else { 114ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed dst[i] = a + div255(255 - a, dst[i]); 115ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 116ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 117ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 118ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed} 119ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 120ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedclass Sprite_D8_S32 : public SkSpriteBlitter { 121ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedpublic: 122ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed Sprite_D8_S32(const SkPixmap& src, SkBlendMode mode) : INHERITED(src) { 123ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkASSERT(src.colorType() == kN32_SkColorType); 124ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver); 125ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 126ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed fUseSrcOver = (mode == SkBlendMode::kSrcOver) && !src.isOpaque(); 127ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 128ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 129ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed void blitRect(int x, int y, int width, int height) override { 130ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkASSERT(width > 0 && height > 0); 131ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed uint8_t* SK_RESTRICT dst = fDst.writable_addr8(x, y); 132ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); 133ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed size_t dstRB = fDst.rowBytes(); 134ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed size_t srcRB = fSource.rowBytes(); 135ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 136ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed do { 137ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (fUseSrcOver) { 138ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed S32_srcover_da8(dst, src, width); 139ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } else { 140ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed S32_src_da8(dst, src, width); 141ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 142ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 143ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed dst = (uint8_t* SK_RESTRICT)((char*)dst + dstRB); 144ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 145ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } while (--height != 0); 146ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 147ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 148ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reedprivate: 149ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed bool fUseSrcOver; 150ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 151ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed typedef SkSpriteBlitter INHERITED; 152ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed}; 153ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 154ef8ce2858b7692c9ec9874c43656e603f304c760Mike ReedSkSpriteBlitter* SkSpriteBlitter::ChooseLA8(const SkPixmap& source, const SkPaint& paint, 155ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkArenaAlloc* allocator) { 156ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed SkASSERT(allocator != nullptr); 157ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 158ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (paint.getColorFilter() != nullptr) { 159ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return nullptr; 160ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 161ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (paint.getMaskFilter() != nullptr) { 162ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return nullptr; 163ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 164ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 165ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed U8CPU alpha = paint.getAlpha(); 166ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (alpha != 0xFF) { 167ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return nullptr; 168ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 169ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed 170ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed if (source.colorType() == kN32_SkColorType) { 171ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed switch (paint.getBlendMode()) { 172ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed case SkBlendMode::kSrc: 173ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed case SkBlendMode::kSrcOver: 174ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return allocator->make<Sprite_D8_S32>(source, paint.getBlendMode()); 175ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed default: 176ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed break; 177ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 178ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed } 179ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed return nullptr; 180ef8ce2858b7692c9ec9874c43656e603f304c760Mike Reed} 181