1 | /* |
2 | * Copyright 2020 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 | #ifndef GrDynamicAtlas_DEFINED |
9 | #define GrDynamicAtlas_DEFINED |
10 | |
11 | #include "src/core/SkArenaAlloc.h" |
12 | #include "src/gpu/GrTextureProxy.h" |
13 | |
14 | class GrOnFlushResourceProvider; |
15 | class GrRenderTargetContext; |
16 | class GrResourceProvider; |
17 | struct SkIPoint16; |
18 | struct SkIRect; |
19 | |
20 | /** |
21 | * This class implements a dynamic size GrRectanizer that grows until it reaches the implementation- |
22 | * dependent max texture size. When finalized, it also creates and stores a GrTextureProxy for the |
23 | * underlying atlas. |
24 | */ |
25 | class GrDynamicAtlas { |
26 | public: |
27 | // As long as GrSurfaceOrigin exists, we just have to decide on one for the atlas texture. |
28 | static constexpr GrSurfaceOrigin kTextureOrigin = kTopLeft_GrSurfaceOrigin; |
29 | static constexpr int kPadding = 1; // Amount of padding below and to the right of each path. |
30 | |
31 | using LazyAtlasDesc = GrSurfaceProxy::LazySurfaceDesc; |
32 | using LazyInstantiateAtlasCallback = GrSurfaceProxy::LazyInstantiateCallback; |
33 | |
34 | enum class InternalMultisample : bool { |
35 | kNo = false, |
36 | kYes = true |
37 | }; |
38 | |
39 | static sk_sp<GrTextureProxy> MakeLazyAtlasProxy(LazyInstantiateAtlasCallback&&, |
40 | GrColorType colorType, |
41 | InternalMultisample, |
42 | const GrCaps&, |
43 | GrSurfaceProxy::UseAllocator); |
44 | |
45 | enum class RectanizerAlgorithm { |
46 | kSkyline, |
47 | kPow2 |
48 | }; |
49 | |
50 | GrDynamicAtlas(GrColorType colorType, InternalMultisample, SkISize initialSize, |
51 | int maxAtlasSize, const GrCaps&, |
52 | RectanizerAlgorithm = RectanizerAlgorithm::kSkyline); |
53 | virtual ~GrDynamicAtlas(); |
54 | |
55 | void reset(SkISize initialSize, const GrCaps& desc); |
56 | |
57 | int maxAtlasSize() const { return fMaxAtlasSize; } |
58 | GrTextureProxy* textureProxy() const { return fTextureProxy.get(); } |
59 | bool isInstantiated() const { return fTextureProxy->isInstantiated(); } |
60 | int currentWidth() const { return fWidth; } |
61 | int currentHeight() const { return fHeight; } |
62 | |
63 | // Attempts to add a rect to the atlas. Returns true if successful, along with the rect's |
64 | // top-left location in the atlas. |
65 | bool addRect(int width, int height, SkIPoint16* location); |
66 | const SkISize& drawBounds() { return fDrawBounds; } |
67 | |
68 | // Instantiates our texture proxy for the atlas and returns a pre-cleared GrRenderTargetContext |
69 | // that the caller may use to render the content. After this call, it is no longer valid to call |
70 | // addRect(), setUserBatchID(), or this method again. |
71 | // |
72 | // 'backingTexture', if provided, is a renderable texture with which to instantiate our proxy. |
73 | // If null then we will create a texture using the resource provider. The purpose of this param |
74 | // is to provide a guaranteed way to recycle a stashed atlas texture from a previous flush. |
75 | std::unique_ptr<GrRenderTargetContext> instantiate( |
76 | GrOnFlushResourceProvider*, sk_sp<GrTexture> backingTexture = nullptr); |
77 | |
78 | private: |
79 | class Node; |
80 | |
81 | Node* makeNode(Node* previous, int l, int t, int r, int b); |
82 | bool internalPlaceRect(int w, int h, SkIPoint16* loc); |
83 | |
84 | const GrColorType fColorType; |
85 | const InternalMultisample fInternalMultisample; |
86 | const int fMaxAtlasSize; |
87 | const RectanizerAlgorithm fRectanizerAlgorithm; |
88 | int fWidth; |
89 | int fHeight; |
90 | SkISize fDrawBounds; |
91 | |
92 | SkSTArenaAllocWithReset<512> fNodeAllocator; |
93 | Node* fTopNode = nullptr; |
94 | |
95 | sk_sp<GrTextureProxy> fTextureProxy; |
96 | sk_sp<GrTexture> fBackingTexture; |
97 | }; |
98 | |
99 | #endif |
100 | |