1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/v1/Device_v1.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkImageFilter.h" 11cb93a386Sopenharmony_ci#include "include/core/SkMaskFilter.h" 12cb93a386Sopenharmony_ci#include "include/core/SkPathEffect.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPicture.h" 14cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 15cb93a386Sopenharmony_ci#include "include/core/SkVertices.h" 16cb93a386Sopenharmony_ci#include "include/effects/SkRuntimeEffect.h" 17cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 18cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h" 19cb93a386Sopenharmony_ci#include "include/private/SkShadowFlags.h" 20cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 21cb93a386Sopenharmony_ci#include "src/core/SkCanvasPriv.h" 22cb93a386Sopenharmony_ci#include "src/core/SkClipStack.h" 23cb93a386Sopenharmony_ci#include "src/core/SkDraw.h" 24cb93a386Sopenharmony_ci#include "src/core/SkImageFilterCache.h" 25cb93a386Sopenharmony_ci#include "src/core/SkImageFilter_Base.h" 26cb93a386Sopenharmony_ci#include "src/core/SkLatticeIter.h" 27cb93a386Sopenharmony_ci#include "src/core/SkPictureData.h" 28cb93a386Sopenharmony_ci#include "src/core/SkRRectPriv.h" 29cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h" 30cb93a386Sopenharmony_ci#include "src/core/SkRecord.h" 31cb93a386Sopenharmony_ci#include "src/core/SkStroke.h" 32cb93a386Sopenharmony_ci#include "src/core/SkTLazy.h" 33cb93a386Sopenharmony_ci#include "src/core/SkVerticesPriv.h" 34cb93a386Sopenharmony_ci#include "src/gpu/GrBlurUtils.h" 35cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 36cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 37cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h" 38cb93a386Sopenharmony_ci#include "src/gpu/GrStyle.h" 39cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h" 40cb93a386Sopenharmony_ci#include "src/gpu/GrTracing.h" 41cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h" 42cb93a386Sopenharmony_ci#include "src/gpu/effects/GrDisableColorXP.h" 43cb93a386Sopenharmony_ci#include "src/gpu/effects/GrRRectEffect.h" 44cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrStyledShape.h" 45cb93a386Sopenharmony_ci#include "src/image/SkImage_Base.h" 46cb93a386Sopenharmony_ci#include "src/image/SkReadPixelsRec.h" 47cb93a386Sopenharmony_ci#include "src/image/SkSurface_Gpu.h" 48cb93a386Sopenharmony_ci#include "src/utils/SkUTF.h" 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci#define ASSERT_SINGLE_OWNER GR_ASSERT_SINGLE_OWNER(fContext->priv().singleOwner()) 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_cinamespace { 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_cibool force_aa_clip(const skgpu::v1::SurfaceDrawContext* sdc) { 58cb93a386Sopenharmony_ci return sdc->numSamples() > 1 || sdc->alwaysAntialias(); 59cb93a386Sopenharmony_ci} 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ciinline GrPrimitiveType point_mode_to_primitive_type(SkCanvas::PointMode mode) { 62cb93a386Sopenharmony_ci switch (mode) { 63cb93a386Sopenharmony_ci case SkCanvas::kPoints_PointMode: 64cb93a386Sopenharmony_ci return GrPrimitiveType::kPoints; 65cb93a386Sopenharmony_ci case SkCanvas::kLines_PointMode: 66cb93a386Sopenharmony_ci return GrPrimitiveType::kLines; 67cb93a386Sopenharmony_ci case SkCanvas::kPolygon_PointMode: 68cb93a386Sopenharmony_ci return GrPrimitiveType::kLineStrip; 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci SK_ABORT("Unexpected mode"); 71cb93a386Sopenharmony_ci} 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_cistd::unique_ptr<GrFragmentProcessor> make_inverse_rrect_fp(const SkMatrix& viewMatrix, 74cb93a386Sopenharmony_ci const SkRRect& rrect, GrAA aa, 75cb93a386Sopenharmony_ci const GrShaderCaps& shaderCaps) { 76cb93a386Sopenharmony_ci SkTCopyOnFirstWrite<SkRRect> devRRect(rrect); 77cb93a386Sopenharmony_ci if (viewMatrix.isIdentity() || rrect.transform(viewMatrix, devRRect.writable())) { 78cb93a386Sopenharmony_ci auto edgeType = (aa == GrAA::kYes) ? GrClipEdgeType::kInverseFillAA 79cb93a386Sopenharmony_ci : GrClipEdgeType::kInverseFillBW; 80cb93a386Sopenharmony_ci auto [success, fp] = GrRRectEffect::Make(/*inputFP=*/nullptr, edgeType, *devRRect, 81cb93a386Sopenharmony_ci shaderCaps); 82cb93a386Sopenharmony_ci return (success) ? std::move(fp) : nullptr; 83cb93a386Sopenharmony_ci } 84cb93a386Sopenharmony_ci return nullptr; 85cb93a386Sopenharmony_ci} 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_cibool init_vertices_paint(GrRecordingContext* rContext, 88cb93a386Sopenharmony_ci const GrColorInfo& colorInfo, 89cb93a386Sopenharmony_ci const SkPaint& skPaint, 90cb93a386Sopenharmony_ci const SkMatrixProvider& matrixProvider, 91cb93a386Sopenharmony_ci SkBlendMode bmode, 92cb93a386Sopenharmony_ci bool hasColors, 93cb93a386Sopenharmony_ci GrPaint* grPaint) { 94cb93a386Sopenharmony_ci if (hasColors) { 95cb93a386Sopenharmony_ci // When there are colors and a shader, the shader and colors are combined using bmode. 96cb93a386Sopenharmony_ci // With no shader, we just use the colors (kDst). 97cb93a386Sopenharmony_ci return SkPaintToGrPaintWithBlend(rContext, 98cb93a386Sopenharmony_ci colorInfo, 99cb93a386Sopenharmony_ci skPaint, 100cb93a386Sopenharmony_ci matrixProvider, 101cb93a386Sopenharmony_ci skPaint.getShader() ? bmode : SkBlendMode::kDst, 102cb93a386Sopenharmony_ci grPaint); 103cb93a386Sopenharmony_ci } else { 104cb93a386Sopenharmony_ci return SkPaintToGrPaint(rContext, colorInfo, skPaint, matrixProvider, grPaint); 105cb93a386Sopenharmony_ci } 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci} // anonymous namespace 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_cinamespace skgpu::v1 { 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_cisk_sp<BaseDevice> Device::Make(GrRecordingContext* rContext, 113cb93a386Sopenharmony_ci GrColorType colorType, 114cb93a386Sopenharmony_ci sk_sp<GrSurfaceProxy> proxy, 115cb93a386Sopenharmony_ci sk_sp<SkColorSpace> colorSpace, 116cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 117cb93a386Sopenharmony_ci const SkSurfaceProps& surfaceProps, 118cb93a386Sopenharmony_ci InitContents init) { 119cb93a386Sopenharmony_ci auto sdc = SurfaceDrawContext::Make(rContext, 120cb93a386Sopenharmony_ci colorType, 121cb93a386Sopenharmony_ci std::move(proxy), 122cb93a386Sopenharmony_ci std::move(colorSpace), 123cb93a386Sopenharmony_ci origin, 124cb93a386Sopenharmony_ci surfaceProps); 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci return Device::Make(std::move(sdc), kPremul_SkAlphaType, init); 127cb93a386Sopenharmony_ci} 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_cisk_sp<BaseDevice> Device::Make(std::unique_ptr<SurfaceDrawContext> sdc, 130cb93a386Sopenharmony_ci SkAlphaType alphaType, 131cb93a386Sopenharmony_ci InitContents init) { 132cb93a386Sopenharmony_ci if (!sdc) { 133cb93a386Sopenharmony_ci return nullptr; 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci GrRecordingContext* rContext = sdc->recordingContext(); 137cb93a386Sopenharmony_ci if (rContext->abandoned()) { 138cb93a386Sopenharmony_ci return nullptr; 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci SkColorType ct = GrColorTypeToSkColorType(sdc->colorInfo().colorType()); 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci DeviceFlags flags; 144cb93a386Sopenharmony_ci if (!rContext->colorTypeSupportedAsSurface(ct) || 145cb93a386Sopenharmony_ci !CheckAlphaTypeAndGetFlags(alphaType, init, &flags)) { 146cb93a386Sopenharmony_ci return nullptr; 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci return sk_sp<Device>(new Device(std::move(sdc), flags)); 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_cisk_sp<BaseDevice> Device::Make(GrRecordingContext* rContext, 152cb93a386Sopenharmony_ci SkBudgeted budgeted, 153cb93a386Sopenharmony_ci const SkImageInfo& ii, 154cb93a386Sopenharmony_ci SkBackingFit fit, 155cb93a386Sopenharmony_ci int sampleCount, 156cb93a386Sopenharmony_ci GrMipmapped mipMapped, 157cb93a386Sopenharmony_ci GrProtected isProtected, 158cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 159cb93a386Sopenharmony_ci const SkSurfaceProps& props, 160cb93a386Sopenharmony_ci InitContents init) { 161cb93a386Sopenharmony_ci if (!rContext) { 162cb93a386Sopenharmony_ci return nullptr; 163cb93a386Sopenharmony_ci } 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci auto sdc = SurfaceDrawContext::Make(rContext, 166cb93a386Sopenharmony_ci SkColorTypeToGrColorType(ii.colorType()), 167cb93a386Sopenharmony_ci ii.refColorSpace(), 168cb93a386Sopenharmony_ci fit, 169cb93a386Sopenharmony_ci ii.dimensions(), 170cb93a386Sopenharmony_ci props, 171cb93a386Sopenharmony_ci sampleCount, 172cb93a386Sopenharmony_ci mipMapped, 173cb93a386Sopenharmony_ci isProtected, 174cb93a386Sopenharmony_ci origin, 175cb93a386Sopenharmony_ci budgeted); 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci return Device::Make(std::move(sdc), ii.alphaType(), init); 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ciDevice::Device(std::unique_ptr<SurfaceDrawContext> sdc, DeviceFlags flags) 181cb93a386Sopenharmony_ci : INHERITED(sk_ref_sp(sdc->recordingContext()), 182cb93a386Sopenharmony_ci MakeInfo(sdc.get(), flags), 183cb93a386Sopenharmony_ci sdc->surfaceProps()) 184cb93a386Sopenharmony_ci , fSurfaceDrawContext(std::move(sdc)) 185cb93a386Sopenharmony_ci , fClip(SkIRect::MakeSize(fSurfaceDrawContext->dimensions()), 186cb93a386Sopenharmony_ci &this->asMatrixProvider(), 187cb93a386Sopenharmony_ci force_aa_clip(fSurfaceDrawContext.get())) { 188cb93a386Sopenharmony_ci if (flags & DeviceFlags::kNeedClear) { 189cb93a386Sopenharmony_ci this->clearAll(); 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci} 192cb93a386Sopenharmony_ci 193cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_cibool Device::onReadPixels(const SkPixmap& pm, int x, int y) { 196cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ci // Context TODO: Elevate direct context requirement to public API 199cb93a386Sopenharmony_ci auto dContext = fContext->asDirectContext(); 200cb93a386Sopenharmony_ci if (!dContext || !SkImageInfoValidConversion(pm.info(), this->imageInfo())) { 201cb93a386Sopenharmony_ci return false; 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci return fSurfaceDrawContext->readPixels(dContext, pm, {x, y}); 205cb93a386Sopenharmony_ci} 206cb93a386Sopenharmony_ci 207cb93a386Sopenharmony_cibool Device::onWritePixels(const SkPixmap& pm, int x, int y) { 208cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 209cb93a386Sopenharmony_ci 210cb93a386Sopenharmony_ci // Context TODO: Elevate direct context requirement to public API 211cb93a386Sopenharmony_ci auto dContext = fContext->asDirectContext(); 212cb93a386Sopenharmony_ci if (!dContext || !SkImageInfoValidConversion(this->imageInfo(), pm.info())) { 213cb93a386Sopenharmony_ci return false; 214cb93a386Sopenharmony_ci } 215cb93a386Sopenharmony_ci 216cb93a386Sopenharmony_ci return fSurfaceDrawContext->writePixels(dContext, pm, {x, y}); 217cb93a386Sopenharmony_ci} 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_cibool Device::onAccessPixels(SkPixmap* pmap) { 220cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 221cb93a386Sopenharmony_ci return false; 222cb93a386Sopenharmony_ci} 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ciSurfaceDrawContext* Device::surfaceDrawContext() { 225cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 226cb93a386Sopenharmony_ci return fSurfaceDrawContext.get(); 227cb93a386Sopenharmony_ci} 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_ciconst SurfaceDrawContext* Device::surfaceDrawContext() const { 230cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 231cb93a386Sopenharmony_ci return fSurfaceDrawContext.get(); 232cb93a386Sopenharmony_ci} 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ciskgpu::SurfaceFillContext* Device::surfaceFillContext() { 235cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 236cb93a386Sopenharmony_ci return fSurfaceDrawContext.get(); 237cb93a386Sopenharmony_ci} 238cb93a386Sopenharmony_ci 239cb93a386Sopenharmony_civoid Device::clearAll() { 240cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 241cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "clearAll", fContext.get()); 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci SkIRect rect = SkIRect::MakeWH(this->width(), this->height()); 244cb93a386Sopenharmony_ci fSurfaceDrawContext->clearAtLeast(rect, SK_PMColor4fTRANSPARENT); 245cb93a386Sopenharmony_ci} 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_civoid Device::onClipPath(const SkPath& path, SkClipOp op, bool aa) { 250cb93a386Sopenharmony_ci#if GR_TEST_UTILS 251cb93a386Sopenharmony_ci if (fContext->priv().options().fAllPathsVolatile && !path.isVolatile()) { 252cb93a386Sopenharmony_ci this->onClipPath(SkPath(path).setIsVolatile(true), op, aa); 253cb93a386Sopenharmony_ci return; 254cb93a386Sopenharmony_ci } 255cb93a386Sopenharmony_ci#endif 256cb93a386Sopenharmony_ci SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference); 257cb93a386Sopenharmony_ci fClip.clipPath(this->localToDevice(), path, GrAA(aa), op); 258cb93a386Sopenharmony_ci} 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_civoid Device::onClipRegion(const SkRegion& globalRgn, SkClipOp op) { 261cb93a386Sopenharmony_ci SkASSERT(op == SkClipOp::kIntersect || op == SkClipOp::kDifference); 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_ci // Regions don't actually need AA, but in DMSAA mode every clip element is antialiased. 264cb93a386Sopenharmony_ci GrAA aa = GrAA(fSurfaceDrawContext->alwaysAntialias()); 265cb93a386Sopenharmony_ci 266cb93a386Sopenharmony_ci if (globalRgn.isEmpty()) { 267cb93a386Sopenharmony_ci fClip.clipRect(SkMatrix::I(), SkRect::MakeEmpty(), aa, op); 268cb93a386Sopenharmony_ci } else if (globalRgn.isRect()) { 269cb93a386Sopenharmony_ci fClip.clipRect(this->globalToDevice().asM33(), SkRect::Make(globalRgn.getBounds()), aa, op); 270cb93a386Sopenharmony_ci } else { 271cb93a386Sopenharmony_ci SkPath path; 272cb93a386Sopenharmony_ci globalRgn.getBoundaryPath(&path); 273cb93a386Sopenharmony_ci fClip.clipPath(this->globalToDevice().asM33(), path, aa, op); 274cb93a386Sopenharmony_ci } 275cb93a386Sopenharmony_ci} 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_civoid Device::onAsRgnClip(SkRegion* region) const { 278cb93a386Sopenharmony_ci SkIRect bounds = fClip.getConservativeBounds(); 279cb93a386Sopenharmony_ci // Assume wide open and then perform intersect/difference operations reducing the region 280cb93a386Sopenharmony_ci region->setRect(bounds); 281cb93a386Sopenharmony_ci const SkRegion deviceBounds(bounds); 282cb93a386Sopenharmony_ci for (const ClipStack::Element& e : fClip) { 283cb93a386Sopenharmony_ci SkRegion tmp; 284cb93a386Sopenharmony_ci if (e.fShape.isRect() && e.fLocalToDevice.isIdentity()) { 285cb93a386Sopenharmony_ci tmp.setRect(e.fShape.rect().roundOut()); 286cb93a386Sopenharmony_ci } else { 287cb93a386Sopenharmony_ci SkPath tmpPath; 288cb93a386Sopenharmony_ci e.fShape.asPath(&tmpPath); 289cb93a386Sopenharmony_ci tmpPath.transform(e.fLocalToDevice); 290cb93a386Sopenharmony_ci tmp.setPath(tmpPath, deviceBounds); 291cb93a386Sopenharmony_ci } 292cb93a386Sopenharmony_ci 293cb93a386Sopenharmony_ci region->op(tmp, (SkRegion::Op) e.fOp); 294cb93a386Sopenharmony_ci } 295cb93a386Sopenharmony_ci} 296cb93a386Sopenharmony_ci 297cb93a386Sopenharmony_cibool Device::onClipIsAA() const { 298cb93a386Sopenharmony_ci for (const ClipStack::Element& e : fClip) { 299cb93a386Sopenharmony_ci if (e.fAA == GrAA::kYes) { 300cb93a386Sopenharmony_ci return true; 301cb93a386Sopenharmony_ci } 302cb93a386Sopenharmony_ci SkASSERT(!fSurfaceDrawContext->alwaysAntialias()); 303cb93a386Sopenharmony_ci } 304cb93a386Sopenharmony_ci return false; 305cb93a386Sopenharmony_ci} 306cb93a386Sopenharmony_ci 307cb93a386Sopenharmony_ciSkBaseDevice::ClipType Device::onGetClipType() const { 308cb93a386Sopenharmony_ci ClipStack::ClipState state = fClip.clipState(); 309cb93a386Sopenharmony_ci if (state == ClipStack::ClipState::kEmpty) { 310cb93a386Sopenharmony_ci return ClipType::kEmpty; 311cb93a386Sopenharmony_ci } else if (state == ClipStack::ClipState::kDeviceRect || 312cb93a386Sopenharmony_ci state == ClipStack::ClipState::kWideOpen) { 313cb93a386Sopenharmony_ci return ClipType::kRect; 314cb93a386Sopenharmony_ci } else { 315cb93a386Sopenharmony_ci return ClipType::kComplex; 316cb93a386Sopenharmony_ci } 317cb93a386Sopenharmony_ci} 318cb93a386Sopenharmony_ci 319cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_civoid Device::drawPaint(const SkPaint& paint) { 322cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 323cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPaint", fContext.get()); 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_ci GrPaint grPaint; 326cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 327cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 328cb93a386Sopenharmony_ci return; 329cb93a386Sopenharmony_ci } 330cb93a386Sopenharmony_ci 331cb93a386Sopenharmony_ci fSurfaceDrawContext->drawPaint(this->clip(), std::move(grPaint), this->localToDevice()); 332cb93a386Sopenharmony_ci} 333cb93a386Sopenharmony_ci 334cb93a386Sopenharmony_civoid Device::drawPoints(SkCanvas::PointMode mode, 335cb93a386Sopenharmony_ci size_t count, 336cb93a386Sopenharmony_ci const SkPoint pts[], 337cb93a386Sopenharmony_ci const SkPaint& paint) { 338cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 339cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPoints", fContext.get()); 340cb93a386Sopenharmony_ci SkScalar width = paint.getStrokeWidth(); 341cb93a386Sopenharmony_ci if (width < 0) { 342cb93a386Sopenharmony_ci return; 343cb93a386Sopenharmony_ci } 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ci GrAA aa = fSurfaceDrawContext->chooseAA(paint); 346cb93a386Sopenharmony_ci 347cb93a386Sopenharmony_ci if (paint.getPathEffect() && 2 == count && SkCanvas::kLines_PointMode == mode) { 348cb93a386Sopenharmony_ci GrStyle style(paint, SkPaint::kStroke_Style); 349cb93a386Sopenharmony_ci GrPaint grPaint; 350cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 351cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 352cb93a386Sopenharmony_ci return; 353cb93a386Sopenharmony_ci } 354cb93a386Sopenharmony_ci SkPath path; 355cb93a386Sopenharmony_ci path.setIsVolatile(true); 356cb93a386Sopenharmony_ci path.moveTo(pts[0]); 357cb93a386Sopenharmony_ci path.lineTo(pts[1]); 358cb93a386Sopenharmony_ci fSurfaceDrawContext->drawPath(this->clip(), std::move(grPaint), aa, this->localToDevice(), 359cb93a386Sopenharmony_ci path, style); 360cb93a386Sopenharmony_ci return; 361cb93a386Sopenharmony_ci } 362cb93a386Sopenharmony_ci 363cb93a386Sopenharmony_ci SkScalar scales[2]; 364cb93a386Sopenharmony_ci bool isHairline = (0 == width) || 365cb93a386Sopenharmony_ci (1 == width && this->localToDevice().getMinMaxScales(scales) && 366cb93a386Sopenharmony_ci SkScalarNearlyEqual(scales[0], 1.f) && SkScalarNearlyEqual(scales[1], 1.f)); 367cb93a386Sopenharmony_ci // we only handle non-coverage-aa hairlines and paints without path effects or mask filters, 368cb93a386Sopenharmony_ci // else we let the SkDraw call our drawPath() 369cb93a386Sopenharmony_ci if (!isHairline || 370cb93a386Sopenharmony_ci paint.getPathEffect() || 371cb93a386Sopenharmony_ci paint.getMaskFilter() || 372cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAAType(aa) == GrAAType::kCoverage) { 373cb93a386Sopenharmony_ci SkRasterClip rc(this->devClipBounds()); 374cb93a386Sopenharmony_ci SkDraw draw; 375cb93a386Sopenharmony_ci draw.fDst = SkPixmap(SkImageInfo::MakeUnknown(this->width(), this->height()), nullptr, 0); 376cb93a386Sopenharmony_ci draw.fMatrixProvider = this; 377cb93a386Sopenharmony_ci draw.fRC = &rc; 378cb93a386Sopenharmony_ci draw.drawPoints(mode, count, pts, paint, this); 379cb93a386Sopenharmony_ci return; 380cb93a386Sopenharmony_ci } 381cb93a386Sopenharmony_ci 382cb93a386Sopenharmony_ci GrPrimitiveType primitiveType = point_mode_to_primitive_type(mode); 383cb93a386Sopenharmony_ci 384cb93a386Sopenharmony_ci const SkMatrixProvider* matrixProvider = this; 385cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 386cb93a386Sopenharmony_ci SkTLazy<SkPostTranslateMatrixProvider> postTranslateMatrixProvider; 387cb93a386Sopenharmony_ci // This offsetting in device space matches the expectations of the Android framework for non-AA 388cb93a386Sopenharmony_ci // points and lines. 389cb93a386Sopenharmony_ci if (GrIsPrimTypeLines(primitiveType) || GrPrimitiveType::kPoints == primitiveType) { 390cb93a386Sopenharmony_ci static const SkScalar kOffset = 0.063f; // Just greater than 1/16. 391cb93a386Sopenharmony_ci matrixProvider = postTranslateMatrixProvider.init(*matrixProvider, kOffset, kOffset); 392cb93a386Sopenharmony_ci } 393cb93a386Sopenharmony_ci#endif 394cb93a386Sopenharmony_ci 395cb93a386Sopenharmony_ci GrPaint grPaint; 396cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 397cb93a386Sopenharmony_ci *matrixProvider, &grPaint)) { 398cb93a386Sopenharmony_ci return; 399cb93a386Sopenharmony_ci } 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci static constexpr SkVertices::VertexMode kIgnoredMode = SkVertices::kTriangles_VertexMode; 402cb93a386Sopenharmony_ci sk_sp<SkVertices> vertices = SkVertices::MakeCopy(kIgnoredMode, SkToS32(count), pts, nullptr, 403cb93a386Sopenharmony_ci nullptr); 404cb93a386Sopenharmony_ci 405cb93a386Sopenharmony_ci fSurfaceDrawContext->drawVertices(this->clip(), std::move(grPaint), *matrixProvider, 406cb93a386Sopenharmony_ci std::move(vertices), &primitiveType); 407cb93a386Sopenharmony_ci} 408cb93a386Sopenharmony_ci 409cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 410cb93a386Sopenharmony_ci 411cb93a386Sopenharmony_civoid Device::drawRect(const SkRect& rect, const SkPaint& paint) { 412cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 413cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawRect", fContext.get()); 414cb93a386Sopenharmony_ci 415cb93a386Sopenharmony_ci GrStyle style(paint); 416cb93a386Sopenharmony_ci 417cb93a386Sopenharmony_ci // A couple reasons we might need to call drawPath. 418cb93a386Sopenharmony_ci if (paint.getMaskFilter() || paint.getPathEffect()) { 419cb93a386Sopenharmony_ci GrStyledShape shape(rect, style); 420cb93a386Sopenharmony_ci 421cb93a386Sopenharmony_ci GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), 422cb93a386Sopenharmony_ci this->clip(), paint, this->asMatrixProvider(), shape); 423cb93a386Sopenharmony_ci return; 424cb93a386Sopenharmony_ci } 425cb93a386Sopenharmony_ci 426cb93a386Sopenharmony_ci GrPaint grPaint; 427cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 428cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 429cb93a386Sopenharmony_ci return; 430cb93a386Sopenharmony_ci } 431cb93a386Sopenharmony_ci 432cb93a386Sopenharmony_ci fSurfaceDrawContext->drawRect(this->clip(), std::move(grPaint), 433cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), rect, 434cb93a386Sopenharmony_ci &style); 435cb93a386Sopenharmony_ci} 436cb93a386Sopenharmony_ci 437cb93a386Sopenharmony_civoid Device::drawEdgeAAQuad(const SkRect& rect, 438cb93a386Sopenharmony_ci const SkPoint clip[4], 439cb93a386Sopenharmony_ci SkCanvas::QuadAAFlags aaFlags, 440cb93a386Sopenharmony_ci const SkColor4f& color, 441cb93a386Sopenharmony_ci SkBlendMode mode) { 442cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 443cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawEdgeAAQuad", fContext.get()); 444cb93a386Sopenharmony_ci 445cb93a386Sopenharmony_ci SkPMColor4f dstColor = SkColor4fPrepForDst(color, fSurfaceDrawContext->colorInfo()).premul(); 446cb93a386Sopenharmony_ci 447cb93a386Sopenharmony_ci GrPaint grPaint; 448cb93a386Sopenharmony_ci grPaint.setColor4f(dstColor); 449cb93a386Sopenharmony_ci if (mode != SkBlendMode::kSrcOver) { 450cb93a386Sopenharmony_ci grPaint.setXPFactory(SkBlendMode_AsXPFactory(mode)); 451cb93a386Sopenharmony_ci } 452cb93a386Sopenharmony_ci 453cb93a386Sopenharmony_ci // This is exclusively meant for tiling operations, so keep AA enabled to handle MSAA seaming 454cb93a386Sopenharmony_ci GrQuadAAFlags grAA = SkToGrQuadAAFlags(aaFlags); 455cb93a386Sopenharmony_ci if (clip) { 456cb93a386Sopenharmony_ci // Use fillQuadWithEdgeAA 457cb93a386Sopenharmony_ci fSurfaceDrawContext->fillQuadWithEdgeAA(this->clip(), std::move(grPaint), GrAA::kYes, grAA, 458cb93a386Sopenharmony_ci this->localToDevice(), clip, nullptr); 459cb93a386Sopenharmony_ci } else { 460cb93a386Sopenharmony_ci // Use fillRectWithEdgeAA to preserve mathematical properties of dst being rectangular 461cb93a386Sopenharmony_ci fSurfaceDrawContext->fillRectWithEdgeAA(this->clip(), std::move(grPaint), GrAA::kYes, grAA, 462cb93a386Sopenharmony_ci this->localToDevice(), rect); 463cb93a386Sopenharmony_ci } 464cb93a386Sopenharmony_ci} 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 467cb93a386Sopenharmony_ci 468cb93a386Sopenharmony_civoid Device::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 469cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 470cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawRRect", fContext.get()); 471cb93a386Sopenharmony_ci 472cb93a386Sopenharmony_ci SkMaskFilterBase* mf = as_MFB(paint.getMaskFilter()); 473cb93a386Sopenharmony_ci if (mf) { 474cb93a386Sopenharmony_ci if (mf->hasFragmentProcessor()) { 475cb93a386Sopenharmony_ci mf = nullptr; // already handled in SkPaintToGrPaint 476cb93a386Sopenharmony_ci } 477cb93a386Sopenharmony_ci } 478cb93a386Sopenharmony_ci 479cb93a386Sopenharmony_ci GrStyle style(paint); 480cb93a386Sopenharmony_ci 481cb93a386Sopenharmony_ci if (mf || style.pathEffect()) { 482cb93a386Sopenharmony_ci // A path effect will presumably transform this rrect into something else. 483cb93a386Sopenharmony_ci GrStyledShape shape(rrect, style); 484cb93a386Sopenharmony_ci 485cb93a386Sopenharmony_ci GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), 486cb93a386Sopenharmony_ci this->clip(), paint, this->asMatrixProvider(), shape); 487cb93a386Sopenharmony_ci return; 488cb93a386Sopenharmony_ci } 489cb93a386Sopenharmony_ci 490cb93a386Sopenharmony_ci SkASSERT(!style.pathEffect()); 491cb93a386Sopenharmony_ci 492cb93a386Sopenharmony_ci GrPaint grPaint; 493cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 494cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 495cb93a386Sopenharmony_ci return; 496cb93a386Sopenharmony_ci } 497cb93a386Sopenharmony_ci 498cb93a386Sopenharmony_ci fSurfaceDrawContext->drawRRect(this->clip(), std::move(grPaint), 499cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), 500cb93a386Sopenharmony_ci rrect, style); 501cb93a386Sopenharmony_ci} 502cb93a386Sopenharmony_ci 503cb93a386Sopenharmony_civoid Device::drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) { 504cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 505cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawDRRect", fContext.get()); 506cb93a386Sopenharmony_ci if (outer.isEmpty()) { 507cb93a386Sopenharmony_ci return; 508cb93a386Sopenharmony_ci } 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci if (inner.isEmpty()) { 511cb93a386Sopenharmony_ci return this->drawRRect(outer, paint); 512cb93a386Sopenharmony_ci } 513cb93a386Sopenharmony_ci 514cb93a386Sopenharmony_ci SkStrokeRec stroke(paint); 515cb93a386Sopenharmony_ci 516cb93a386Sopenharmony_ci if (stroke.isFillStyle() && !paint.getMaskFilter() && !paint.getPathEffect()) { 517cb93a386Sopenharmony_ci // For axis-aligned filled DRRects, just draw a regular rrect with inner clipped out using a 518cb93a386Sopenharmony_ci // coverage FP instead of using path rendering. 519cb93a386Sopenharmony_ci if (auto fp = make_inverse_rrect_fp(this->localToDevice(), inner, 520cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAA(paint), 521cb93a386Sopenharmony_ci *fSurfaceDrawContext->caps()->shaderCaps())) { 522cb93a386Sopenharmony_ci GrPaint grPaint; 523cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 524cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 525cb93a386Sopenharmony_ci return; 526cb93a386Sopenharmony_ci } 527cb93a386Sopenharmony_ci SkASSERT(!grPaint.hasCoverageFragmentProcessor()); 528cb93a386Sopenharmony_ci grPaint.setCoverageFragmentProcessor(std::move(fp)); 529cb93a386Sopenharmony_ci fSurfaceDrawContext->drawRRect(this->clip(), std::move(grPaint), 530cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAA(paint), 531cb93a386Sopenharmony_ci this->localToDevice(), outer, GrStyle()); 532cb93a386Sopenharmony_ci return; 533cb93a386Sopenharmony_ci } 534cb93a386Sopenharmony_ci } 535cb93a386Sopenharmony_ci 536cb93a386Sopenharmony_ci SkPath path; 537cb93a386Sopenharmony_ci path.setIsVolatile(true); 538cb93a386Sopenharmony_ci path.addRRect(outer); 539cb93a386Sopenharmony_ci path.addRRect(inner); 540cb93a386Sopenharmony_ci path.setFillType(SkPathFillType::kEvenOdd); 541cb93a386Sopenharmony_ci 542cb93a386Sopenharmony_ci // TODO: We are losing the possible mutability of the path here but this should probably be 543cb93a386Sopenharmony_ci // fixed by upgrading GrStyledShape to handle DRRects. 544cb93a386Sopenharmony_ci GrStyledShape shape(path, paint); 545cb93a386Sopenharmony_ci 546cb93a386Sopenharmony_ci GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), this->clip(), 547cb93a386Sopenharmony_ci paint, this->asMatrixProvider(), shape); 548cb93a386Sopenharmony_ci} 549cb93a386Sopenharmony_ci 550cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////// 551cb93a386Sopenharmony_ci 552cb93a386Sopenharmony_civoid Device::drawRegion(const SkRegion& region, const SkPaint& paint) { 553cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 554cb93a386Sopenharmony_ci 555cb93a386Sopenharmony_ci if (paint.getMaskFilter()) { 556cb93a386Sopenharmony_ci SkPath path; 557cb93a386Sopenharmony_ci region.getBoundaryPath(&path); 558cb93a386Sopenharmony_ci path.setIsVolatile(true); 559cb93a386Sopenharmony_ci return this->drawPath(path, paint, true); 560cb93a386Sopenharmony_ci } 561cb93a386Sopenharmony_ci 562cb93a386Sopenharmony_ci GrPaint grPaint; 563cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 564cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 565cb93a386Sopenharmony_ci return; 566cb93a386Sopenharmony_ci } 567cb93a386Sopenharmony_ci 568cb93a386Sopenharmony_ci fSurfaceDrawContext->drawRegion(this->clip(), std::move(grPaint), 569cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), 570cb93a386Sopenharmony_ci region, GrStyle(paint)); 571cb93a386Sopenharmony_ci} 572cb93a386Sopenharmony_ci 573cb93a386Sopenharmony_civoid Device::drawOval(const SkRect& oval, const SkPaint& paint) { 574cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 575cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawOval", fContext.get()); 576cb93a386Sopenharmony_ci 577cb93a386Sopenharmony_ci if (paint.getMaskFilter()) { 578cb93a386Sopenharmony_ci // The RRect path can handle special case blurring 579cb93a386Sopenharmony_ci SkRRect rr = SkRRect::MakeOval(oval); 580cb93a386Sopenharmony_ci return this->drawRRect(rr, paint); 581cb93a386Sopenharmony_ci } 582cb93a386Sopenharmony_ci 583cb93a386Sopenharmony_ci GrPaint grPaint; 584cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 585cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 586cb93a386Sopenharmony_ci return; 587cb93a386Sopenharmony_ci } 588cb93a386Sopenharmony_ci 589cb93a386Sopenharmony_ci fSurfaceDrawContext->drawOval(this->clip(), std::move(grPaint), 590cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), oval, 591cb93a386Sopenharmony_ci GrStyle(paint)); 592cb93a386Sopenharmony_ci} 593cb93a386Sopenharmony_ci 594cb93a386Sopenharmony_civoid Device::drawArc(const SkRect& oval, 595cb93a386Sopenharmony_ci SkScalar startAngle, 596cb93a386Sopenharmony_ci SkScalar sweepAngle, 597cb93a386Sopenharmony_ci bool useCenter, 598cb93a386Sopenharmony_ci const SkPaint& paint) { 599cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 600cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawArc", fContext.get()); 601cb93a386Sopenharmony_ci if (paint.getMaskFilter()) { 602cb93a386Sopenharmony_ci this->INHERITED::drawArc(oval, startAngle, sweepAngle, useCenter, paint); 603cb93a386Sopenharmony_ci return; 604cb93a386Sopenharmony_ci } 605cb93a386Sopenharmony_ci GrPaint grPaint; 606cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 607cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 608cb93a386Sopenharmony_ci return; 609cb93a386Sopenharmony_ci } 610cb93a386Sopenharmony_ci 611cb93a386Sopenharmony_ci fSurfaceDrawContext->drawArc(this->clip(), std::move(grPaint), 612cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), oval, 613cb93a386Sopenharmony_ci startAngle, sweepAngle, useCenter, GrStyle(paint)); 614cb93a386Sopenharmony_ci} 615cb93a386Sopenharmony_ci 616cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 617cb93a386Sopenharmony_ci 618cb93a386Sopenharmony_civoid Device::drawPath(const SkPath& origSrcPath, const SkPaint& paint, bool pathIsMutable) { 619cb93a386Sopenharmony_ci#if GR_TEST_UTILS 620cb93a386Sopenharmony_ci if (fContext->priv().options().fAllPathsVolatile && !origSrcPath.isVolatile()) { 621cb93a386Sopenharmony_ci this->drawPath(SkPath(origSrcPath).setIsVolatile(true), paint, true); 622cb93a386Sopenharmony_ci return; 623cb93a386Sopenharmony_ci } 624cb93a386Sopenharmony_ci#endif 625cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 626cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPath", fContext.get()); 627cb93a386Sopenharmony_ci if (!paint.getMaskFilter()) { 628cb93a386Sopenharmony_ci GrPaint grPaint; 629cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint, 630cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 631cb93a386Sopenharmony_ci return; 632cb93a386Sopenharmony_ci } 633cb93a386Sopenharmony_ci fSurfaceDrawContext->drawPath(this->clip(), std::move(grPaint), 634cb93a386Sopenharmony_ci fSurfaceDrawContext->chooseAA(paint), this->localToDevice(), 635cb93a386Sopenharmony_ci origSrcPath, GrStyle(paint)); 636cb93a386Sopenharmony_ci return; 637cb93a386Sopenharmony_ci } 638cb93a386Sopenharmony_ci 639cb93a386Sopenharmony_ci // TODO: losing possible mutability of 'origSrcPath' here 640cb93a386Sopenharmony_ci GrStyledShape shape(origSrcPath, paint); 641cb93a386Sopenharmony_ci 642cb93a386Sopenharmony_ci GrBlurUtils::drawShapeWithMaskFilter(fContext.get(), fSurfaceDrawContext.get(), this->clip(), 643cb93a386Sopenharmony_ci paint, this->asMatrixProvider(), shape); 644cb93a386Sopenharmony_ci} 645cb93a386Sopenharmony_ci 646cb93a386Sopenharmony_cisk_sp<SkSpecialImage> Device::makeSpecial(const SkBitmap& bitmap) { 647cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 648cb93a386Sopenharmony_ci 649cb93a386Sopenharmony_ci // TODO: this makes a tight copy of 'bitmap' but it doesn't have to be (given SkSpecialImage's 650cb93a386Sopenharmony_ci // semantics). Since this is cached we would have to bake the fit into the cache key though. 651cb93a386Sopenharmony_ci auto view = std::get<0>(GrMakeCachedBitmapProxyView(fContext.get(), bitmap)); 652cb93a386Sopenharmony_ci if (!view) { 653cb93a386Sopenharmony_ci return nullptr; 654cb93a386Sopenharmony_ci } 655cb93a386Sopenharmony_ci 656cb93a386Sopenharmony_ci const SkIRect rect = SkIRect::MakeSize(view.proxy()->dimensions()); 657cb93a386Sopenharmony_ci 658cb93a386Sopenharmony_ci // GrMakeCachedBitmapProxyView creates a tight copy of 'bitmap' so we don't have to subset 659cb93a386Sopenharmony_ci // the special image 660cb93a386Sopenharmony_ci return SkSpecialImage::MakeDeferredFromGpu(fContext.get(), 661cb93a386Sopenharmony_ci rect, 662cb93a386Sopenharmony_ci bitmap.getGenerationID(), 663cb93a386Sopenharmony_ci std::move(view), 664cb93a386Sopenharmony_ci SkColorTypeToGrColorType(bitmap.colorType()), 665cb93a386Sopenharmony_ci bitmap.refColorSpace(), 666cb93a386Sopenharmony_ci this->surfaceProps()); 667cb93a386Sopenharmony_ci} 668cb93a386Sopenharmony_ci 669cb93a386Sopenharmony_cisk_sp<SkSpecialImage> Device::makeSpecial(const SkImage* image) { 670cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 671cb93a386Sopenharmony_ci 672cb93a386Sopenharmony_ci SkPixmap pm; 673cb93a386Sopenharmony_ci if (image->isTextureBacked()) { 674cb93a386Sopenharmony_ci auto [view, ct] = as_IB(image)->asView(this->recordingContext(), GrMipmapped::kNo); 675cb93a386Sopenharmony_ci SkASSERT(view); 676cb93a386Sopenharmony_ci 677cb93a386Sopenharmony_ci return SkSpecialImage::MakeDeferredFromGpu(fContext.get(), 678cb93a386Sopenharmony_ci SkIRect::MakeWH(image->width(), image->height()), 679cb93a386Sopenharmony_ci image->uniqueID(), 680cb93a386Sopenharmony_ci std::move(view), 681cb93a386Sopenharmony_ci ct, 682cb93a386Sopenharmony_ci image->refColorSpace(), 683cb93a386Sopenharmony_ci this->surfaceProps()); 684cb93a386Sopenharmony_ci } else if (image->peekPixels(&pm)) { 685cb93a386Sopenharmony_ci SkBitmap bm; 686cb93a386Sopenharmony_ci 687cb93a386Sopenharmony_ci bm.installPixels(pm); 688cb93a386Sopenharmony_ci return this->makeSpecial(bm); 689cb93a386Sopenharmony_ci } else { 690cb93a386Sopenharmony_ci return nullptr; 691cb93a386Sopenharmony_ci } 692cb93a386Sopenharmony_ci} 693cb93a386Sopenharmony_ci 694cb93a386Sopenharmony_cisk_sp<SkSpecialImage> Device::snapSpecial(const SkIRect& subset, bool forceCopy) { 695cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 696cb93a386Sopenharmony_ci 697cb93a386Sopenharmony_ci auto sdc = fSurfaceDrawContext.get(); 698cb93a386Sopenharmony_ci 699cb93a386Sopenharmony_ci // If we are wrapping a vulkan secondary command buffer, then we can't snap off a special image 700cb93a386Sopenharmony_ci // since it would require us to make a copy of the underlying VkImage which we don't have access 701cb93a386Sopenharmony_ci // to. Additionaly we can't stop and start the render pass that is used with the secondary 702cb93a386Sopenharmony_ci // command buffer. 703cb93a386Sopenharmony_ci if (sdc->wrapsVkSecondaryCB()) { 704cb93a386Sopenharmony_ci return nullptr; 705cb93a386Sopenharmony_ci } 706cb93a386Sopenharmony_ci 707cb93a386Sopenharmony_ci SkASSERT(sdc->asSurfaceProxy()); 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_ci SkIRect finalSubset = subset; 710cb93a386Sopenharmony_ci GrSurfaceProxyView view = sdc->readSurfaceView(); 711cb93a386Sopenharmony_ci if (forceCopy || !view.asTextureProxy()) { 712cb93a386Sopenharmony_ci // When the device doesn't have a texture, or a copy is requested, we create a temporary 713cb93a386Sopenharmony_ci // texture that matches the device contents 714cb93a386Sopenharmony_ci view = GrSurfaceProxyView::Copy(fContext.get(), 715cb93a386Sopenharmony_ci std::move(view), 716cb93a386Sopenharmony_ci GrMipmapped::kNo, // Don't auto generate mips 717cb93a386Sopenharmony_ci subset, 718cb93a386Sopenharmony_ci SkBackingFit::kApprox, 719cb93a386Sopenharmony_ci SkBudgeted::kYes); // Always budgeted 720cb93a386Sopenharmony_ci if (!view) { 721cb93a386Sopenharmony_ci return nullptr; 722cb93a386Sopenharmony_ci } 723cb93a386Sopenharmony_ci // Since this copied only the requested subset, the special image wrapping the proxy no 724cb93a386Sopenharmony_ci // longer needs the original subset. 725cb93a386Sopenharmony_ci finalSubset = SkIRect::MakeSize(view.dimensions()); 726cb93a386Sopenharmony_ci } 727cb93a386Sopenharmony_ci 728cb93a386Sopenharmony_ci GrColorType ct = SkColorTypeToGrColorType(this->imageInfo().colorType()); 729cb93a386Sopenharmony_ci 730cb93a386Sopenharmony_ci return SkSpecialImage::MakeDeferredFromGpu(fContext.get(), 731cb93a386Sopenharmony_ci finalSubset, 732cb93a386Sopenharmony_ci kNeedNewImageUniqueID_SpecialImage, 733cb93a386Sopenharmony_ci std::move(view), 734cb93a386Sopenharmony_ci ct, 735cb93a386Sopenharmony_ci this->imageInfo().refColorSpace(), 736cb93a386Sopenharmony_ci this->surfaceProps()); 737cb93a386Sopenharmony_ci} 738cb93a386Sopenharmony_ci 739cb93a386Sopenharmony_civoid Device::drawDevice(SkBaseDevice* device, 740cb93a386Sopenharmony_ci const SkSamplingOptions& sampling, 741cb93a386Sopenharmony_ci const SkPaint& paint) { 742cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 743cb93a386Sopenharmony_ci // clear of the source device must occur before CHECK_SHOULD_DRAW 744cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawDevice", fContext.get()); 745cb93a386Sopenharmony_ci this->INHERITED::drawDevice(device, sampling, paint); 746cb93a386Sopenharmony_ci} 747cb93a386Sopenharmony_ci 748cb93a386Sopenharmony_civoid Device::drawImageRect(const SkImage* image, 749cb93a386Sopenharmony_ci const SkRect* src, 750cb93a386Sopenharmony_ci const SkRect& dst, 751cb93a386Sopenharmony_ci const SkSamplingOptions& sampling, 752cb93a386Sopenharmony_ci const SkPaint& paint, 753cb93a386Sopenharmony_ci SkCanvas::SrcRectConstraint constraint) { 754cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 755cb93a386Sopenharmony_ci GrAA aa = fSurfaceDrawContext->chooseAA(paint); 756cb93a386Sopenharmony_ci GrQuadAAFlags aaFlags = (aa == GrAA::kYes) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone; 757cb93a386Sopenharmony_ci this->drawImageQuad(image, src, &dst, nullptr, aa, aaFlags, nullptr, sampling, paint, 758cb93a386Sopenharmony_ci constraint); 759cb93a386Sopenharmony_ci} 760cb93a386Sopenharmony_ci 761cb93a386Sopenharmony_civoid Device::drawViewLattice(GrSurfaceProxyView view, 762cb93a386Sopenharmony_ci const GrColorInfo& info, 763cb93a386Sopenharmony_ci std::unique_ptr<SkLatticeIter> iter, 764cb93a386Sopenharmony_ci const SkRect& dst, 765cb93a386Sopenharmony_ci SkFilterMode filter, 766cb93a386Sopenharmony_ci const SkPaint& origPaint) { 767cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawViewLattice", fContext.get()); 768cb93a386Sopenharmony_ci SkASSERT(view); 769cb93a386Sopenharmony_ci 770cb93a386Sopenharmony_ci SkTCopyOnFirstWrite<SkPaint> paint(&origPaint); 771cb93a386Sopenharmony_ci 772cb93a386Sopenharmony_ci if (!info.isAlphaOnly() && (paint->getColor() & 0x00FFFFFF) != 0x00FFFFFF) { 773cb93a386Sopenharmony_ci paint.writable()->setColor(SkColorSetARGB(origPaint.getAlpha(), 0xFF, 0xFF, 0xFF)); 774cb93a386Sopenharmony_ci } 775cb93a386Sopenharmony_ci GrPaint grPaint; 776cb93a386Sopenharmony_ci if (!SkPaintToGrPaintWithPrimitiveColor(this->recordingContext(), 777cb93a386Sopenharmony_ci fSurfaceDrawContext->colorInfo(), *paint, 778cb93a386Sopenharmony_ci this->asMatrixProvider(), &grPaint)) { 779cb93a386Sopenharmony_ci return; 780cb93a386Sopenharmony_ci } 781cb93a386Sopenharmony_ci 782cb93a386Sopenharmony_ci if (info.isAlphaOnly()) { 783cb93a386Sopenharmony_ci // If we were doing this with an FP graph we'd use a kDstIn blend between the texture and 784cb93a386Sopenharmony_ci // the paint color. 785cb93a386Sopenharmony_ci view.concatSwizzle(GrSwizzle("aaaa")); 786cb93a386Sopenharmony_ci } 787cb93a386Sopenharmony_ci auto csxf = GrColorSpaceXform::Make(info, fSurfaceDrawContext->colorInfo()); 788cb93a386Sopenharmony_ci 789cb93a386Sopenharmony_ci fSurfaceDrawContext->drawImageLattice(this->clip(), std::move(grPaint), this->localToDevice(), 790cb93a386Sopenharmony_ci std::move(view), info.alphaType(), std::move(csxf), 791cb93a386Sopenharmony_ci filter, std::move(iter), dst); 792cb93a386Sopenharmony_ci} 793cb93a386Sopenharmony_ci 794cb93a386Sopenharmony_civoid Device::drawImageLattice(const SkImage* image, 795cb93a386Sopenharmony_ci const SkCanvas::Lattice& lattice, 796cb93a386Sopenharmony_ci const SkRect& dst, 797cb93a386Sopenharmony_ci SkFilterMode filter, 798cb93a386Sopenharmony_ci const SkPaint& paint) { 799cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 800cb93a386Sopenharmony_ci auto iter = std::make_unique<SkLatticeIter>(lattice, dst); 801cb93a386Sopenharmony_ci if (auto [view, ct] = as_IB(image)->asView(this->recordingContext(), GrMipmapped::kNo); view) { 802cb93a386Sopenharmony_ci GrColorInfo colorInfo(ct, image->alphaType(), image->refColorSpace()); 803cb93a386Sopenharmony_ci this->drawViewLattice(std::move(view), 804cb93a386Sopenharmony_ci std::move(colorInfo), 805cb93a386Sopenharmony_ci std::move(iter), 806cb93a386Sopenharmony_ci dst, 807cb93a386Sopenharmony_ci filter, 808cb93a386Sopenharmony_ci paint); 809cb93a386Sopenharmony_ci } 810cb93a386Sopenharmony_ci} 811cb93a386Sopenharmony_ci 812cb93a386Sopenharmony_civoid Device::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) { 813cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 814cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawVertices", fContext.get()); 815cb93a386Sopenharmony_ci SkASSERT(vertices); 816cb93a386Sopenharmony_ci 817cb93a386Sopenharmony_ci SkVerticesPriv info(vertices->priv()); 818cb93a386Sopenharmony_ci 819cb93a386Sopenharmony_ci GrPaint grPaint; 820cb93a386Sopenharmony_ci if (!init_vertices_paint(fContext.get(), fSurfaceDrawContext->colorInfo(), paint, 821cb93a386Sopenharmony_ci this->asMatrixProvider(), mode, info.hasColors(), &grPaint)) { 822cb93a386Sopenharmony_ci return; 823cb93a386Sopenharmony_ci } 824cb93a386Sopenharmony_ci fSurfaceDrawContext->drawVertices(this->clip(), 825cb93a386Sopenharmony_ci std::move(grPaint), 826cb93a386Sopenharmony_ci this->asMatrixProvider(), 827cb93a386Sopenharmony_ci sk_ref_sp(const_cast<SkVertices*>(vertices)), 828cb93a386Sopenharmony_ci nullptr); 829cb93a386Sopenharmony_ci} 830cb93a386Sopenharmony_ci 831cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 832cb93a386Sopenharmony_ci 833cb93a386Sopenharmony_civoid Device::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) { 834cb93a386Sopenharmony_ci#if GR_TEST_UTILS 835cb93a386Sopenharmony_ci if (fContext->priv().options().fAllPathsVolatile && !path.isVolatile()) { 836cb93a386Sopenharmony_ci this->drawShadow(SkPath(path).setIsVolatile(true), rec); 837cb93a386Sopenharmony_ci return; 838cb93a386Sopenharmony_ci } 839cb93a386Sopenharmony_ci#endif 840cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 841cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawShadow", fContext.get()); 842cb93a386Sopenharmony_ci 843cb93a386Sopenharmony_ci if (!fSurfaceDrawContext->drawFastShadow(this->clip(), this->localToDevice(), path, rec)) { 844cb93a386Sopenharmony_ci // failed to find an accelerated case 845cb93a386Sopenharmony_ci this->INHERITED::drawShadow(path, rec); 846cb93a386Sopenharmony_ci } 847cb93a386Sopenharmony_ci} 848cb93a386Sopenharmony_ci 849cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 850cb93a386Sopenharmony_ci 851cb93a386Sopenharmony_civoid Device::drawAtlas(const SkRSXform xform[], 852cb93a386Sopenharmony_ci const SkRect texRect[], 853cb93a386Sopenharmony_ci const SkColor colors[], 854cb93a386Sopenharmony_ci int count, 855cb93a386Sopenharmony_ci SkBlendMode mode, 856cb93a386Sopenharmony_ci const SkPaint& paint) { 857cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 858cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawAtlas", fContext.get()); 859cb93a386Sopenharmony_ci 860cb93a386Sopenharmony_ci GrPaint grPaint; 861cb93a386Sopenharmony_ci if (colors) { 862cb93a386Sopenharmony_ci if (!SkPaintToGrPaintWithBlend(this->recordingContext(), fSurfaceDrawContext->colorInfo(), 863cb93a386Sopenharmony_ci paint, this->asMatrixProvider(), mode, &grPaint)) { 864cb93a386Sopenharmony_ci return; 865cb93a386Sopenharmony_ci } 866cb93a386Sopenharmony_ci } else { 867cb93a386Sopenharmony_ci if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), 868cb93a386Sopenharmony_ci paint, this->asMatrixProvider(), &grPaint)) { 869cb93a386Sopenharmony_ci return; 870cb93a386Sopenharmony_ci } 871cb93a386Sopenharmony_ci } 872cb93a386Sopenharmony_ci 873cb93a386Sopenharmony_ci fSurfaceDrawContext->drawAtlas(this->clip(), std::move(grPaint), this->localToDevice(), count, 874cb93a386Sopenharmony_ci xform, texRect, colors); 875cb93a386Sopenharmony_ci} 876cb93a386Sopenharmony_ci 877cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 878cb93a386Sopenharmony_ci 879cb93a386Sopenharmony_civoid Device::onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint) { 880cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 881cb93a386Sopenharmony_ci GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawGlyphRunList", fContext.get()); 882cb93a386Sopenharmony_ci SkASSERT(!glyphRunList.hasRSXForm()); 883cb93a386Sopenharmony_ci 884cb93a386Sopenharmony_ci fSurfaceDrawContext->drawGlyphRunList( 885cb93a386Sopenharmony_ci this->clip(), this->asMatrixProvider(), glyphRunList, paint); 886cb93a386Sopenharmony_ci} 887cb93a386Sopenharmony_ci 888cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 889cb93a386Sopenharmony_ci 890cb93a386Sopenharmony_civoid Device::drawDrawable(SkDrawable* drawable, const SkMatrix* matrix, SkCanvas* canvas) { 891cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 892cb93a386Sopenharmony_ci 893cb93a386Sopenharmony_ci GrBackendApi api = this->recordingContext()->backend(); 894cb93a386Sopenharmony_ci if (GrBackendApi::kVulkan == api) { 895cb93a386Sopenharmony_ci const SkMatrix& ctm = this->localToDevice(); 896cb93a386Sopenharmony_ci const SkMatrix& combinedMatrix = matrix ? SkMatrix::Concat(ctm, *matrix) : ctm; 897cb93a386Sopenharmony_ci std::unique_ptr<SkDrawable::GpuDrawHandler> gpuDraw = 898cb93a386Sopenharmony_ci drawable->snapGpuDrawHandler(api, combinedMatrix, this->devClipBounds(), 899cb93a386Sopenharmony_ci this->imageInfo()); 900cb93a386Sopenharmony_ci if (gpuDraw) { 901cb93a386Sopenharmony_ci fSurfaceDrawContext->drawDrawable( 902cb93a386Sopenharmony_ci std::move(gpuDraw), combinedMatrix.mapRect(drawable->getBounds())); 903cb93a386Sopenharmony_ci return; 904cb93a386Sopenharmony_ci } 905cb93a386Sopenharmony_ci } 906cb93a386Sopenharmony_ci this->INHERITED::drawDrawable(drawable, matrix, canvas); 907cb93a386Sopenharmony_ci} 908cb93a386Sopenharmony_ci 909cb93a386Sopenharmony_ci 910cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 911cb93a386Sopenharmony_ci 912cb93a386Sopenharmony_cibool Device::wait(int numSemaphores, 913cb93a386Sopenharmony_ci const GrBackendSemaphore* waitSemaphores, 914cb93a386Sopenharmony_ci bool deleteSemaphoresAfterWait) { 915cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 916cb93a386Sopenharmony_ci 917cb93a386Sopenharmony_ci return fSurfaceDrawContext->waitOnSemaphores(numSemaphores, waitSemaphores, 918cb93a386Sopenharmony_ci deleteSemaphoresAfterWait); 919cb93a386Sopenharmony_ci} 920cb93a386Sopenharmony_ci 921cb93a386Sopenharmony_cibool Device::replaceBackingProxy(SkSurface::ContentChangeMode mode, 922cb93a386Sopenharmony_ci sk_sp<GrRenderTargetProxy> newRTP, 923cb93a386Sopenharmony_ci GrColorType grColorType, 924cb93a386Sopenharmony_ci sk_sp<SkColorSpace> colorSpace, 925cb93a386Sopenharmony_ci GrSurfaceOrigin origin, 926cb93a386Sopenharmony_ci const SkSurfaceProps& props) { 927cb93a386Sopenharmony_ci auto sdc = SurfaceDrawContext::Make(fContext.get(), grColorType, std::move(newRTP), 928cb93a386Sopenharmony_ci std::move(colorSpace), origin, props); 929cb93a386Sopenharmony_ci if (!sdc) { 930cb93a386Sopenharmony_ci return false; 931cb93a386Sopenharmony_ci } 932cb93a386Sopenharmony_ci 933cb93a386Sopenharmony_ci SkASSERT(sdc->dimensions() == fSurfaceDrawContext->dimensions()); 934cb93a386Sopenharmony_ci SkASSERT(sdc->numSamples() == fSurfaceDrawContext->numSamples()); 935cb93a386Sopenharmony_ci SkASSERT(sdc->asSurfaceProxy()->priv().isExact()); 936cb93a386Sopenharmony_ci if (mode == SkSurface::kRetain_ContentChangeMode) { 937cb93a386Sopenharmony_ci if (fContext->abandoned()) { 938cb93a386Sopenharmony_ci return false; 939cb93a386Sopenharmony_ci } 940cb93a386Sopenharmony_ci 941cb93a386Sopenharmony_ci SkASSERT(fSurfaceDrawContext->asTextureProxy()); 942cb93a386Sopenharmony_ci SkAssertResult(sdc->blitTexture(fSurfaceDrawContext->readSurfaceView(), 943cb93a386Sopenharmony_ci SkIRect::MakeWH(this->width(), this->height()), 944cb93a386Sopenharmony_ci SkIPoint::Make(0, 0))); 945cb93a386Sopenharmony_ci } 946cb93a386Sopenharmony_ci 947cb93a386Sopenharmony_ci fSurfaceDrawContext = std::move(sdc); 948cb93a386Sopenharmony_ci return true; 949cb93a386Sopenharmony_ci} 950cb93a386Sopenharmony_ci 951cb93a386Sopenharmony_civoid Device::asyncRescaleAndReadPixels(const SkImageInfo& info, 952cb93a386Sopenharmony_ci const SkIRect& srcRect, 953cb93a386Sopenharmony_ci RescaleGamma rescaleGamma, 954cb93a386Sopenharmony_ci RescaleMode rescaleMode, 955cb93a386Sopenharmony_ci ReadPixelsCallback callback, 956cb93a386Sopenharmony_ci ReadPixelsContext context) { 957cb93a386Sopenharmony_ci auto* sdc = fSurfaceDrawContext.get(); 958cb93a386Sopenharmony_ci // Context TODO: Elevate direct context requirement to public API. 959cb93a386Sopenharmony_ci auto dContext = sdc->recordingContext()->asDirectContext(); 960cb93a386Sopenharmony_ci if (!dContext) { 961cb93a386Sopenharmony_ci return; 962cb93a386Sopenharmony_ci } 963cb93a386Sopenharmony_ci sdc->asyncRescaleAndReadPixels(dContext, info, srcRect, rescaleGamma, rescaleMode, callback, 964cb93a386Sopenharmony_ci context); 965cb93a386Sopenharmony_ci} 966cb93a386Sopenharmony_ci 967cb93a386Sopenharmony_civoid Device::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace, 968cb93a386Sopenharmony_ci sk_sp<SkColorSpace> dstColorSpace, 969cb93a386Sopenharmony_ci const SkIRect& srcRect, 970cb93a386Sopenharmony_ci SkISize dstSize, 971cb93a386Sopenharmony_ci RescaleGamma rescaleGamma, 972cb93a386Sopenharmony_ci RescaleMode rescaleMode, 973cb93a386Sopenharmony_ci ReadPixelsCallback callback, 974cb93a386Sopenharmony_ci ReadPixelsContext context) { 975cb93a386Sopenharmony_ci auto* sdc = fSurfaceDrawContext.get(); 976cb93a386Sopenharmony_ci // Context TODO: Elevate direct context requirement to public API. 977cb93a386Sopenharmony_ci auto dContext = sdc->recordingContext()->asDirectContext(); 978cb93a386Sopenharmony_ci if (!dContext) { 979cb93a386Sopenharmony_ci return; 980cb93a386Sopenharmony_ci } 981cb93a386Sopenharmony_ci sdc->asyncRescaleAndReadPixelsYUV420(dContext, 982cb93a386Sopenharmony_ci yuvColorSpace, 983cb93a386Sopenharmony_ci std::move(dstColorSpace), 984cb93a386Sopenharmony_ci srcRect, 985cb93a386Sopenharmony_ci dstSize, 986cb93a386Sopenharmony_ci rescaleGamma, 987cb93a386Sopenharmony_ci rescaleMode, 988cb93a386Sopenharmony_ci callback, 989cb93a386Sopenharmony_ci context); 990cb93a386Sopenharmony_ci} 991cb93a386Sopenharmony_ci 992cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 993cb93a386Sopenharmony_ci 994cb93a386Sopenharmony_ciSkBaseDevice* Device::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) { 995cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 996cb93a386Sopenharmony_ci 997cb93a386Sopenharmony_ci SkSurfaceProps props(this->surfaceProps().flags(), cinfo.fPixelGeometry); 998cb93a386Sopenharmony_ci 999cb93a386Sopenharmony_ci // layers are never drawn in repeat modes, so we can request an approx 1000cb93a386Sopenharmony_ci // match and ignore any padding. 1001cb93a386Sopenharmony_ci SkBackingFit fit = kNever_TileUsage == cinfo.fTileUsage ? SkBackingFit::kApprox 1002cb93a386Sopenharmony_ci : SkBackingFit::kExact; 1003cb93a386Sopenharmony_ci 1004cb93a386Sopenharmony_ci SkASSERT(cinfo.fInfo.colorType() != kRGBA_1010102_SkColorType); 1005cb93a386Sopenharmony_ci 1006cb93a386Sopenharmony_ci auto sdc = SurfaceDrawContext::MakeWithFallback( 1007cb93a386Sopenharmony_ci fContext.get(), SkColorTypeToGrColorType(cinfo.fInfo.colorType()), 1008cb93a386Sopenharmony_ci fSurfaceDrawContext->colorInfo().refColorSpace(), fit, cinfo.fInfo.dimensions(), props, 1009cb93a386Sopenharmony_ci fSurfaceDrawContext->numSamples(), GrMipmapped::kNo, 1010cb93a386Sopenharmony_ci fSurfaceDrawContext->asSurfaceProxy()->isProtected(), kBottomLeft_GrSurfaceOrigin, 1011cb93a386Sopenharmony_ci SkBudgeted::kYes); 1012cb93a386Sopenharmony_ci if (!sdc) { 1013cb93a386Sopenharmony_ci return nullptr; 1014cb93a386Sopenharmony_ci } 1015cb93a386Sopenharmony_ci 1016cb93a386Sopenharmony_ci // Skia's convention is to only clear a device if it is non-opaque. 1017cb93a386Sopenharmony_ci InitContents init = cinfo.fInfo.isOpaque() ? InitContents::kUninit : InitContents::kClear; 1018cb93a386Sopenharmony_ci 1019cb93a386Sopenharmony_ci return Device::Make(std::move(sdc), cinfo.fInfo.alphaType(), init).release(); 1020cb93a386Sopenharmony_ci} 1021cb93a386Sopenharmony_ci 1022cb93a386Sopenharmony_cisk_sp<SkSurface> Device::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 1023cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1024cb93a386Sopenharmony_ci // TODO: Change the signature of newSurface to take a budgeted parameter. 1025cb93a386Sopenharmony_ci static const SkBudgeted kBudgeted = SkBudgeted::kNo; 1026cb93a386Sopenharmony_ci return SkSurface::MakeRenderTarget(fContext.get(), kBudgeted, info, 1027cb93a386Sopenharmony_ci fSurfaceDrawContext->numSamples(), 1028cb93a386Sopenharmony_ci fSurfaceDrawContext->origin(), &props); 1029cb93a386Sopenharmony_ci} 1030cb93a386Sopenharmony_ci 1031cb93a386Sopenharmony_ciSkImageFilterCache* Device::getImageFilterCache() { 1032cb93a386Sopenharmony_ci ASSERT_SINGLE_OWNER 1033cb93a386Sopenharmony_ci // We always return a transient cache, so it is freed after each 1034cb93a386Sopenharmony_ci // filter traversal. 1035cb93a386Sopenharmony_ci return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize); 1036cb93a386Sopenharmony_ci} 1037cb93a386Sopenharmony_ci 1038cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////// 1039cb93a386Sopenharmony_ci 1040cb93a386Sopenharmony_cibool Device::android_utils_clipWithStencil() { 1041cb93a386Sopenharmony_ci SkRegion clipRegion; 1042cb93a386Sopenharmony_ci this->onAsRgnClip(&clipRegion); 1043cb93a386Sopenharmony_ci if (clipRegion.isEmpty()) { 1044cb93a386Sopenharmony_ci return false; 1045cb93a386Sopenharmony_ci } 1046cb93a386Sopenharmony_ci auto sdc = fSurfaceDrawContext.get(); 1047cb93a386Sopenharmony_ci SkASSERT(sdc); 1048cb93a386Sopenharmony_ci GrPaint grPaint; 1049cb93a386Sopenharmony_ci grPaint.setXPFactory(GrDisableColorXPFactory::Get()); 1050cb93a386Sopenharmony_ci static constexpr GrUserStencilSettings kDrawToStencil( 1051cb93a386Sopenharmony_ci GrUserStencilSettings::StaticInit< 1052cb93a386Sopenharmony_ci 0x1, 1053cb93a386Sopenharmony_ci GrUserStencilTest::kAlways, 1054cb93a386Sopenharmony_ci 0x1, 1055cb93a386Sopenharmony_ci GrUserStencilOp::kReplace, 1056cb93a386Sopenharmony_ci GrUserStencilOp::kReplace, 1057cb93a386Sopenharmony_ci 0x1>() 1058cb93a386Sopenharmony_ci ); 1059cb93a386Sopenharmony_ci // Regions don't actually need AA, but in DMSAA mode everything is antialiased. 1060cb93a386Sopenharmony_ci GrAA aa = GrAA(fSurfaceDrawContext->alwaysAntialias()); 1061cb93a386Sopenharmony_ci sdc->drawRegion(nullptr, std::move(grPaint), aa, SkMatrix::I(), clipRegion, 1062cb93a386Sopenharmony_ci GrStyle::SimpleFill(), &kDrawToStencil); 1063cb93a386Sopenharmony_ci return true; 1064cb93a386Sopenharmony_ci} 1065cb93a386Sopenharmony_ci 1066cb93a386Sopenharmony_cibool Device::drawBlurImage(const SkImage* image, const SkBlurArg& blurArg) 1067cb93a386Sopenharmony_ci{ 1068cb93a386Sopenharmony_ci if (image == nullptr) { 1069cb93a386Sopenharmony_ci return false; 1070cb93a386Sopenharmony_ci } 1071cb93a386Sopenharmony_ci if (auto[view, ct] = as_IB(image)->asView(this->recordingContext(), GrMipmapped::kNo); view) { 1072cb93a386Sopenharmony_ci return fSurfaceDrawContext->drawBlurImage(std::move(view), blurArg); 1073cb93a386Sopenharmony_ci } 1074cb93a386Sopenharmony_ci} 1075cb93a386Sopenharmony_ci 1076cb93a386Sopenharmony_ci} // namespace skgpu::v1 1077