| 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 |