1 /*
2 * Copyright 2023 Google LLC
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 "src/gpu/graphite/RasterPathAtlas.h"
9
10 #include "include/core/SkColorSpace.h"
11 #include "include/gpu/graphite/Recorder.h"
12 #include "src/core/SkIPoint16.h"
13 #include "src/gpu/graphite/AtlasProvider.h"
14 #include "src/gpu/graphite/DrawContext.h"
15 #include "src/gpu/graphite/Log.h"
16 #include "src/gpu/graphite/RasterPathUtils.h"
17 #include "src/gpu/graphite/RecorderPriv.h"
18
19 namespace skgpu::graphite {
20
21 static constexpr uint32_t kDefaultAtlasDim = 4096;
22
23 static constexpr uint32_t kSmallPathPlotWidth = 512;
24 static constexpr uint32_t kSmallPathPlotHeight = 256;
25
RasterPathAtlas(Recorder * recorder)26 RasterPathAtlas::RasterPathAtlas(Recorder* recorder)
27 : PathAtlas(recorder, kDefaultAtlasDim, kDefaultAtlasDim)
28 , fCachedAtlasMgr(fWidth, fHeight, fWidth, fHeight, recorder->priv().caps())
29 , fSmallPathAtlasMgr(std::max(fWidth/2, kSmallPathPlotWidth),
30 std::max(fHeight/2, kSmallPathPlotHeight),
31 kSmallPathPlotWidth, kSmallPathPlotHeight,
32 recorder->priv().caps())
33 , fUncachedAtlasMgr(fWidth, fHeight, fWidth, fHeight, recorder->priv().caps()) {
34 SkASSERT(recorder);
35 }
36
recordUploads(DrawContext * dc)37 void RasterPathAtlas::recordUploads(DrawContext* dc) {
38 fCachedAtlasMgr.recordUploads(dc, fRecorder);
39 fSmallPathAtlasMgr.recordUploads(dc, fRecorder);
40 fUncachedAtlasMgr.recordUploads(dc, fRecorder);
41 }
42
onAddShape(const Shape & shape,const Transform & transform,const SkStrokeRec & strokeRec,skvx::half2 maskOrigin,skvx::half2 maskSize,skvx::half2 * outPos)43 const TextureProxy* RasterPathAtlas::onAddShape(const Shape& shape,
44 const Transform& transform,
45 const SkStrokeRec& strokeRec,
46 skvx::half2 maskOrigin,
47 skvx::half2 maskSize,
48 skvx::half2* outPos) {
49 skgpu::UniqueKey maskKey;
50 bool hasKey = shape.hasKey();
51 if (hasKey) {
52 constexpr int kMaxSmallPathSize = 162;
53 // Try to locate or add to cached DrawAtlas
54 const TextureProxy* proxy = nullptr;
55 if (maskSize.x() <= kMaxSmallPathSize && maskSize.y() <= kMaxSmallPathSize) {
56 proxy = fSmallPathAtlasMgr.findOrCreateEntry(fRecorder,
57 shape,
58 transform,
59 strokeRec,
60 maskOrigin,
61 maskSize,
62 outPos);
63 }
64 if (!proxy) {
65 proxy = fCachedAtlasMgr.findOrCreateEntry(fRecorder,
66 shape,
67 transform,
68 strokeRec,
69 maskOrigin,
70 maskSize,
71 outPos);
72 }
73 if (proxy) {
74 return proxy;
75 }
76 }
77
78 // try to add to uncached DrawAtlas
79 AtlasLocator loc;
80 return fUncachedAtlasMgr.addToAtlas(fRecorder,
81 shape,
82 transform,
83 strokeRec,
84 maskSize,
85 outPos,
86 &loc);
87 }
88
89 /////////////////////////////////////////////////////////////////////////////////////////
90
onAddToAtlas(const Shape & shape,const Transform & transform,const SkStrokeRec & strokeRec,SkIRect shapeBounds,const AtlasLocator & locator)91 bool RasterPathAtlas::RasterAtlasMgr::onAddToAtlas(const Shape& shape,
92 const Transform& transform,
93 const SkStrokeRec& strokeRec,
94 SkIRect shapeBounds,
95 const AtlasLocator& locator) {
96 // Rasterize path to backing pixmap.
97 // This pixmap will be the size of the Plot that contains the given rect, not the entire atlas,
98 // and hence the position we render at will be relative to that Plot.
99 // The value of outPos is relative to the entire texture, to be used for texture coords.
100 SkAutoPixmapStorage dst;
101 SkIPoint renderPos = fDrawAtlas->prepForRender(locator, &dst);
102
103 RasterMaskHelper helper(&dst);
104 if (!helper.init(fDrawAtlas->plotSize())) {
105 return false;
106 }
107 // Offset to plot location and draw
108 shapeBounds.offset(renderPos.x()+kEntryPadding, renderPos.y()+kEntryPadding);
109 helper.drawShape(shape, transform, strokeRec, shapeBounds);
110
111 return true;
112 }
113
114 } // namespace skgpu::graphite
115