SF: Make ExternalTexture mockable
Expose GraphicBuffer properties via ExternalTexture class. Within
SurfaceFlinger access the buffer via this proxy interface.
This allows us to inject and mock GraphicBuffers as needed.
Specifically this will be used to recreate layer state from
transaction traces.
Test: compiles
Bug: 200284593
Change-Id: I2e7f6bee28314b70eac477cfadbf9f94c4d70339
diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp
index eabff58..84771c0 100644
--- a/libs/renderengine/ExternalTexture.cpp
+++ b/libs/renderengine/ExternalTexture.cpp
@@ -14,30 +14,32 @@
* limitations under the License.
*/
-#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <ui/GraphicBuffer.h>
#include "log/log_main.h"
-namespace android::renderengine {
+namespace android::renderengine::impl {
-ExternalTexture::ExternalTexture(const sp<GraphicBuffer>& buffer, RenderEngine& renderEngine,
- uint32_t usage)
+ExternalTexture::ExternalTexture(const sp<GraphicBuffer>& buffer,
+ renderengine::RenderEngine& renderEngine, uint32_t usage)
: mBuffer(buffer), mRenderEngine(renderEngine) {
LOG_ALWAYS_FATAL_IF(buffer == nullptr,
"Attempted to bind a null buffer to an external texture!");
// GLESRenderEngine has a separate texture cache for output buffers,
- if (usage == Usage::WRITEABLE &&
- (mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::GLES ||
- mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::THREADED)) {
+ if (usage == WRITEABLE &&
+ (mRenderEngine.getRenderEngineType() ==
+ renderengine::RenderEngine::RenderEngineType::GLES ||
+ mRenderEngine.getRenderEngineType() ==
+ renderengine::RenderEngine::RenderEngineType::THREADED)) {
return;
}
- mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & Usage::WRITEABLE);
+ mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & WRITEABLE);
}
ExternalTexture::~ExternalTexture() {
mRenderEngine.unmapExternalTextureBuffer(mBuffer);
}
-} // namespace android::renderengine
+} // namespace android::renderengine::impl
diff --git a/libs/renderengine/benchmark/RenderEngineBench.cpp b/libs/renderengine/benchmark/RenderEngineBench.cpp
index 6c8f8e8..ead97cf 100644
--- a/libs/renderengine/benchmark/RenderEngineBench.cpp
+++ b/libs/renderengine/benchmark/RenderEngineBench.cpp
@@ -22,6 +22,7 @@
#include <renderengine/ExternalTexture.h>
#include <renderengine/LayerSettings.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <mutex>
@@ -115,15 +116,15 @@
uint32_t height,
uint64_t extraUsageFlags = 0,
std::string name = "output") {
- return std::make_shared<ExternalTexture>(new GraphicBuffer(width, height,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE |
- extraUsageFlags,
- std::move(name)),
- re,
- ExternalTexture::Usage::READABLE |
- ExternalTexture::Usage::WRITEABLE);
+ return std::make_shared<
+ impl::ExternalTexture>(new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE |
+ extraUsageFlags,
+ std::move(name)),
+ re,
+ impl::ExternalTexture::Usage::READABLE |
+ impl::ExternalTexture::Usage::WRITEABLE);
}
static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h
index 07f0833..621a209 100644
--- a/libs/renderengine/include/renderengine/ExternalTexture.h
+++ b/libs/renderengine/include/renderengine/ExternalTexture.h
@@ -33,28 +33,22 @@
*/
class ExternalTexture {
public:
- // Usage specifies the rendering intent for the buffer.
- enum Usage : uint32_t {
- // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a
- // hint to load the buffer into a separate cache
- READABLE = 1 << 0,
+ ExternalTexture() = default;
+ virtual ~ExternalTexture() = default;
- // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an
- // external texture
- WRITEABLE = 1 << 1,
- };
- // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given
- // usage hint of type Usage.
- ExternalTexture(const sp<GraphicBuffer>& buffer, RenderEngine& renderEngine, uint32_t usage);
-
- ~ExternalTexture();
+ virtual bool hasSameBuffer(const ExternalTexture& other) const = 0;
+ virtual uint32_t getWidth() const = 0;
+ virtual uint32_t getHeight() const = 0;
+ virtual uint64_t getId() const = 0;
+ virtual PixelFormat getPixelFormat() const = 0;
+ virtual uint64_t getUsage() const = 0;
// Retrieves the buffer that is bound to this texture.
- const sp<GraphicBuffer>& getBuffer() const { return mBuffer; }
+ virtual const sp<GraphicBuffer>& getBuffer() const = 0;
-private:
- sp<GraphicBuffer> mBuffer;
- RenderEngine& mRenderEngine;
+ Rect getBounds() const {
+ return {0, 0, static_cast<int32_t>(getWidth()), static_cast<int32_t>(getHeight())};
+ }
DISALLOW_COPY_AND_ASSIGN(ExternalTexture);
};
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index d646756..faa84fc 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -76,6 +76,7 @@
namespace impl {
class RenderEngine;
+class ExternalTexture;
}
enum class Protection {
@@ -228,7 +229,7 @@
// avoid any thread synchronization that may be required by directly calling postRenderCleanup.
virtual bool canSkipPostRenderCleanup() const = 0;
- friend class ExternalTexture;
+ friend class impl::ExternalTexture;
friend class threaded::RenderEngineThreaded;
friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test;
const RenderEngineType mRenderEngineType;
diff --git a/libs/renderengine/include/renderengine/impl/ExternalTexture.h b/libs/renderengine/include/renderengine/impl/ExternalTexture.h
new file mode 100644
index 0000000..c0e24f0
--- /dev/null
+++ b/libs/renderengine/include/renderengine/impl/ExternalTexture.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <renderengine/ExternalTexture.h>
+#include <ui/GraphicBuffer.h>
+
+namespace android::renderengine::impl {
+
+class RenderEngine;
+
+class ExternalTexture : public android::renderengine::ExternalTexture {
+public:
+ // Usage specifies the rendering intent for the buffer.
+ enum Usage : uint32_t {
+ // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a
+ // hint to load the buffer into a separate cache
+ READABLE = 1 << 0,
+
+ // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an
+ // external texture
+ WRITEABLE = 1 << 1,
+ };
+
+ // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given
+ // usage hint of type Usage.
+ ExternalTexture(const sp<GraphicBuffer>& buffer,
+ android::renderengine::RenderEngine& renderEngine, uint32_t usage);
+ ~ExternalTexture();
+ const sp<GraphicBuffer>& getBuffer() const override { return mBuffer; };
+ uint32_t getWidth() const override { return getBuffer()->getWidth(); }
+ uint32_t getHeight() const override { return getBuffer()->getHeight(); }
+ uint64_t getId() const override { return getBuffer()->getId(); }
+ PixelFormat getPixelFormat() const override { return getBuffer()->getPixelFormat(); }
+ uint64_t getUsage() const override { return getBuffer()->getUsage(); }
+ bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+ return getBuffer() == other.getBuffer();
+ }
+
+private:
+ sp<GraphicBuffer> mBuffer;
+ android::renderengine::RenderEngine& mRenderEngine;
+};
+
+} // namespace android::renderengine::impl
diff --git a/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
new file mode 100644
index 0000000..974e0fd
--- /dev/null
+++ b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#pragma once
+
+#include <renderengine/ExternalTexture.h>
+
+namespace android {
+namespace renderengine {
+namespace mock {
+
+class FakeExternalTexture : public renderengine::ExternalTexture {
+ const sp<GraphicBuffer> mNullBuffer = nullptr;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint64_t mId;
+ PixelFormat mPixelFormat;
+ uint64_t mUsage;
+
+public:
+ FakeExternalTexture(uint32_t width, uint32_t height, uint64_t id, PixelFormat pixelFormat,
+ uint64_t usage)
+ : mWidth(width), mHeight(height), mId(id), mPixelFormat(pixelFormat), mUsage(usage) {}
+ const sp<GraphicBuffer>& getBuffer() const { return mNullBuffer; }
+ bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+ return getId() == other.getId();
+ }
+ uint32_t getWidth() const override { return mWidth; }
+ uint32_t getHeight() const override { return mHeight; }
+ uint64_t getId() const override { return mId; }
+ PixelFormat getPixelFormat() const override { return mPixelFormat; }
+ uint64_t getUsage() const override { return mUsage; }
+ ~FakeExternalTexture() = default;
+};
+
+} // namespace mock
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index b18a872..a3a1969 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -19,6 +19,7 @@
#include "android-base/unique_fd.h"
#include "renderengine/DisplaySettings.h"
#include "renderengine/LayerSettings.h"
+#include "renderengine/impl/ExternalTexture.h"
#include "ui/GraphicBuffer.h"
#include "ui/GraphicTypes.h"
#include "ui/PixelFormat.h"
@@ -365,8 +366,8 @@
1, usage, "primeShaderCache_dst");
const auto dstTexture =
- std::make_shared<ExternalTexture>(dstBuffer, *renderengine,
- ExternalTexture::Usage::WRITEABLE);
+ std::make_shared<impl::ExternalTexture>(dstBuffer, *renderengine,
+ impl::ExternalTexture::Usage::WRITEABLE);
// This buffer will be the source for the call to drawImageLayers. Draw
// something to it as a placeholder for what an app draws. We should draw
// something, but the details are not important. Make use of the shadow layer drawing step
@@ -375,10 +376,10 @@
new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
1, usage, "drawImageLayer_src");
- const auto srcTexture =
- std::make_shared<ExternalTexture>(srcBuffer, *renderengine,
- ExternalTexture::Usage::READABLE |
- ExternalTexture::Usage::WRITEABLE);
+ const auto srcTexture = std::make_shared<
+ impl::ExternalTexture>(srcBuffer, *renderengine,
+ impl::ExternalTexture::Usage::READABLE |
+ impl::ExternalTexture::Usage::WRITEABLE);
drawHolePunchLayer(renderengine, display, dstTexture);
drawSolidLayers(renderengine, display, dstTexture);
@@ -398,8 +399,8 @@
new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
1, usageExternal, "primeShaderCache_external");
const auto externalTexture =
- std::make_shared<ExternalTexture>(externalBuffer, *renderengine,
- ExternalTexture::Usage::READABLE);
+ std::make_shared<impl::ExternalTexture>(externalBuffer, *renderengine,
+ impl::ExternalTexture::Usage::READABLE);
std::vector<const std::shared_ptr<ExternalTexture>> textures =
{srcTexture, externalTexture};
@@ -412,8 +413,8 @@
status_t error = f16ExternalBuffer->initCheck();
if (!error) {
const auto f16ExternalTexture =
- std::make_shared<ExternalTexture>(f16ExternalBuffer, *renderengine,
- ExternalTexture::Usage::READABLE);
+ std::make_shared<impl::ExternalTexture>(f16ExternalBuffer, *renderengine,
+ impl::ExternalTexture::Usage::READABLE);
textures.push_back(f16ExternalTexture);
}
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index eb2b2dc..2a25b0b 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -26,6 +26,7 @@
#include <gtest/gtest.h>
#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <sync/sync.h>
#include <system/graphics-base-v1.0.h>
#include <tonemap/tonemap.h>
@@ -178,7 +179,7 @@
public:
std::shared_ptr<renderengine::ExternalTexture> allocateDefaultBuffer() {
return std::make_shared<
- renderengine::
+ renderengine::impl::
ExternalTexture>(new GraphicBuffer(DEFAULT_DISPLAY_WIDTH,
DEFAULT_DISPLAY_HEIGHT,
HAL_PIXEL_FORMAT_RGBA_8888, 1,
@@ -188,15 +189,16 @@
GRALLOC_USAGE_HW_TEXTURE,
"output"),
*mRE,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
}
// Allocates a 1x1 buffer to fill with a solid color
std::shared_ptr<renderengine::ExternalTexture> allocateSourceBuffer(uint32_t width,
uint32_t height) {
return std::make_shared<
- renderengine::
+ renderengine::impl::
ExternalTexture>(new GraphicBuffer(width, height,
HAL_PIXEL_FORMAT_RGBA_8888, 1,
GRALLOC_USAGE_SW_READ_OFTEN |
@@ -204,8 +206,9 @@
GRALLOC_USAGE_HW_TEXTURE,
"input"),
*mRE,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
}
std::shared_ptr<renderengine::ExternalTexture> allocateAndFillSourceBuffer(uint32_t width,
@@ -2439,16 +2442,17 @@
};
auto buf = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_SW_READ_OFTEN |
- GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE,
- "input"),
- *mRE,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, HAL_PIXEL_FORMAT_RGBA_8888,
+ 1,
+ GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "input"),
+ *mRE,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
ASSERT_EQ(0, buf->getBuffer()->initCheck());
{
@@ -2472,16 +2476,17 @@
}
mBuffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_SW_READ_OFTEN |
- GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE,
- "output"),
- *mRE,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, HAL_PIXEL_FORMAT_RGBA_8888,
+ 1,
+ GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "output"),
+ *mRE,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
ASSERT_EQ(0, mBuffer->getBuffer()->initCheck());
const renderengine::LayerSettings layer{
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index db7e12b..9685189 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -17,6 +17,7 @@
#include <cutils/properties.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include "../threaded/RenderEngineThreaded.h"
@@ -174,9 +175,10 @@
renderengine::DisplaySettings settings;
std::vector<renderengine::LayerSettings> layers;
std::shared_ptr<renderengine::ExternalTexture> buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(), *mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
base::unique_fd bufferFence;