1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
18 #define ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
19 
20 #include <GpuMemoryTracker.h>
21 #include "Caches.h"
22 #include "Texture.h"
23 #include "utils/Macros.h"
24 #include <ui/Region.h>
25 
26 #include <set>
27 
28 namespace android {
29 namespace uirenderer {
30 
31 class RenderState;
32 
33 /**
34  * Lightweight alternative to Layer. Owns the persistent state of an offscreen render target, and
35  * encompasses enough information to draw it back on screen (minus paint properties, which are held
36  * by LayerOp).
37  *
38  * Has two distinct sizes - viewportWidth/viewportHeight describe content area,
39  * texture.width/.height are actual allocated texture size. Texture will tend to be larger than the
40  * viewport bounds, since textures are always allocated with width / height as a multiple of 64, for
41  * the purpose of improving reuse.
42  */
43 class OffscreenBuffer : GpuMemoryTracker {
44 public:
45     OffscreenBuffer(RenderState& renderState, Caches& caches,
46             uint32_t viewportWidth, uint32_t viewportHeight);
47     ~OffscreenBuffer();
48 
49     Rect getTextureCoordinates();
50 
51     void dirty(Rect dirtyArea);
52 
53     // must be called prior to rendering, to construct/update vertex buffer
54     void updateMeshFromRegion();
55 
56     // Set by RenderNode for HW layers, TODO for clipped saveLayers
setWindowTransform(const Matrix4 & transform)57     void setWindowTransform(const Matrix4& transform) {
58         inverseTransformInWindow.loadInverse(transform);
59     }
60 
61     static uint32_t computeIdealDimension(uint32_t dimension);
62 
getSizeInBytes()63     uint32_t getSizeInBytes() { return texture.objectSize(); }
64 
65     RenderState& renderState;
66 
67     uint32_t viewportWidth;
68     uint32_t viewportHeight;
69     Texture texture;
70 
71     // Portion of layer that has been drawn to. Used to minimize drawing area when
72     // drawing back to screen / parent FBO.
73     Region region;
74 
75     Matrix4 inverseTransformInWindow;
76 
77     // vbo / size of mesh
78     GLsizei elementCount = 0;
79     GLuint vbo = 0;
80 
81     bool hasRenderedSinceRepaint;
82 };
83 
84 /**
85  * Pool of OffscreenBuffers allocated, but not currently in use.
86  */
87 class OffscreenBufferPool {
88 public:
89     OffscreenBufferPool();
90     ~OffscreenBufferPool();
91 
92     WARN_UNUSED_RESULT OffscreenBuffer* get(RenderState& renderState,
93             const uint32_t width, const uint32_t height);
94 
95     WARN_UNUSED_RESULT OffscreenBuffer* resize(OffscreenBuffer* layer,
96             const uint32_t width, const uint32_t height);
97 
98     void putOrDelete(OffscreenBuffer* layer);
99 
100     /**
101      * Clears the pool. This causes all layers to be deleted.
102      */
103     void clear();
104 
105     /**
106      * Returns the maximum size of the pool in bytes.
107      */
getMaxSize()108     uint32_t getMaxSize() { return mMaxSize; }
109 
110     /**
111      * Returns the current size of the pool in bytes.
112      */
getSize()113     uint32_t getSize() { return mSize; }
114 
getCount()115     size_t getCount() { return mPool.size(); }
116 
117     /**
118      * Prints out the content of the pool.
119      */
120     void dump();
121 private:
122     struct Entry {
EntryEntry123         Entry() {}
124 
EntryEntry125         Entry(const uint32_t layerWidth, const uint32_t layerHeight)
126                 : width(OffscreenBuffer::computeIdealDimension(layerWidth))
127                 , height(OffscreenBuffer::computeIdealDimension(layerHeight)) {}
128 
EntryEntry129         Entry(OffscreenBuffer* layer)
130                 : layer(layer)
131                 , width(layer->texture.width())
132                 , height(layer->texture.height()) {
133         }
134 
135         static int compare(const Entry& lhs, const Entry& rhs);
136 
137         bool operator==(const Entry& other) const {
138             return compare(*this, other) == 0;
139         }
140 
141         bool operator!=(const Entry& other) const {
142             return compare(*this, other) != 0;
143         }
144 
145         bool operator<(const Entry& other) const {
146             return Entry::compare(*this, other) < 0;
147         }
148 
149         OffscreenBuffer* layer = nullptr;
150         uint32_t width = 0;
151         uint32_t height = 0;
152     }; // struct Entry
153 
154     std::multiset<Entry> mPool;
155 
156     uint32_t mSize = 0;
157     uint32_t mMaxSize;
158 }; // class OffscreenBufferCache
159 
160 }; // namespace uirenderer
161 }; // namespace android
162 
163 #endif // ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
164