Flutter Engine
The Flutter Engine
bc1_transparency.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 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/gm.h"
21
22constexpr int kImgWidth = 16;
23constexpr int kImgHeight = 8;
24constexpr int kPad = 4;
25
26struct BC1Block {
27 uint16_t fColor0;
28 uint16_t fColor1;
29 uint32_t fIndices;
30};
31
32static int num_4x4_blocks(int size) {
33 return ((size + 3) & ~3) >> 2;
34}
35
36static uint16_t to565(SkColor col) {
37 int r5 = SkMulDiv255Round(31, SkColorGetR(col));
38 int g6 = SkMulDiv255Round(63, SkColorGetG(col));
39 int b5 = SkMulDiv255Round(31, SkColorGetB(col));
40
41 return (r5 << 11) | (g6 << 5) | b5;
42}
43
44// BC1 has per-block transparency. If, taken as ints,
45// fColor0 < fColor1 -> the block has transparency (& it is in color3)
46// fColor1 > fColor0 -> the block is opaque
47//
48// This method can create two blocks to test out BC1's behavior. If BC1
49// behaves as expected (i.e., w/ per-block transparency) then, for RGBA textures,
50// the transparent block(s) should appear as:
51// opaque black, medium grey, transparent black, white.
52// and the opaque block(s) should appear as:
53// opaque black, dark grey, light grey, white
54//
55// For RGB textures, however, the transparent block(s) should appear as:
56// opaque black, medium grey, _opaque_ black, white
57// and the opaque block(s) should appear as:
58// opaque black, dark grey, light grey, white.
59static void create_BC1_block(BC1Block* block, bool transparent) {
60 unsigned int byte;
61
62 if (transparent) {
63 block->fColor0 = to565(SK_ColorBLACK);
64 block->fColor1 = to565(SK_ColorWHITE);
65 SkASSERT(block->fColor0 <= block->fColor1); // this signals a transparent block
66 // opaque black (col0), medium grey (col2), transparent black (col3), white (col1).
67 byte = (0x0 << 0) | (0x2 << 2) | (0x3 << 4) | (0x1 << 6);
68 } else {
69 block->fColor0 = to565(SK_ColorWHITE);
70 block->fColor1 = to565(SK_ColorBLACK);
71 SkASSERT(block->fColor0 > block->fColor1); // this signals an opaque block
72 // opaque black (col1), dark grey (col3), light grey (col2), white (col0)
73 byte = (0x1 << 0) | (0x3 << 2) | (0x2 << 4) | (0x0 << 6);
74 }
75
76 block->fIndices = (byte << 24) | (byte << 16) | (byte << 8) | byte;
77}
78
79// This makes a 16x8 BC1 texture which has the top 4 rows be officially transparent
80// and the bottom 4 rows be officially opaque.
83
85 nullptr, false);
86
88 BC1Block* dstBlocks = reinterpret_cast<BC1Block*>(tmp->writable_data());
89
90 BC1Block transBlock, opaqueBlock;
91 create_BC1_block(&transBlock, true);
92 create_BC1_block(&opaqueBlock, false);
93
94 int numXBlocks = num_4x4_blocks(kImgWidth);
95 int numYBlocks = num_4x4_blocks(kImgHeight);
96
97 for (int y = 0; y < numYBlocks; ++y) {
98 for (int x = 0; x < numXBlocks; ++x) {
99 dstBlocks[y*numXBlocks + x] = (y < numYBlocks/2) ? transBlock : opaqueBlock;
100 }
101 }
102
103 return tmp;
104}
105
107 SkTextureCompressionType compression) {
108 if (direct) {
110 direct, std::move(data), kImgWidth, kImgHeight, compression, skgpu::Mipmapped::kNo);
111 } else {
113 std::move(data), kImgWidth, kImgHeight, compression);
114 }
115}
116
117static void draw_image(SkCanvas* canvas, sk_sp<SkImage> image, int x, int y) {
118
119 bool isCompressed = false;
120 if (image && image->isTextureBacked()) {
121 const GrCaps* caps = as_IB(image)->context()->priv().caps();
123 canvas->recordingContext());
124 isCompressed = caps->isFormatCompressed(proxy->backendFormat());
125 }
126
127 canvas->drawImage(image, x, y);
128
129 if (!isCompressed) {
131 r.outset(1.0f, 1.0f);
132
133 SkPaint redStroke;
134 redStroke.setColor(SK_ColorRED);
136 redStroke.setStrokeWidth(2.0f);
137
138 canvas->drawRect(r, redStroke);
139 }
140}
141
142namespace skiagm {
143
144// This GM draws the BC1 compressed texture filled with "make_compressed_data"s data twice.
145//
146// It is drawn once (on the top) as a kBC1_RGB8_UNORM texture and then again (on the bottom)
147// as a kBC1_RGBA8_UNORM texture.
148//
149// If BC1 behaves as expected we should see:
150//
151// RGB8 Black MidGrey Black* White ...
152// Black DrkGrey LtGrey White ...
153//
154// RGBA8 Black MidGrey Green+ White ...
155// Black DrkGrey LtGrey White ...
156//
157// * We expect this to be black bc the transparent black will be forced to opaque. If BC1 were
158// treating it as an opaque block then it would be LtGrey - not black.
159// + This is just the background showing through the transparent black
160class BC1TransparencyGM : public GM {
161public:
164 }
165
166protected:
167 SkString getName() const override { return SkString("bc1_transparency"); }
168
169 SkISize getISize() override {
170 return SkISize::Make(kImgWidth + 2 * kPad, 2 * kImgHeight + 3 * kPad);
171 }
172
174 auto dContext = GrAsDirectContext(canvas->recordingContext());
175 if (dContext && dContext->abandoned()) {
176 // This isn't a GpuGM so a null 'context' is okay but an abandoned context
177 // if forbidden.
178 return DrawResult::kSkip;
179 }
180
182
183 fRGBImage = data_to_img(dContext, bc1Data, SkTextureCompressionType::kBC1_RGB8_UNORM);
184 fRGBAImage = data_to_img(dContext, std::move(bc1Data),
186 if (!fRGBImage || !fRGBAImage) {
187 *errorMsg = "Failed to create BC1 images.";
188 return DrawResult::kFail;
189 }
190
191 return DrawResult::kOk;
192 }
193
194 void onGpuTeardown() override {
195 fRGBImage = nullptr;
196 fRGBAImage = nullptr;
197 }
198
199 void onDraw(SkCanvas* canvas) override {
200 draw_image(canvas, fRGBImage, kPad, kPad);
201 draw_image(canvas, fRGBAImage, kPad, 2 * kPad + kImgHeight);
202 }
203
204private:
205 sk_sp<SkImage> fRGBImage;
206 sk_sp<SkImage> fRGBAImage;
207
208 using INHERITED = GM;
209};
210
211//////////////////////////////////////////////////////////////////////////////
212
213DEF_GM(return new BC1TransparencyGM;)
214} // namespace skiagm
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SkColorGetR(color)
Definition: SkColor.h:65
#define SkColorGetG(color)
Definition: SkColor.h:69
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
#define SkColorGetB(color)
Definition: SkColor.h:73
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
size_t SkCompressedDataSize(SkTextureCompressionType type, SkISize dimensions, TArray< size_t > *individualMipOffsets, bool mipmapped)
static SkImage_Base * as_IB(SkImage *image)
Definition: SkImage_Base.h:201
static U8CPU SkMulDiv255Round(U16CPU a, U16CPU b)
Definition: SkMath.h:73
SkTextureCompressionType
constexpr int kPad
static uint16_t to565(SkColor col)
static int num_4x4_blocks(int size)
constexpr int kImgWidth
static sk_sp< SkImage > data_to_img(GrDirectContext *direct, sk_sp< SkData > data, SkTextureCompressionType compression)
static sk_sp< SkData > make_compressed_data()
constexpr int kImgHeight
static void create_BC1_block(BC1Block *block, bool transparent)
static void draw_image(SkCanvas *canvas, sk_sp< SkImage > image, int x, int y)
const GrCaps * caps() const
Definition: GrCaps.h:57
bool isFormatCompressed(const GrBackendFormat &format) const
Definition: GrCaps.cpp:457
GrImageContextPriv priv()
const GrBackendFormat & backendFormat() const
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition: SkData.cpp:116
void * writable_data()
Definition: SkData.h:52
virtual GrImageContext * context() const
Definition: SkImage_Base.h:112
virtual bool isTextureBacked() const =0
void setStyle(Style style)
Definition: SkPaint.cpp:105
void setColor(SkColor color)
Definition: SkPaint.cpp:119
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
void setStrokeWidth(SkScalar width)
Definition: SkPaint.cpp:159
T * get() const
Definition: SkRefCnt.h:303
SkString getName() const override
void onDraw(SkCanvas *canvas) override
DrawResult onGpuSetup(SkCanvas *canvas, SkString *errorMsg, GraphiteTestContext *) override
Definition: gm.h:110
GM(SkColor backgroundColor=SK_ColorWHITE)
Definition: gm.cpp:81
void setBGColor(SkColor)
Definition: gm.cpp:159
double y
double x
SK_API sk_sp< SkImage > TextureFromCompressedTextureData(GrDirectContext *direct, sk_sp< SkData > data, int width, int height, SkTextureCompressionType type, skgpu::Mipmapped mipmapped=skgpu::Mipmapped::kNo, GrProtected isProtected=GrProtected::kNo)
SK_API sk_sp< SkImage > RasterFromCompressedTextureData(sk_sp< SkData > data, int width, int height, SkTextureCompressionType type)
sk_sp< const SkImage > image
Definition: SkRecords.h:269
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
GrTextureProxy * GetTextureImageProxy(SkImage *image, GrRecordingContext *rContext)
Definition: ProxyUtils.cpp:32
DEF_GM(return F(C(clipbox), 0.0f, 0.0f, {})) DEF_GM(return F(C(clipbox)
DrawResult
Definition: gm.h:104
uint16_t fColor0
uint32_t fIndices
uint16_t fColor1
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
void outset(float dx, float dy)
Definition: SkRect.h:1077
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63