gfx/skia/trunk/src/gpu/GrSWMaskHelper.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright 2012 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #include "GrSWMaskHelper.h"
michael@0 9 #include "GrDrawState.h"
michael@0 10 #include "GrDrawTargetCaps.h"
michael@0 11 #include "GrGpu.h"
michael@0 12
michael@0 13 #include "SkStrokeRec.h"
michael@0 14
michael@0 15 // TODO: try to remove this #include
michael@0 16 #include "GrContext.h"
michael@0 17
michael@0 18 namespace {
michael@0 19 /*
michael@0 20 * Convert a boolean operation into a transfer mode code
michael@0 21 */
michael@0 22 SkXfermode::Mode op_to_mode(SkRegion::Op op) {
michael@0 23
michael@0 24 static const SkXfermode::Mode modeMap[] = {
michael@0 25 SkXfermode::kDstOut_Mode, // kDifference_Op
michael@0 26 SkXfermode::kModulate_Mode, // kIntersect_Op
michael@0 27 SkXfermode::kSrcOver_Mode, // kUnion_Op
michael@0 28 SkXfermode::kXor_Mode, // kXOR_Op
michael@0 29 SkXfermode::kClear_Mode, // kReverseDifference_Op
michael@0 30 SkXfermode::kSrc_Mode, // kReplace_Op
michael@0 31 };
michael@0 32
michael@0 33 return modeMap[op];
michael@0 34 }
michael@0 35
michael@0 36 }
michael@0 37
michael@0 38 /**
michael@0 39 * Draw a single rect element of the clip stack into the accumulation bitmap
michael@0 40 */
michael@0 41 void GrSWMaskHelper::draw(const SkRect& rect, SkRegion::Op op,
michael@0 42 bool antiAlias, uint8_t alpha) {
michael@0 43 SkPaint paint;
michael@0 44
michael@0 45 SkXfermode* mode = SkXfermode::Create(op_to_mode(op));
michael@0 46
michael@0 47 paint.setXfermode(mode);
michael@0 48 paint.setAntiAlias(antiAlias);
michael@0 49 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
michael@0 50
michael@0 51 fDraw.drawRect(rect, paint);
michael@0 52
michael@0 53 SkSafeUnref(mode);
michael@0 54 }
michael@0 55
michael@0 56 /**
michael@0 57 * Draw a single path element of the clip stack into the accumulation bitmap
michael@0 58 */
michael@0 59 void GrSWMaskHelper::draw(const SkPath& path, const SkStrokeRec& stroke, SkRegion::Op op,
michael@0 60 bool antiAlias, uint8_t alpha) {
michael@0 61
michael@0 62 SkPaint paint;
michael@0 63 if (stroke.isHairlineStyle()) {
michael@0 64 paint.setStyle(SkPaint::kStroke_Style);
michael@0 65 paint.setStrokeWidth(SK_Scalar1);
michael@0 66 } else {
michael@0 67 if (stroke.isFillStyle()) {
michael@0 68 paint.setStyle(SkPaint::kFill_Style);
michael@0 69 } else {
michael@0 70 paint.setStyle(SkPaint::kStroke_Style);
michael@0 71 paint.setStrokeJoin(stroke.getJoin());
michael@0 72 paint.setStrokeCap(stroke.getCap());
michael@0 73 paint.setStrokeWidth(stroke.getWidth());
michael@0 74 }
michael@0 75 }
michael@0 76 paint.setAntiAlias(antiAlias);
michael@0 77
michael@0 78 if (SkRegion::kReplace_Op == op && 0xFF == alpha) {
michael@0 79 SkASSERT(0xFF == paint.getAlpha());
michael@0 80 fDraw.drawPathCoverage(path, paint);
michael@0 81 } else {
michael@0 82 paint.setXfermodeMode(op_to_mode(op));
michael@0 83 paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
michael@0 84 fDraw.drawPath(path, paint);
michael@0 85 }
michael@0 86 }
michael@0 87
michael@0 88 bool GrSWMaskHelper::init(const SkIRect& resultBounds,
michael@0 89 const SkMatrix* matrix) {
michael@0 90 if (NULL != matrix) {
michael@0 91 fMatrix = *matrix;
michael@0 92 } else {
michael@0 93 fMatrix.setIdentity();
michael@0 94 }
michael@0 95
michael@0 96 // Now translate so the bound's UL corner is at the origin
michael@0 97 fMatrix.postTranslate(-resultBounds.fLeft * SK_Scalar1,
michael@0 98 -resultBounds.fTop * SK_Scalar1);
michael@0 99 SkIRect bounds = SkIRect::MakeWH(resultBounds.width(),
michael@0 100 resultBounds.height());
michael@0 101
michael@0 102 if (!fBM.allocPixels(SkImageInfo::MakeA8(bounds.fRight, bounds.fBottom))) {
michael@0 103 return false;
michael@0 104 }
michael@0 105 sk_bzero(fBM.getPixels(), fBM.getSafeSize());
michael@0 106
michael@0 107 sk_bzero(&fDraw, sizeof(fDraw));
michael@0 108 fRasterClip.setRect(bounds);
michael@0 109 fDraw.fRC = &fRasterClip;
michael@0 110 fDraw.fClip = &fRasterClip.bwRgn();
michael@0 111 fDraw.fMatrix = &fMatrix;
michael@0 112 fDraw.fBitmap = &fBM;
michael@0 113 return true;
michael@0 114 }
michael@0 115
michael@0 116 /**
michael@0 117 * Get a texture (from the texture cache) of the correct size & format.
michael@0 118 * Return true on success; false on failure.
michael@0 119 */
michael@0 120 bool GrSWMaskHelper::getTexture(GrAutoScratchTexture* texture) {
michael@0 121 GrTextureDesc desc;
michael@0 122 desc.fWidth = fBM.width();
michael@0 123 desc.fHeight = fBM.height();
michael@0 124 desc.fConfig = kAlpha_8_GrPixelConfig;
michael@0 125
michael@0 126 texture->set(fContext, desc);
michael@0 127 return NULL != texture->texture();
michael@0 128 }
michael@0 129
michael@0 130 /**
michael@0 131 * Move the result of the software mask generation back to the gpu
michael@0 132 */
michael@0 133 void GrSWMaskHelper::toTexture(GrTexture *texture) {
michael@0 134 SkAutoLockPixels alp(fBM);
michael@0 135
michael@0 136 // If we aren't reusing scratch textures we don't need to flush before
michael@0 137 // writing since no one else will be using 'texture'
michael@0 138 bool reuseScratch = fContext->getGpu()->caps()->reuseScratchTextures();
michael@0 139
michael@0 140 // Since we're uploading to it, 'texture' shouldn't have a render target.
michael@0 141 SkASSERT(NULL == texture->asRenderTarget());
michael@0 142
michael@0 143 texture->writePixels(0, 0, fBM.width(), fBM.height(),
michael@0 144 kAlpha_8_GrPixelConfig,
michael@0 145 fBM.getPixels(), fBM.rowBytes(),
michael@0 146 reuseScratch ? 0 : GrContext::kDontFlush_PixelOpsFlag);
michael@0 147 }
michael@0 148
michael@0 149 ////////////////////////////////////////////////////////////////////////////////
michael@0 150 /**
michael@0 151 * Software rasterizes path to A8 mask (possibly using the context's matrix)
michael@0 152 * and uploads the result to a scratch texture. Returns the resulting
michael@0 153 * texture on success; NULL on failure.
michael@0 154 */
michael@0 155 GrTexture* GrSWMaskHelper::DrawPathMaskToTexture(GrContext* context,
michael@0 156 const SkPath& path,
michael@0 157 const SkStrokeRec& stroke,
michael@0 158 const SkIRect& resultBounds,
michael@0 159 bool antiAlias,
michael@0 160 SkMatrix* matrix) {
michael@0 161 GrAutoScratchTexture ast;
michael@0 162
michael@0 163 GrSWMaskHelper helper(context);
michael@0 164
michael@0 165 if (!helper.init(resultBounds, matrix)) {
michael@0 166 return NULL;
michael@0 167 }
michael@0 168
michael@0 169 helper.draw(path, stroke, SkRegion::kReplace_Op, antiAlias, 0xFF);
michael@0 170
michael@0 171 if (!helper.getTexture(&ast)) {
michael@0 172 return NULL;
michael@0 173 }
michael@0 174
michael@0 175 helper.toTexture(ast.texture());
michael@0 176
michael@0 177 return ast.detach();
michael@0 178 }
michael@0 179
michael@0 180 void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
michael@0 181 GrDrawTarget* target,
michael@0 182 const SkIRect& rect) {
michael@0 183 GrDrawState* drawState = target->drawState();
michael@0 184
michael@0 185 GrDrawState::AutoViewMatrixRestore avmr;
michael@0 186 if (!avmr.setIdentity(drawState)) {
michael@0 187 return;
michael@0 188 }
michael@0 189 GrDrawState::AutoRestoreEffects are(drawState);
michael@0 190
michael@0 191 SkRect dstRect = SkRect::MakeLTRB(SK_Scalar1 * rect.fLeft,
michael@0 192 SK_Scalar1 * rect.fTop,
michael@0 193 SK_Scalar1 * rect.fRight,
michael@0 194 SK_Scalar1 * rect.fBottom);
michael@0 195
michael@0 196 // We want to use device coords to compute the texture coordinates. We set our matrix to be
michael@0 197 // equal to the view matrix followed by a translation so that the top-left of the device bounds
michael@0 198 // maps to 0,0, and then a scaling matrix to normalized coords. We apply this matrix to the
michael@0 199 // vertex positions rather than local coords.
michael@0 200 SkMatrix maskMatrix;
michael@0 201 maskMatrix.setIDiv(texture->width(), texture->height());
michael@0 202 maskMatrix.preTranslate(SkIntToScalar(-rect.fLeft), SkIntToScalar(-rect.fTop));
michael@0 203 maskMatrix.preConcat(drawState->getViewMatrix());
michael@0 204
michael@0 205 drawState->addCoverageEffect(
michael@0 206 GrSimpleTextureEffect::Create(texture,
michael@0 207 maskMatrix,
michael@0 208 GrTextureParams::kNone_FilterMode,
michael@0 209 kPosition_GrCoordSet))->unref();
michael@0 210
michael@0 211 target->drawSimpleRect(dstRect);
michael@0 212 }

mercurial