SkCanvas*
SkSurface_Compute::onNewCanvas()
{
  uint32_t w = 0,h = 0;

  // skc_interop_size_get(compute->interop,&w,&h); TODO skc.h

  SkDevice_Compute * const device_compute = new SkDevice_Compute(compute,w,h);;
  SkCanvas         * const canvas         = new SkCanvas(device_compute,SkCanvas::kConservativeRasterClip_InitFlag);

  //
  // destroy device upon surface destruction
  //
  device = sk_sp<SkBaseDevice>(device_compute);

  //
  // move origin from upper left to lower left
  //
  SkMatrix matrix;

  matrix.setScaleTranslate(1.0f,-1.0f,0.0f,(SkScalar)h);

  canvas->setMatrix(matrix);

  return canvas;
}
    void onDraw(SkCanvas* canvas) override {
        static const SkFilterQuality kFilterQuality = SkFilterQuality::kHigh_SkFilterQuality;
        static const bool kDoAA = true;

        {
            SkRect r1 = SkRect::MakeXYWH(50.0f, 0.0f, 50.0f, 50.0f);
            SkPaint p1;
            p1.setAntiAlias(kDoAA);
            p1.setFilterQuality(kFilterQuality);
            SkMatrix localMat;
            localMat.setScaleTranslate(2.0f, 2.0f, 50.0f, 0.0f);
            p1.setShader(SkImageShader::Make(fTop,
                                             SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
                                             &localMat));

            canvas->drawRect(r1, p1);
        }

        {
            SkRect r2 = SkRect::MakeXYWH(50.0f, 50.0f, 50.0f, 36.0f);

            SkPaint p2;
            p2.setColor(SK_ColorWHITE);
            p2.setAntiAlias(kDoAA);
            p2.setFilterQuality(kFilterQuality);

            canvas->drawRect(r2, p2);
        }

        {
            SkRect r3 = SkRect::MakeXYWH(50.0f, 86.0f, 50.0f, 50.0f);

            SkPaint p3;
            p3.setAntiAlias(kDoAA);
            p3.setFilterQuality(kFilterQuality);
            SkMatrix localMat;
            localMat.setScaleTranslate(2.0f, 2.0f, 50.0f, 86.0f);
            p3.setShader(SkImageShader::Make(fBot,
                                             SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
                                             &localMat));

            canvas->drawRect(r3, p3);
        }
    }
示例#3
0
std::unique_ptr<GrFillRRectOp> GrFillRRectOp::Make(
        GrRecordingContext* ctx, GrAAType aaType, const SkMatrix& viewMatrix, const SkRRect& rrect,
        const GrCaps& caps, GrPaint&& paint) {
    if (!caps.instanceAttribSupport()) {
        return nullptr;
    }

    Flags flags = Flags::kNone;
    if (GrAAType::kCoverage == aaType) {
        // TODO: Support perspective in a follow-on CL. This shouldn't be difficult, since we
        // already use HW derivatives. The only trick will be adjusting the AA outset to account for
        // perspective. (i.e., outset = 0.5 * z.)
        if (viewMatrix.hasPerspective()) {
            return nullptr;
        }
        if (can_use_hw_derivatives_with_coverage(*caps.shaderCaps(), viewMatrix, rrect)) {
            // HW derivatives (more specifically, fwidth()) are consistently faster on all platforms
            // in coverage mode. We use them as long as the approximation will be accurate enough.
            flags |= Flags::kUseHWDerivatives;
        }
    } else {
        if (GrAAType::kMSAA == aaType) {
            if (!caps.sampleLocationsSupport() || !caps.shaderCaps()->sampleVariablesSupport()) {
                return nullptr;
            }
        }
        if (viewMatrix.hasPerspective()) {
            // HW derivatives are consistently slower on all platforms in sample mask mode. We
            // therefore only use them when there is perspective, since then we can't interpolate
            // the symbolic screen-space gradient.
            flags |= Flags::kUseHWDerivatives | Flags::kHasPerspective;
        }
    }

    // Produce a matrix that draws the round rect from normalized [-1, -1, +1, +1] space.
    float l = rrect.rect().left(), r = rrect.rect().right(),
          t = rrect.rect().top(), b = rrect.rect().bottom();
    SkMatrix m;
    // Unmap the normalized rect [-1, -1, +1, +1] back to [l, t, r, b].
    m.setScaleTranslate((r - l)/2, (b - t)/2, (l + r)/2, (t + b)/2);
    // Map to device space.
    m.postConcat(viewMatrix);

    SkRect devBounds;
    if (!(flags & Flags::kHasPerspective)) {
        // Since m is an affine matrix that maps the rect [-1, -1, +1, +1] into the shape's
        // device-space quad, it's quite simple to find the bounding rectangle:
        devBounds = SkRect::MakeXYWH(m.getTranslateX(), m.getTranslateY(), 0, 0);
        devBounds.outset(SkScalarAbs(m.getScaleX()) + SkScalarAbs(m.getSkewX()),
                         SkScalarAbs(m.getSkewY()) + SkScalarAbs(m.getScaleY()));
    } else {
        viewMatrix.mapRect(&devBounds, rrect.rect());
    }

    if (GrAAType::kMSAA == aaType && caps.preferTrianglesOverSampleMask()) {
        // We are on a platform that prefers fine triangles instead of using the sample mask. See if
        // the round rect is large enough that it will be faster for us to send it off to the
        // default path renderer instead. The 200x200 threshold was arrived at using the
        // "shapes_rrect" benchmark on an ARM Galaxy S9.
        if (devBounds.height() * devBounds.width() > 200 * 200) {
            return nullptr;
        }
    }

    GrOpMemoryPool* pool = ctx->priv().opMemoryPool();
    return pool->allocate<GrFillRRectOp>(aaType, rrect, flags, m, std::move(paint), devBounds);
}