OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrSWMaskHelper.h" | 8 #include "GrSWMaskHelper.h" |
9 | 9 |
10 #include "GrDrawState.h" | 10 #include "GrDrawState.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 kASTC_12x12_GrPixelConfig // kASTC_12x12_Format, | 43 kASTC_12x12_GrPixelConfig // kASTC_12x12_Format, |
44 }; | 44 }; |
45 GR_STATIC_ASSERT(0 == SkTextureCompressor::kLATC_Format); | 45 GR_STATIC_ASSERT(0 == SkTextureCompressor::kLATC_Format); |
46 GR_STATIC_ASSERT(1 == SkTextureCompressor::kR11_EAC_Format); | 46 GR_STATIC_ASSERT(1 == SkTextureCompressor::kR11_EAC_Format); |
47 GR_STATIC_ASSERT(2 == SkTextureCompressor::kASTC_12x12_Format); | 47 GR_STATIC_ASSERT(2 == SkTextureCompressor::kASTC_12x12_Format); |
48 GR_STATIC_ASSERT(SK_ARRAY_COUNT(configMap) == SkTextureCompressor::kFormatCn
t); | 48 GR_STATIC_ASSERT(SK_ARRAY_COUNT(configMap) == SkTextureCompressor::kFormatCn
t); |
49 | 49 |
50 return configMap[fmt]; | 50 return configMap[fmt]; |
51 } | 51 } |
52 | 52 |
| 53 #if GR_COMPRESS_ALPHA_MASK |
| 54 static bool choose_compressed_fmt(const GrDrawTargetCaps* caps, |
| 55 SkTextureCompressor::Format *fmt) { |
| 56 if (NULL == fmt) { |
| 57 return false; |
| 58 } |
| 59 |
| 60 // We can't use scratch textures without the ability to update |
| 61 // compressed textures... |
| 62 if (!(caps->compressedTexSubImageSupport())) { |
| 63 return false; |
| 64 } |
| 65 |
| 66 // Figure out what our preferred texture type is. If ASTC is available, that
always |
| 67 // gives the biggest win. Otherwise, in terms of compression speed and accur
acy, |
| 68 // LATC has a slight edge over R11 EAC. |
| 69 if (caps->isConfigTexturable(kASTC_12x12_GrPixelConfig)) { |
| 70 *fmt = SkTextureCompressor::kASTC_12x12_Format; |
| 71 return true; |
| 72 } else if (caps->isConfigTexturable(kLATC_GrPixelConfig)) { |
| 73 *fmt = SkTextureCompressor::kLATC_Format; |
| 74 return true; |
| 75 } else if (caps->isConfigTexturable(kR11_EAC_GrPixelConfig)) { |
| 76 *fmt = SkTextureCompressor::kR11_EAC_Format; |
| 77 return true; |
| 78 } |
| 79 |
| 80 return false; |
| 81 } |
| 82 #endif |
| 83 |
53 } | 84 } |
54 | 85 |
55 /** | 86 /** |
56 * Draw a single rect element of the clip stack into the accumulation bitmap | 87 * Draw a single rect element of the clip stack into the accumulation bitmap |
57 */ | 88 */ |
58 void GrSWMaskHelper::draw(const SkRect& rect, SkRegion::Op op, | 89 void GrSWMaskHelper::draw(const SkRect& rect, SkRegion::Op op, |
59 bool antiAlias, uint8_t alpha) { | 90 bool antiAlias, uint8_t alpha) { |
60 SkPaint paint; | 91 SkPaint paint; |
61 | 92 |
62 SkXfermode* mode = SkXfermode::Create(op_to_mode(op)); | 93 SkXfermode* mode = SkXfermode::Create(op_to_mode(op)); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 fMatrix.setIdentity(); | 141 fMatrix.setIdentity(); |
111 } | 142 } |
112 | 143 |
113 // Now translate so the bound's UL corner is at the origin | 144 // Now translate so the bound's UL corner is at the origin |
114 fMatrix.postTranslate(-resultBounds.fLeft * SK_Scalar1, | 145 fMatrix.postTranslate(-resultBounds.fLeft * SK_Scalar1, |
115 -resultBounds.fTop * SK_Scalar1); | 146 -resultBounds.fTop * SK_Scalar1); |
116 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), | 147 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), |
117 resultBounds.height()); | 148 resultBounds.height()); |
118 | 149 |
119 #if GR_COMPRESS_ALPHA_MASK | 150 #if GR_COMPRESS_ALPHA_MASK |
120 fCompressedFormat = SkTextureCompressor::kR11_EAC_Format; | 151 fCompressMask = choose_compressed_fmt(fContext->getGpu()->caps(), &fCompress
edFormat); |
| 152 #else |
| 153 fCompressMask = false; |
| 154 #endif |
121 | 155 |
122 // Make sure that the width is a multiple of 16 so that we can use | 156 // Make sure that the width is a multiple of 16 so that we can use |
123 // specialized SIMD instructions that compress 4 blocks at a time. | 157 // specialized SIMD instructions that compress 4 blocks at a time. |
124 int dimX, dimY; | 158 int cmpWidth, cmpHeight; |
125 SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY); | 159 if (fCompressMask) { |
126 const int cmpWidth = dimX * ((bounds.fRight + (dimX - 1)) / dimX); | 160 int dimX, dimY; |
127 const int cmpHeight = dimY * ((bounds.fBottom + (dimY - 1)) / dimY); | 161 SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY)
; |
128 #else | 162 cmpWidth = dimX * ((bounds.fRight + (dimX - 1)) / dimX); |
129 const int cmpWidth = bounds.fRight; | 163 cmpHeight = dimY * ((bounds.fBottom + (dimY - 1)) / dimY); |
130 const int cmpHeight = bounds.fBottom; | 164 } else { |
131 #endif | 165 cmpWidth = bounds.fRight; |
| 166 cmpHeight = bounds.fBottom; |
| 167 } |
132 | 168 |
133 if (!fBM.allocPixels(SkImageInfo::MakeA8(cmpWidth, cmpHeight))) { | 169 if (!fBM.allocPixels(SkImageInfo::MakeA8(cmpWidth, cmpHeight))) { |
134 return false; | 170 return false; |
135 } | 171 } |
136 | 172 |
137 sk_bzero(fBM.getPixels(), fBM.getSafeSize()); | 173 sk_bzero(fBM.getPixels(), fBM.getSafeSize()); |
138 | 174 |
139 sk_bzero(&fDraw, sizeof(fDraw)); | 175 sk_bzero(&fDraw, sizeof(fDraw)); |
140 fRasterClip.setRect(bounds); | 176 fRasterClip.setRect(bounds); |
141 fDraw.fRC = &fRasterClip; | 177 fDraw.fRC = &fRasterClip; |
142 fDraw.fClip = &fRasterClip.bwRgn(); | 178 fDraw.fClip = &fRasterClip.bwRgn(); |
143 fDraw.fMatrix = &fMatrix; | 179 fDraw.fMatrix = &fMatrix; |
144 fDraw.fBitmap = &fBM; | 180 fDraw.fBitmap = &fBM; |
145 return true; | 181 return true; |
146 } | 182 } |
147 | 183 |
148 /** | 184 /** |
149 * Get a texture (from the texture cache) of the correct size & format. | 185 * Get a texture (from the texture cache) of the correct size & format. |
150 * Return true on success; false on failure. | 186 * Return true on success; false on failure. |
151 */ | 187 */ |
152 bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* texture) { | 188 bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* texture) { |
153 GrTextureDesc desc; | 189 GrTextureDesc desc; |
154 desc.fWidth = fBM.width(); | 190 desc.fWidth = fBM.width(); |
155 desc.fHeight = fBM.height(); | 191 desc.fHeight = fBM.height(); |
| 192 desc.fConfig = kAlpha_8_GrPixelConfig; |
156 | 193 |
157 #if GR_COMPRESS_ALPHA_MASK | 194 if (fCompressMask) { |
158 | 195 |
159 #ifdef SK_DEBUG | 196 #ifdef SK_DEBUG |
160 int dimX, dimY; | 197 int dimX, dimY; |
161 SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY); | 198 SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY)
; |
162 SkASSERT((desc.fWidth % dimX) == 0); | 199 SkASSERT((desc.fWidth % dimX) == 0); |
163 SkASSERT((desc.fHeight % dimY) == 0); | 200 SkASSERT((desc.fHeight % dimY) == 0); |
164 #endif | 201 #endif |
165 | 202 |
166 desc.fConfig = fmt_to_config(fCompressedFormat); | 203 desc.fConfig = fmt_to_config(fCompressedFormat); |
167 | 204 |
168 // If this config isn't supported then we should fall back to A8 | 205 // If this config isn't supported then we should fall back to A8 |
169 if (!(fContext->getGpu()->caps()->isConfigTexturable(desc.fConfig))) { | 206 if (!(fContext->getGpu()->caps()->isConfigTexturable(desc.fConfig))) { |
170 desc.fConfig = kAlpha_8_GrPixelConfig; | 207 SkDEBUGFAIL("Determining compression should be set from choose_compr
essed_fmt"); |
| 208 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 209 } |
171 } | 210 } |
172 #else | |
173 desc.fConfig = kAlpha_8_GrPixelConfig; | |
174 #endif | |
175 | 211 |
176 texture->set(fContext, desc); | 212 texture->set(fContext, desc); |
177 return NULL != texture->texture(); | 213 return NULL != texture->texture(); |
178 } | 214 } |
179 | 215 |
180 void GrSWMaskHelper::sendTextureData(GrTexture *texture, const GrTextureDesc& de
sc, | 216 void GrSWMaskHelper::sendTextureData(GrTexture *texture, const GrTextureDesc& de
sc, |
181 const void *data, int rowbytes) { | 217 const void *data, int rowbytes) { |
182 // If we aren't reusing scratch textures we don't need to flush before | 218 // If we aren't reusing scratch textures we don't need to flush before |
183 // writing since no one else will be using 'texture' | 219 // writing since no one else will be using 'texture' |
184 bool reuseScratch = fContext->getGpu()->caps()->reuseScratchTextures(); | 220 bool reuseScratch = fContext->getGpu()->caps()->reuseScratchTextures(); |
185 | 221 |
186 // Since we're uploading to it, and it's compressed, 'texture' shouldn't | 222 // Since we're uploading to it, and it's compressed, 'texture' shouldn't |
187 // have a render target. | 223 // have a render target. |
188 SkASSERT(NULL == texture->asRenderTarget()); | 224 SkASSERT(NULL == texture->asRenderTarget()); |
189 | 225 |
190 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, | 226 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, |
191 desc.fConfig, data, rowbytes, | 227 desc.fConfig, data, rowbytes, |
192 reuseScratch ? 0 : GrContext::kDontFlush_PixelOpsFlag); | 228 reuseScratch ? 0 : GrContext::kDontFlush_PixelOpsFlag); |
193 } | 229 } |
194 | 230 |
195 void GrSWMaskHelper::compressTextureData(GrTexture *texture, const GrTextureDesc
& desc) { | 231 void GrSWMaskHelper::compressTextureData(GrTexture *texture, const GrTextureDesc
& desc) { |
196 | 232 |
197 SkASSERT(GrPixelConfigIsCompressed(desc.fConfig)); | 233 SkASSERT(GrPixelConfigIsCompressed(desc.fConfig)); |
| 234 SkASSERT(fmt_to_config(fCompressedFormat) == desc.fConfig); |
198 | 235 |
199 SkTextureCompressor::Format format = SkTextureCompressor::kLATC_Format; | 236 SkAutoDataUnref cmpData(SkTextureCompressor::CompressBitmapToFormat(fBM, fCo
mpressedFormat)); |
200 | |
201 // Choose the format required by the texture descriptor. | |
202 switch(desc.fConfig) { | |
203 case kLATC_GrPixelConfig: | |
204 format = SkTextureCompressor::kLATC_Format; | |
205 break; | |
206 case kR11_EAC_GrPixelConfig: | |
207 format = SkTextureCompressor::kR11_EAC_Format; | |
208 break; | |
209 default: | |
210 SkFAIL("Unrecognized texture compression format."); | |
211 break; | |
212 } | |
213 | |
214 SkAutoDataUnref cmpData(SkTextureCompressor::CompressBitmapToFormat(fBM, for
mat)); | |
215 SkASSERT(NULL != cmpData); | 237 SkASSERT(NULL != cmpData); |
216 | 238 |
217 this->sendTextureData(texture, desc, cmpData->data(), 0); | 239 this->sendTextureData(texture, desc, cmpData->data(), 0); |
218 } | 240 } |
219 | 241 |
220 /** | 242 /** |
221 * Move the result of the software mask generation back to the gpu | 243 * Move the result of the software mask generation back to the gpu |
222 */ | 244 */ |
223 void GrSWMaskHelper::toTexture(GrTexture *texture) { | 245 void GrSWMaskHelper::toTexture(GrTexture *texture) { |
224 SkAutoLockPixels alp(fBM); | 246 SkAutoLockPixels alp(fBM); |
225 | 247 |
226 GrTextureDesc desc; | 248 GrTextureDesc desc; |
227 desc.fWidth = fBM.width(); | 249 desc.fWidth = fBM.width(); |
228 desc.fHeight = fBM.height(); | 250 desc.fHeight = fBM.height(); |
229 desc.fConfig = texture->config(); | 251 desc.fConfig = texture->config(); |
230 | 252 |
231 // First see if we should compress this texture before uploading. | 253 // First see if we should compress this texture before uploading. |
232 if (GrPixelConfigIsCompressed(texture->config())) { | 254 if (fCompressMask) { |
233 this->compressTextureData(texture, desc); | 255 this->compressTextureData(texture, desc); |
234 } else { | 256 } else { |
235 // Looks like we have to send a full A8 texture. | 257 // Looks like we have to send a full A8 texture. |
236 this->sendTextureData(texture, desc, fBM.getPixels(), fBM.rowBytes()); | 258 this->sendTextureData(texture, desc, fBM.getPixels(), fBM.rowBytes()); |
237 } | 259 } |
238 } | 260 } |
239 | 261 |
240 //////////////////////////////////////////////////////////////////////////////// | 262 //////////////////////////////////////////////////////////////////////////////// |
241 /** | 263 /** |
242 * Software rasterizes path to A8 mask (possibly using the context's matrix) | 264 * Software rasterizes path to A8 mask (possibly using the context's matrix) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 maskMatrix.preConcat(drawState->getViewMatrix()); | 315 maskMatrix.preConcat(drawState->getViewMatrix()); |
294 | 316 |
295 drawState->addCoverageEffect( | 317 drawState->addCoverageEffect( |
296 GrSimpleTextureEffect::Create(texture, | 318 GrSimpleTextureEffect::Create(texture, |
297 maskMatrix, | 319 maskMatrix, |
298 GrTextureParams::kNone_Fi
lterMode, | 320 GrTextureParams::kNone_Fi
lterMode, |
299 kPosition_GrCoordSet))->u
nref(); | 321 kPosition_GrCoordSet))->u
nref(); |
300 | 322 |
301 target->drawSimpleRect(dstRect); | 323 target->drawSimpleRect(dstRect); |
302 } | 324 } |
OLD | NEW |