1 /* 2 * Copyright 2012 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 "GrSWMaskHelper.h" 9 10 #include "GrContext.h" 11 #include "GrContextPriv.h" 12 #include "GrProxyProvider.h" 13 #include "GrShape.h" 14 #include "GrSurfaceContext.h" 15 #include "GrTextureProxy.h" 16 17 /* 18 * Convert a boolean operation into a transfer mode code 19 */ 20 static SkBlendMode op_to_mode(SkRegion::Op op) { 21 22 static const SkBlendMode modeMap[] = { 23 SkBlendMode::kDstOut, // kDifference_Op 24 SkBlendMode::kModulate, // kIntersect_Op 25 SkBlendMode::kSrcOver, // kUnion_Op 26 SkBlendMode::kXor, // kXOR_Op 27 SkBlendMode::kClear, // kReverseDifference_Op 28 SkBlendMode::kSrc, // kReplace_Op 29 }; 30 31 return modeMap[op]; 32 } 33 34 /** 35 * Draw a single rect element of the clip stack into the accumulation bitmap 36 */ 37 void GrSWMaskHelper::drawRect(const SkRect& rect, const SkMatrix& matrix, SkRegion::Op op, GrAA aa, 38 uint8_t alpha) { 39 SkPaint paint; 40 paint.setBlendMode(op_to_mode(op)); 41 paint.setAntiAlias(GrAA::kYes == aa); 42 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); 43 44 SkMatrix translatedMatrix = matrix; 45 translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY); 46 fDraw.fMatrix = &translatedMatrix; 47 48 fDraw.drawRect(rect, paint); 49 } 50 51 /** 52 * Draw a single path element of the clip stack into the accumulation bitmap 53 */ 54 void GrSWMaskHelper::drawShape(const GrShape& shape, const SkMatrix& matrix, SkRegion::Op op, 55 GrAA aa, uint8_t alpha) { 56 SkPaint paint; 57 paint.setPathEffect(shape.style().refPathEffect()); 58 shape.style().strokeRec().applyToPaint(&paint); 59 paint.setAntiAlias(GrAA::kYes == aa); 60 61 SkMatrix translatedMatrix = matrix; 62 translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY); 63 fDraw.fMatrix = &translatedMatrix; 64 65 SkPath path; 66 shape.asPath(&path); 67 if (SkRegion::kReplace_Op == op && 0xFF == alpha) { 68 SkASSERT(0xFF == paint.getAlpha()); 69 fDraw.drawPathCoverage(path, paint); 70 } else { 71 paint.setBlendMode(op_to_mode(op)); 72 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); 73 fDraw.drawPath(path, paint); 74 } 75 }; 76 77 bool GrSWMaskHelper::init(const SkIRect& resultBounds) { 78 // We will need to translate draws so the bound's UL corner is at the origin 79 fTranslate = {-SkIntToScalar(resultBounds.fLeft), -SkIntToScalar(resultBounds.fTop)}; 80 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height()); 81 82 const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(bounds.width(), bounds.height()); 83 if (!fPixels->tryAlloc(bmImageInfo)) { 84 return false; 85 } 86 fPixels->erase(0); 87 88 fDraw.fDst = *fPixels; 89 fRasterClip.setRect(bounds); 90 fDraw.fRC = &fRasterClip; 91 return true; 92 } 93 94 sk_sp<GrTextureProxy> GrSWMaskHelper::toTextureProxy(GrContext* context, SkBackingFit fit) { 95 SkImageInfo ii = SkImageInfo::MakeA8(fPixels->width(), fPixels->height()); 96 size_t rowBytes = fPixels->rowBytes(); 97 98 sk_sp<SkData> data = fPixels->detachPixelsAsData(); 99 if (!data) { 100 return nullptr; 101 } 102 103 sk_sp<SkImage> img = SkImage::MakeRasterData(ii, std::move(data), rowBytes); 104 if (!img) { 105 return nullptr; 106 } 107 108 // TODO: http://skbug.com/8422: Although this fixes http://skbug.com/8351, it seems like these 109 // should just participate in the normal allocation process and not need the pending IO flag. 110 auto surfaceFlags = GrInternalSurfaceFlags::kNone; 111 if (!context->contextPriv().resourceProvider()) { 112 // In DDL mode, this texture proxy will be instantiated at flush time, therfore it cannot 113 // have pending IO. 114 surfaceFlags |= GrInternalSurfaceFlags::kNoPendingIO; 115 } 116 auto clearFlag = kNone_GrSurfaceFlags; 117 // In a WASM build on Firefox, we see warnings like 118 // WebGL warning: texSubImage2D: This operation requires zeroing texture data. This is slow. 119 // WebGL warning: texSubImage2D: Texture has not been initialized prior to a partial upload, 120 // forcing the browser to clear it. This may be slow. 121 // Setting the initial clear seems to make those warnings go away and offers a substantial 122 // boost in performance in Firefox. Chrome sees a more modest increase. 123 #if IS_WEBGL==1 124 clearFlag = kPerformInitialClear_GrSurfaceFlag; 125 #endif 126 return context->contextPriv().proxyProvider()->createTextureProxy( 127 std::move(img), clearFlag, 1, SkBudgeted::kYes, fit, surfaceFlags); 128 } 129