| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2016 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 | |
| 8 #include "gm.h" | |
| 9 #include "SkCanvas.h" | |
| 10 #include "SkImageInfo.h" | |
| 11 #include "SkXfermode.h" | |
| 12 #include "SkHalf.h" | |
| 13 #include "SkImage.h" | |
| 14 #include "SkPM4f.h" | |
| 15 | |
| 16 static SkPMColor f16_to_pmcolor(uint64_t src) { | |
| 17 SkPMColor dst; | |
| 18 const SkHalf* sptr = reinterpret_cast<const SkHalf*>(&src); | |
| 19 uint8_t* dptr = reinterpret_cast<uint8_t*>(&dst); | |
| 20 for (int i = 0; i < 4; ++i) { | |
| 21 float f = SkHalfToFloat(sptr[i]); | |
| 22 dptr[i] = SkToU8((int)(f * 255 + 0.5f)); | |
| 23 } | |
| 24 return dst; | |
| 25 } | |
| 26 | |
| 27 static SkPMColor u16_to_pmcolor(uint64_t src) { | |
| 28 SkPMColor dst; | |
| 29 const uint16_t* sptr = reinterpret_cast<const uint16_t*>(&src); | |
| 30 uint8_t* dptr = reinterpret_cast<uint8_t*>(&dst); | |
| 31 for (int i = 0; i < 4; ++i) { | |
| 32 dptr[i] = sptr[i] >> 8; | |
| 33 } | |
| 34 return dst; | |
| 35 } | |
| 36 | |
| 37 static SkImage* new_u64_image(const SkBitmap& src, uint32_t flags) { | |
| 38 SkBitmap dst; | |
| 39 dst.allocN32Pixels(src.width(), src.height()); | |
| 40 SkPixmap srcPM, dstPM; | |
| 41 src.peekPixels(&srcPM); | |
| 42 dst.peekPixels(&dstPM); | |
| 43 | |
| 44 for (int y = 0; y < srcPM.height(); ++y) { | |
| 45 for (int x = 0; x < srcPM.width(); ++x) { | |
| 46 uint64_t srcP = *srcPM.addr64(x, y); | |
| 47 uint32_t* dstP = dstPM.writable_addr32(x, y); | |
| 48 | |
| 49 if (flags & SkXfermode::kDstIsFloat16_U64Flag) { | |
| 50 *dstP = f16_to_pmcolor(srcP); | |
| 51 } else { | |
| 52 *dstP = u16_to_pmcolor(srcP); | |
| 53 } | |
| 54 } | |
| 55 } | |
| 56 return SkImage::NewRasterCopy(dstPM.info(), dstPM.addr(), dstPM.rowBytes()); | |
| 57 } | |
| 58 | |
| 59 static void draw_rect(SkCanvas* canvas, const SkRect& r, SkColor c, uint32_t u64
_flags, | |
| 60 const SkAlpha aa[]) { | |
| 61 const SkIRect ir = r.round(); | |
| 62 const SkImageInfo info = SkImageInfo::Make(ir.width(), ir.height(), | |
| 63 kRGBA_F16_SkColorType, kPremul_Sk
AlphaType); | |
| 64 | |
| 65 SkBitmap bm; | |
| 66 bm.allocPixels(info); | |
| 67 SkPixmap pm; | |
| 68 bm.peekPixels(&pm); | |
| 69 memset(pm.writable_addr(), 0, pm.getSafeSize()); | |
| 70 | |
| 71 if (SkColorGetA(c) == 0xFF) { | |
| 72 u64_flags |= SkXfermode::kSrcIsOpaque_PM4fFlag; | |
| 73 } | |
| 74 | |
| 75 const SkXfermode::U64State state { nullptr, u64_flags }; | |
| 76 | |
| 77 const SkPM4f src = SkColor4f::FromColor(c).premul(); | |
| 78 auto proc1 = SkXfermode::GetU64Proc1(SkXfermode::kSrcOver_Mode, u64_flags); | |
| 79 for (int y = 0; y < ir.height()/2; ++y) { | |
| 80 proc1(state, pm.writable_addr64(0, y), src, ir.width(), aa); | |
| 81 } | |
| 82 | |
| 83 SkPM4f buffer[1000]; | |
| 84 for (int i = 0; i < ir.width(); ++i) { | |
| 85 buffer[i] = src; | |
| 86 } | |
| 87 auto procN = SkXfermode::GetU64ProcN(SkXfermode::kSrcOver_Mode, u64_flags); | |
| 88 for (int y = ir.height()/2 + 1; y < ir.height(); ++y) { | |
| 89 procN(state, pm.writable_addr64(0, y), buffer, ir.width(), aa); | |
| 90 } | |
| 91 | |
| 92 SkAutoTUnref<SkImage> image(new_u64_image(bm, u64_flags)); | |
| 93 canvas->drawImage(image, r.left(), r.top(), nullptr); | |
| 94 } | |
| 95 | |
| 96 /* | |
| 97 * Test SkXfer4fProcs directly for src-over, comparing them to current SkColor
blits. | |
| 98 */ | |
| 99 DEF_SIMPLE_GM(xfer_u64_srcover, canvas, 580, 760) { | |
| 100 const int IW = 50; | |
| 101 const SkScalar W = IW; | |
| 102 const SkScalar H = 100; | |
| 103 | |
| 104 const int32_t flags[] = { | |
| 105 -1, // normal | |
| 106 0, // U16 components | |
| 107 SkXfermode::kDstIsFloat16_U64Flag, // F16 components | |
| 108 }; | |
| 109 const SkColor colors[] = { | |
| 110 SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, | |
| 111 0x88000000, 0x88FF0000, 0x8800FF00, 0x880000FF | |
| 112 }; | |
| 113 | |
| 114 uint8_t aa_scanline[IW]; | |
| 115 for (int i = 0; i < IW; ++i) { | |
| 116 aa_scanline[i] = i * 255 / (IW - 1); | |
| 117 } | |
| 118 uint8_t const* aa_table[] = { nullptr, aa_scanline }; | |
| 119 | |
| 120 SkBitmap mask; | |
| 121 mask.installPixels(SkImageInfo::MakeA8(IW, 1), aa_scanline, IW); | |
| 122 | |
| 123 canvas->translate(20, 20); | |
| 124 | |
| 125 const SkRect r = SkRect::MakeWH(W, H); | |
| 126 for (const uint8_t* aa : aa_table) { | |
| 127 canvas->save(); | |
| 128 for (auto flag : flags) { | |
| 129 canvas->save(); | |
| 130 for (SkColor c : colors) { | |
| 131 if (flag < 0) { | |
| 132 SkPaint p; | |
| 133 p.setColor(c); | |
| 134 if (aa) { | |
| 135 canvas->drawBitmapRect(mask, r, &p); | |
| 136 } else { | |
| 137 canvas->drawRect(r, p); | |
| 138 } | |
| 139 } else { | |
| 140 draw_rect(canvas, r, c, flag, aa); | |
| 141 } | |
| 142 canvas->translate(W + 20, 0); | |
| 143 } | |
| 144 canvas->restore(); | |
| 145 canvas->translate(0, H + 20); | |
| 146 } | |
| 147 canvas->restore(); | |
| 148 canvas->translate(0, (H + 20) * SK_ARRAY_COUNT(flags) + 20); | |
| 149 } | |
| 150 } | |
| OLD | NEW |