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
14class GrOnFlushResourceProvider;
15class GrRenderTargetContext;
16class GrResourceProvider;
17struct SkIPoint16;
18struct 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 */
25class GrDynamicAtlas {
26public:
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
78private:
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