Recycle OffscreenBuffers
Change-Id: Ia2e219026f211a5308ecf8209c5f986bb888aadd
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.h b/libs/hwui/renderstate/OffscreenBufferPool.h
new file mode 100644
index 0000000..f0fd82d
--- /dev/null
+++ b/libs/hwui/renderstate/OffscreenBufferPool.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
+#define ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H
+
+#include "Caches.h"
+#include "Texture.h"
+#include "utils/Macros.h"
+
+#include <ui/Region.h>
+
+#include <set>
+
+namespace android {
+namespace uirenderer {
+
+class RenderState;
+
+/**
+ * Lightweight alternative to Layer. Owns the persistent state of an offscreen render target, and
+ * encompasses enough information to draw it back on screen (minus paint properties, which are held
+ * by LayerOp).
+ */
+class OffscreenBuffer {
+public:
+ OffscreenBuffer(RenderState& renderState, Caches& caches,
+ uint32_t viewportWidth, uint32_t viewportHeight);
+ ~OffscreenBuffer();
+
+ // must be called prior to rendering, to construct/update vertex buffer
+ void updateMeshFromRegion();
+
+ static uint32_t computeIdealDimension(uint32_t dimension);
+
+ uint32_t getSizeInBytes() { return texture.width * texture.height * 4; }
+
+ RenderState& renderState;
+ uint32_t viewportWidth;
+ uint32_t viewportHeight;
+ Texture texture;
+
+ // Portion of layer that has been drawn to. Used to minimize drawing area when
+ // drawing back to screen / parent FBO.
+ Region region;
+ GLsizei elementCount = 0;
+ GLuint vbo = 0;
+};
+
+/**
+ * Pool of OffscreenBuffers allocated, but not currently in use.
+ */
+class OffscreenBufferPool {
+public:
+ OffscreenBufferPool();
+ ~OffscreenBufferPool();
+
+ WARN_UNUSED_RESULT OffscreenBuffer* get(RenderState& renderState,
+ const uint32_t width, const uint32_t height);
+
+ WARN_UNUSED_RESULT OffscreenBuffer* resize(OffscreenBuffer* layer,
+ const uint32_t width, const uint32_t height);
+
+ void putOrDelete(OffscreenBuffer* layer);
+
+ /**
+ * Clears the pool. This causes all layers to be deleted.
+ */
+ void clear();
+
+ /**
+ * Returns the maximum size of the pool in bytes.
+ */
+ uint32_t getMaxSize() { return mMaxSize; }
+
+ /**
+ * Returns the current size of the pool in bytes.
+ */
+ uint32_t getSize() { return mSize; }
+
+ size_t getCount() { return mPool.size(); }
+
+ /**
+ * Prints out the content of the pool.
+ */
+ void dump();
+private:
+ struct Entry {
+ Entry() {}
+
+ Entry(const uint32_t layerWidth, const uint32_t layerHeight)
+ : width(OffscreenBuffer::computeIdealDimension(layerWidth))
+ , height(OffscreenBuffer::computeIdealDimension(layerHeight)) {}
+
+ Entry(OffscreenBuffer* layer)
+ : layer(layer)
+ , width(layer->texture.width)
+ , height(layer->texture.height) {
+ }
+
+ static int compare(const Entry& lhs, const Entry& rhs);
+
+ bool operator==(const Entry& other) const {
+ return compare(*this, other) == 0;
+ }
+
+ bool operator!=(const Entry& other) const {
+ return compare(*this, other) != 0;
+ }
+
+ bool operator<(const Entry& other) const {
+ return Entry::compare(*this, other) < 0;
+ }
+
+ OffscreenBuffer* layer = nullptr;
+ uint32_t width = 0;
+ uint32_t height = 0;
+ }; // struct Entry
+
+ std::multiset<Entry> mPool;
+
+ uint32_t mSize = 0;
+ uint32_t mMaxSize;
+}; // class OffscreenBufferCache
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H