Home | History | Annotate | Download | only in gpu
      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 "GrShape.h"
     13 #include "GrSurfaceContext.h"
     14 #include "GrTextureProxy.h"
     15 
     16 /*
     17  * Convert a boolean operation into a transfer mode code
     18  */
     19 static SkBlendMode op_to_mode(SkRegion::Op op) {
     20 
     21     static const SkBlendMode modeMap[] = {
     22         SkBlendMode::kDstOut,   // kDifference_Op
     23         SkBlendMode::kModulate, // kIntersect_Op
     24         SkBlendMode::kSrcOver,  // kUnion_Op
     25         SkBlendMode::kXor,      // kXOR_Op
     26         SkBlendMode::kClear,    // kReverseDifference_Op
     27         SkBlendMode::kSrc,      // kReplace_Op
     28     };
     29 
     30     return modeMap[op];
     31 }
     32 
     33 /**
     34  * Draw a single rect element of the clip stack into the accumulation bitmap
     35  */
     36 void GrSWMaskHelper::drawRect(const SkRect& rect, const SkMatrix& matrix, SkRegion::Op op, GrAA aa,
     37                               uint8_t alpha) {
     38     SkPaint paint;
     39     paint.setBlendMode(op_to_mode(op));
     40     paint.setAntiAlias(GrAA::kYes == aa);
     41     paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
     42 
     43     SkMatrix translatedMatrix = matrix;
     44     translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY);
     45     fDraw.fMatrix = &translatedMatrix;
     46 
     47     fDraw.drawRect(rect, paint);
     48 }
     49 
     50 /**
     51  * Draw a single path element of the clip stack into the accumulation bitmap
     52  */
     53 void GrSWMaskHelper::drawShape(const GrShape& shape, const SkMatrix& matrix, SkRegion::Op op,
     54                                GrAA aa, uint8_t alpha) {
     55     SkPaint paint;
     56     paint.setPathEffect(shape.style().refPathEffect());
     57     shape.style().strokeRec().applyToPaint(&paint);
     58     paint.setAntiAlias(GrAA::kYes == aa);
     59 
     60     SkMatrix translatedMatrix = matrix;
     61     translatedMatrix.postTranslate(fTranslate.fX, fTranslate.fY);
     62     fDraw.fMatrix = &translatedMatrix;
     63 
     64     SkPath path;
     65     shape.asPath(&path);
     66     if (SkRegion::kReplace_Op == op && 0xFF == alpha) {
     67         SkASSERT(0xFF == paint.getAlpha());
     68         fDraw.drawPathCoverage(path, paint);
     69     } else {
     70         paint.setBlendMode(op_to_mode(op));
     71         paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha));
     72         fDraw.drawPath(path, paint);
     73     }
     74 };
     75 
     76 bool GrSWMaskHelper::init(const SkIRect& resultBounds) {
     77     // We will need to translate draws so the bound's UL corner is at the origin
     78     fTranslate = {-SkIntToScalar(resultBounds.fLeft), -SkIntToScalar(resultBounds.fTop)};
     79     SkIRect bounds = SkIRect::MakeWH(resultBounds.width(), resultBounds.height());
     80 
     81     const SkImageInfo bmImageInfo = SkImageInfo::MakeA8(bounds.width(), bounds.height());
     82     if (!fPixels->tryAlloc(bmImageInfo)) {
     83         return false;
     84     }
     85     fPixels->erase(0);
     86 
     87     sk_bzero(&fDraw, sizeof(fDraw));
     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     GrSurfaceDesc desc;
     96     desc.fOrigin = kTopLeft_GrSurfaceOrigin;
     97     desc.fWidth = fPixels->width();
     98     desc.fHeight = fPixels->height();
     99     desc.fConfig = kAlpha_8_GrPixelConfig;
    100 
    101     sk_sp<GrSurfaceContext> sContext = context->contextPriv().makeDeferredSurfaceContext(
    102                                                                                 desc,
    103                                                                                 GrMipMapped::kNo,
    104                                                                                 fit,
    105                                                                                 SkBudgeted::kYes);
    106     if (!sContext || !sContext->asTextureProxy()) {
    107         return nullptr;
    108     }
    109 
    110     SkImageInfo ii = SkImageInfo::MakeA8(desc.fWidth, desc.fHeight);
    111     if (!sContext->writePixels(ii, fPixels->addr(), fPixels->rowBytes(), 0, 0)) {
    112         return nullptr;
    113     }
    114 
    115     return sContext->asTextureProxyRef();
    116 }
    117