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 maskSize,skvx::half2 * outPos)43 const TextureProxy* RasterPathAtlas::onAddShape(const Shape& shape,
44 const Transform& transform,
45 const SkStrokeRec& strokeRec,
46 skvx::half2 maskSize,
47 skvx::half2* outPos) {
48 skgpu::UniqueKey maskKey;
49 bool hasKey = shape.hasKey();
50 if (hasKey) {
51 constexpr int kMaxSmallPathSize = 162;
52 // Try to locate or add to cached DrawAtlas
53 const TextureProxy* proxy = nullptr;
54 if (maskSize.x() <= kMaxSmallPathSize && maskSize.y() <= kMaxSmallPathSize) {
55 proxy = fSmallPathAtlasMgr.findOrCreateEntry(fRecorder,
56 shape,
57 transform,
58 strokeRec,
59 maskSize,
60 outPos);
61 }
62 if (!proxy) {
63 proxy = fCachedAtlasMgr.findOrCreateEntry(fRecorder,
64 shape,
65 transform,
66 strokeRec,
67 maskSize,
68 outPos);
69 }
70 if (proxy) {
71 return proxy;
72 }
73 }
74
75 // try to add to uncached DrawAtlas
76 AtlasLocator loc;
77 return fUncachedAtlasMgr.addToAtlas(fRecorder,
78 shape,
79 transform,
80 strokeRec,
81 maskSize,
82 outPos,
83 &loc);
84 }
85
86 /////////////////////////////////////////////////////////////////////////////////////////
87
onAddToAtlas(const Shape & shape,const Transform & transform,const SkStrokeRec & strokeRec,SkIRect shapeBounds,const AtlasLocator & locator)88 bool RasterPathAtlas::RasterAtlasMgr::onAddToAtlas(const Shape& shape,
89 const Transform& transform,
90 const SkStrokeRec& strokeRec,
91 SkIRect shapeBounds,
92 const AtlasLocator& locator) {
93 // Rasterize path to backing pixmap.
94 // This pixmap will be the size of the Plot that contains the given rect, not the entire atlas,
95 // and hence the position we render at will be relative to that Plot.
96 // The value of outPos is relative to the entire texture, to be used for texture coords.
97 SkAutoPixmapStorage dst;
98 SkIPoint renderPos = fDrawAtlas->prepForRender(locator, &dst);
99
100 RasterMaskHelper helper(&dst);
101 if (!helper.init(fDrawAtlas->plotSize())) {
102 return false;
103 }
104 // Offset to plot location and draw
105 shapeBounds.offset(renderPos.x()+kEntryPadding, renderPos.y()+kEntryPadding);
106 helper.drawShape(shape, transform, strokeRec, shapeBounds);
107
108 return true;
109 }
110
111 } // namespace skgpu::graphite
112