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.

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

mercurial