Chromium Code Reviews| 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 | |
|
robertphillips
2014/07/30 12:15:49
I would reverse the order of the arguments.
Would
krajcevski
2014/07/30 15:10:19
Done.
| |
| 54 static bool choose_compressed_fmt(SkTextureCompressor::Format *fmt, GrContext *c tx) { | |
| 55 if (NULL == fmt) { | |
| 56 return false; | |
| 57 } | |
| 58 | |
| 59 // Figure out what our preferred texture type is. If ASTC is available, that always | |
| 60 // gives the biggest win. Otherwise, in terms of compression speed and accur acy, | |
| 61 // LATC has a slight edge over R11 EAC. | |
| 62 bool result = false; | |
| 63 if (ctx->getGpu()->caps()->isConfigTexturable(kASTC_12x12_GrPixelConfig)) { | |
| 64 *fmt = SkTextureCompressor::kASTC_12x12_Format; | |
| 65 result = true; | |
| 66 } else if (ctx->getGpu()->caps()->isConfigTexturable(kLATC_GrPixelConfig)) { | |
| 67 *fmt = SkTextureCompressor::kLATC_Format; | |
| 68 result = true; | |
| 69 } else if (ctx->getGpu()->caps()->isConfigTexturable(kR11_EAC_GrPixelConfig) ) { | |
| 70 *fmt = SkTextureCompressor::kR11_EAC_Format; | |
| 71 result = true; | |
|
robertphillips
2014/07/30 12:15:49
We usually only use #error in preprocessor-ish cod
krajcevski
2014/07/30 15:10:19
Done.
| |
| 72 #error "FIXME: Is there a way to find out if we're on desktop or not?" | |
| 73 } | |
| 74 | |
| 75 return result; | |
| 76 } | |
| 77 #endif | |
| 78 | |
| 53 } | 79 } |
| 54 | 80 |
| 55 /** | 81 /** |
| 56 * Draw a single rect element of the clip stack into the accumulation bitmap | 82 * Draw a single rect element of the clip stack into the accumulation bitmap |
| 57 */ | 83 */ |
| 58 void GrSWMaskHelper::draw(const SkRect& rect, SkRegion::Op op, | 84 void GrSWMaskHelper::draw(const SkRect& rect, SkRegion::Op op, |
| 59 bool antiAlias, uint8_t alpha) { | 85 bool antiAlias, uint8_t alpha) { |
| 60 SkPaint paint; | 86 SkPaint paint; |
| 61 | 87 |
| 62 SkXfermode* mode = SkXfermode::Create(op_to_mode(op)); | 88 SkXfermode* mode = SkXfermode::Create(op_to_mode(op)); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 fMatrix.setIdentity(); | 136 fMatrix.setIdentity(); |
| 111 } | 137 } |
| 112 | 138 |
| 113 // Now translate so the bound's UL corner is at the origin | 139 // Now translate so the bound's UL corner is at the origin |
| 114 fMatrix.postTranslate(-resultBounds.fLeft * SK_Scalar1, | 140 fMatrix.postTranslate(-resultBounds.fLeft * SK_Scalar1, |
| 115 -resultBounds.fTop * SK_Scalar1); | 141 -resultBounds.fTop * SK_Scalar1); |
| 116 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), | 142 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), |
| 117 resultBounds.height()); | 143 resultBounds.height()); |
| 118 | 144 |
| 119 #if GR_COMPRESS_ALPHA_MASK | 145 #if GR_COMPRESS_ALPHA_MASK |
| 120 fCompressedFormat = SkTextureCompressor::kR11_EAC_Format; | 146 fCompressMask = choose_compressed_fmt(&fCompressedFormat, fContext); |
| 147 #else | |
| 148 fCompressMask = false; | |
| 149 #endif | |
| 121 | 150 |
| 122 // Make sure that the width is a multiple of 16 so that we can use | 151 // 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. | 152 // specialized SIMD instructions that compress 4 blocks at a time. |
| 124 int dimX, dimY; | 153 int cmpWidth, cmpHeight; |
| 125 SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY); | 154 if (fCompressMask) { |
| 126 const int cmpWidth = dimX * ((bounds.fRight + (dimX - 1)) / dimX); | 155 int dimX, dimY; |
| 127 const int cmpHeight = dimY * ((bounds.fBottom + (dimY - 1)) / dimY); | 156 SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY) ; |
| 128 #else | 157 cmpWidth = dimX * ((bounds.fRight + (dimX - 1)) / dimX); |
| 129 const int cmpWidth = bounds.fRight; | 158 cmpHeight = dimY * ((bounds.fBottom + (dimY - 1)) / dimY); |
| 130 const int cmpHeight = bounds.fBottom; | 159 } else { |
| 131 #endif | 160 cmpWidth = bounds.fRight; |
| 161 cmpHeight = bounds.fBottom; | |
| 162 } | |
| 132 | 163 |
| 133 if (!fBM.allocPixels(SkImageInfo::MakeA8(cmpWidth, cmpHeight))) { | 164 if (!fBM.allocPixels(SkImageInfo::MakeA8(cmpWidth, cmpHeight))) { |
| 134 return false; | 165 return false; |
| 135 } | 166 } |
| 136 | 167 |
| 137 sk_bzero(fBM.getPixels(), fBM.getSafeSize()); | 168 sk_bzero(fBM.getPixels(), fBM.getSafeSize()); |
| 138 | 169 |
| 139 sk_bzero(&fDraw, sizeof(fDraw)); | 170 sk_bzero(&fDraw, sizeof(fDraw)); |
| 140 fRasterClip.setRect(bounds); | 171 fRasterClip.setRect(bounds); |
| 141 fDraw.fRC = &fRasterClip; | 172 fDraw.fRC = &fRasterClip; |
| 142 fDraw.fClip = &fRasterClip.bwRgn(); | 173 fDraw.fClip = &fRasterClip.bwRgn(); |
| 143 fDraw.fMatrix = &fMatrix; | 174 fDraw.fMatrix = &fMatrix; |
| 144 fDraw.fBitmap = &fBM; | 175 fDraw.fBitmap = &fBM; |
| 145 return true; | 176 return true; |
| 146 } | 177 } |
| 147 | 178 |
| 148 /** | 179 /** |
| 149 * Get a texture (from the texture cache) of the correct size & format. | 180 * Get a texture (from the texture cache) of the correct size & format. |
| 150 * Return true on success; false on failure. | 181 * Return true on success; false on failure. |
| 151 */ | 182 */ |
| 152 bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* texture) { | 183 bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* texture) { |
| 153 GrTextureDesc desc; | 184 GrTextureDesc desc; |
| 154 desc.fWidth = fBM.width(); | 185 desc.fWidth = fBM.width(); |
| 155 desc.fHeight = fBM.height(); | 186 desc.fHeight = fBM.height(); |
| 187 desc.fConfig = kAlpha_8_GrPixelConfig; | |
| 156 | 188 |
| 157 #if GR_COMPRESS_ALPHA_MASK | 189 if (fCompressMask) { |
| 158 | 190 |
| 159 #ifdef SK_DEBUG | 191 #ifdef SK_DEBUG |
| 160 int dimX, dimY; | 192 int dimX, dimY; |
| 161 SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY); | 193 SkTextureCompressor::GetBlockDimensions(fCompressedFormat, &dimX, &dimY) ; |
| 162 SkASSERT((desc.fWidth % dimX) == 0); | 194 SkASSERT((desc.fWidth % dimX) == 0); |
| 163 SkASSERT((desc.fHeight % dimY) == 0); | 195 SkASSERT((desc.fHeight % dimY) == 0); |
| 164 #endif | 196 #endif |
| 165 | 197 |
| 166 desc.fConfig = fmt_to_config(fCompressedFormat); | 198 desc.fConfig = fmt_to_config(fCompressedFormat); |
| 167 | 199 |
| 168 // If this config isn't supported then we should fall back to A8 | 200 // If this config isn't supported then we should fall back to A8 |
| 169 if (!(fContext->getGpu()->caps()->isConfigTexturable(desc.fConfig))) { | 201 if (!(fContext->getGpu()->caps()->isConfigTexturable(desc.fConfig))) { |
| 170 desc.fConfig = kAlpha_8_GrPixelConfig; | 202 desc.fConfig = kAlpha_8_GrPixelConfig; |
| 203 } | |
| 171 } | 204 } |
| 172 #else | |
| 173 desc.fConfig = kAlpha_8_GrPixelConfig; | |
| 174 #endif | |
| 175 | 205 |
| 176 texture->set(fContext, desc); | 206 texture->set(fContext, desc); |
| 177 return NULL != texture->texture(); | 207 return NULL != texture->texture(); |
| 178 } | 208 } |
| 179 | 209 |
| 180 void GrSWMaskHelper::sendTextureData(GrTexture *texture, const GrTextureDesc& de sc, | 210 void GrSWMaskHelper::sendTextureData(GrTexture *texture, const GrTextureDesc& de sc, |
| 181 const void *data, int rowbytes) { | 211 const void *data, int rowbytes) { |
| 182 // If we aren't reusing scratch textures we don't need to flush before | 212 // If we aren't reusing scratch textures we don't need to flush before |
| 183 // writing since no one else will be using 'texture' | 213 // writing since no one else will be using 'texture' |
| 184 bool reuseScratch = fContext->getGpu()->caps()->reuseScratchTextures(); | 214 bool reuseScratch = fContext->getGpu()->caps()->reuseScratchTextures(); |
| 185 | 215 |
| 186 // Since we're uploading to it, and it's compressed, 'texture' shouldn't | 216 // Since we're uploading to it, and it's compressed, 'texture' shouldn't |
| 187 // have a render target. | 217 // have a render target. |
| 188 SkASSERT(NULL == texture->asRenderTarget()); | 218 SkASSERT(NULL == texture->asRenderTarget()); |
| 189 | 219 |
| 190 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, | 220 texture->writePixels(0, 0, desc.fWidth, desc.fHeight, |
| 191 desc.fConfig, data, rowbytes, | 221 desc.fConfig, data, rowbytes, |
| 192 reuseScratch ? 0 : GrContext::kDontFlush_PixelOpsFlag); | 222 reuseScratch ? 0 : GrContext::kDontFlush_PixelOpsFlag); |
| 193 } | 223 } |
| 194 | 224 |
| 195 void GrSWMaskHelper::compressTextureData(GrTexture *texture, const GrTextureDesc & desc) { | 225 void GrSWMaskHelper::compressTextureData(GrTexture *texture, const GrTextureDesc & desc) { |
| 196 | 226 |
| 197 SkASSERT(GrPixelConfigIsCompressed(desc.fConfig)); | 227 SkASSERT(GrPixelConfigIsCompressed(desc.fConfig)); |
| 228 SkASSERT(fmt_to_config(fCompressedFormat) == desc.fConfig); | |
| 198 | 229 |
| 199 SkTextureCompressor::Format format = SkTextureCompressor::kLATC_Format; | 230 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); | 231 SkASSERT(NULL != cmpData); |
| 216 | 232 |
| 217 this->sendTextureData(texture, desc, cmpData->data(), 0); | 233 this->sendTextureData(texture, desc, cmpData->data(), 0); |
| 218 } | 234 } |
| 219 | 235 |
| 220 /** | 236 /** |
| 221 * Move the result of the software mask generation back to the gpu | 237 * Move the result of the software mask generation back to the gpu |
| 222 */ | 238 */ |
| 223 void GrSWMaskHelper::toTexture(GrTexture *texture) { | 239 void GrSWMaskHelper::toTexture(GrTexture *texture) { |
| 224 SkAutoLockPixels alp(fBM); | 240 SkAutoLockPixels alp(fBM); |
| 225 | 241 |
| 226 GrTextureDesc desc; | 242 GrTextureDesc desc; |
| 227 desc.fWidth = fBM.width(); | 243 desc.fWidth = fBM.width(); |
| 228 desc.fHeight = fBM.height(); | 244 desc.fHeight = fBM.height(); |
| 229 desc.fConfig = texture->config(); | 245 desc.fConfig = texture->config(); |
| 230 | 246 |
| 231 // First see if we should compress this texture before uploading. | 247 // First see if we should compress this texture before uploading. |
| 232 if (GrPixelConfigIsCompressed(texture->config())) { | 248 if (fCompressMask) { |
| 233 this->compressTextureData(texture, desc); | 249 this->compressTextureData(texture, desc); |
| 234 } else { | 250 } else { |
| 235 // Looks like we have to send a full A8 texture. | 251 // Looks like we have to send a full A8 texture. |
| 236 this->sendTextureData(texture, desc, fBM.getPixels(), fBM.rowBytes()); | 252 this->sendTextureData(texture, desc, fBM.getPixels(), fBM.rowBytes()); |
| 237 } | 253 } |
| 238 } | 254 } |
| 239 | 255 |
| 240 //////////////////////////////////////////////////////////////////////////////// | 256 //////////////////////////////////////////////////////////////////////////////// |
| 241 /** | 257 /** |
| 242 * Software rasterizes path to A8 mask (possibly using the context's matrix) | 258 * 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()); | 309 maskMatrix.preConcat(drawState->getViewMatrix()); |
| 294 | 310 |
| 295 drawState->addCoverageEffect( | 311 drawState->addCoverageEffect( |
| 296 GrSimpleTextureEffect::Create(texture, | 312 GrSimpleTextureEffect::Create(texture, |
| 297 maskMatrix, | 313 maskMatrix, |
| 298 GrTextureParams::kNone_Fi lterMode, | 314 GrTextureParams::kNone_Fi lterMode, |
| 299 kPosition_GrCoordSet))->u nref(); | 315 kPosition_GrCoordSet))->u nref(); |
| 300 | 316 |
| 301 target->drawSimpleRect(dstRect); | 317 target->drawSimpleRect(dstRect); |
| 302 } | 318 } |
| OLD | NEW |