First-pass for the new RenderEngine interface.
Includes separate test suite just for renderengine, so that we can test
against the interface directly.
I'll try to sync the interface definition in go/re-interface-cleanup
with whatever we land on here.
TODOs (future cls):
* Adding/deleting textures (move SF texture pool behind renderengine?)
* BufferLayer::bindTextureImage should probably move behind RE since
there's some duplicated code.
Bug: 117103231
Change-Id: Ib155b47c7c2ebbb9a23075a8534bd2842e846b9e
Test: test-renderengine
diff --git a/services/surfaceflinger/RenderEngine/TEST_MAPPING b/services/surfaceflinger/RenderEngine/TEST_MAPPING
new file mode 100644
index 0000000..995dba1
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "librenderengine_test"
+ }
+ ]
+}
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index 5c4c3d5..dbf50c5 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -650,6 +650,13 @@
} while (true);
}
+status_t GLES20RenderEngine::drawLayers(const DisplaySettings& /*settings*/,
+ const std::vector<LayerSettings>& /*layers*/,
+ ANativeWindowBuffer* const /*buffer*/,
+ base::unique_fd* /*displayFence*/) const {
+ return NO_ERROR;
+}
+
void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
ui::Transform::orientation_flags rotation) {
int32_t l = sourceCrop.left;
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
index 4f03a90..b08e096 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
@@ -73,6 +73,10 @@
void unbindFrameBuffer(Framebuffer* framebuffer) override;
void checkErrors() const override;
+ status_t drawLayers(const DisplaySettings& settings, const std::vector<LayerSettings>& layers,
+ ANativeWindowBuffer* const buffer,
+ base::unique_fd* displayFence) const override;
+
// internal to RenderEngine
EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
EGLConfig getEGLConfig() const { return mEGLConfig; }
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/DisplaySettings.h b/services/surfaceflinger/RenderEngine/include/renderengine/DisplaySettings.h
new file mode 100644
index 0000000..5941cdf
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/DisplaySettings.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 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 <math/mat4.h>
+#include <ui/GraphicTypes.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+namespace android {
+namespace renderengine {
+
+// DisplaySettings contains the settings that are applicable when drawing all
+// layers for a given display.
+struct DisplaySettings {
+ // Rectangle describing the physical display. We will project from the
+ // logical clip onto this rectangle.
+ Rect physicalDisplay;
+
+ // Rectangle bounded by the x,y- clipping planes in the logical display, so
+ // that the orthographic projection matrix can be computed. When
+ // constructing this matrix, z-coordinate bound are assumed to be at z=0 and
+ // z=1.
+ Rect clip;
+
+ // Global transform to apply to all layers.
+ mat4 globalTransform;
+
+ // Maximum luminance pulled from the display's HDR capabilities.
+ float maxLuminence;
+
+ // Output dataspace that will be populated if wide color gamut is used, or
+ // DataSpace::UNKNOWN otherwise.
+ ui::Dataspace outputDataspace;
+
+ // Additional color transform to apply in linear space after transforming
+ // to the output dataspace.
+ mat4 colorTransform;
+
+ // Region that will be cleared to (0, 0, 0, 0) prior to rendering.
+ // clearRegion will first be transformed by globalTransform so that it will
+ // be in the same coordinate space as the rendered layers.
+ Region clearRegion;
+};
+
+} // namespace renderengine
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/LayerSettings.h b/services/surfaceflinger/RenderEngine/include/renderengine/LayerSettings.h
new file mode 100644
index 0000000..facea21
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/LayerSettings.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 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 <math/mat4.h>
+#include <math/vec3.h>
+#include <renderengine/Texture.h>
+#include <ui/FloatRect.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicTypes.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+#include <ui/Transform.h>
+
+namespace android {
+namespace renderengine {
+
+// Metadata describing the input buffer to render from.
+struct Buffer {
+ // Buffer containing the image that we will render.
+ // If buffer == nullptr, then the rest of the fields in this struct will be
+ // ignored.
+ sp<GraphicBuffer> buffer;
+
+ // Texture identifier to bind the external texture to.
+ // TODO(alecmouri): This is GL-specific...make the type backend-agnostic.
+ uint32_t textureName;
+
+ // Whether to use filtering when rendering the texture.
+ bool useTextureFiltering;
+
+ // Transform matrix to apply to texture coordinates.
+ mat4 textureTransform;
+
+ // Wheteher to use pre-multiplied alpha
+ bool usePremultipliedAlpha;
+
+ // HDR color-space setting for Y410.
+ bool isY410BT2020;
+};
+
+// Metadata describing the layer geometry.
+struct Geometry {
+ // Boundaries of the layer.
+ FloatRect boundaries;
+
+ // Transform matrix to apply to mesh coordinates.
+ mat4 positionTransform;
+};
+
+// Descriptor of the source pixels for this layer.
+struct PixelSource {
+ // Source buffer
+ Buffer buffer;
+
+ // The solid color with which to fill the layer.
+ // This should only be populated if we don't render from an application
+ // buffer.
+ half3 solidColor;
+};
+
+// The settings that RenderEngine requires for correctly rendering a Layer.
+struct LayerSettings {
+ // Geometry information
+ Geometry geometry;
+
+ // Source pixels for this layer.
+ PixelSource source;
+
+ // Alpha option to apply to the source pixels
+ half alpha;
+
+ // Color space describing how the source pixels should be interpreted.
+ ui::Dataspace sourceDataspace;
+};
+
+} // namespace renderengine
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
index 122271f..f5d3d6b 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
@@ -23,8 +23,10 @@
#include <android-base/unique_fd.h>
#include <math/mat4.h>
+#include <renderengine/DisplaySettings.h>
#include <renderengine/Framebuffer.h>
#include <renderengine/Image.h>
+#include <renderengine/LayerSettings.h>
#include <ui/GraphicTypes.h>
#include <ui/Transform.h>
@@ -64,6 +66,11 @@
virtual ~RenderEngine() = 0;
+ // ----- BEGIN DEPRECATED INTERFACE -----
+ // This interface, while still in use until a suitable replacement is built,
+ // should be considered deprecated, minus some methods which still may be
+ // used to support legacy behavior.
+
virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
virtual std::unique_ptr<Surface> createSurface() = 0;
virtual std::unique_ptr<Image> createImage() = 0;
@@ -133,6 +140,37 @@
// queries
virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0;
+
+ // ----- END DEPRECATED INTERFACE -----
+
+ // ----- BEGIN NEW INTERFACE -----
+
+ // Renders layers for a particular display via GPU composition. This method
+ // should be called for every display that needs to be rendered via the GPU.
+ // @param settings The display-wide settings that should be applied prior to
+ // drawing any layers.
+ // @param layers The layers to draw onto the display, in Z-order.
+ // @param buffer The buffer which will be drawn to. This buffer will be
+ // ready once displayFence fires.
+ // @param displayFence A pointer to a fence, which will fire when the buffer
+ // has been drawn to and is ready to be examined. The fence will be
+ // initialized by this method. The caller will be responsible for owning the
+ // fence.
+ // @return An error code indicating whether drawing was successful. For
+ // now, this always returns NO_ERROR.
+ // TODO(alecmouri): Consider making this a multi-display API, so that the
+ // caller deoes not need to handle multiple fences.
+ virtual status_t drawLayers(const DisplaySettings& settings,
+ const std::vector<LayerSettings>& layers,
+ ANativeWindowBuffer* const buffer,
+ base::unique_fd* displayFence) const = 0;
+
+ // TODO(alecmouri): Expose something like bindTexImage() so that devices
+ // that don't support native sync fences can get rid of code duplicated
+ // between BufferStateLayer and BufferQueueLayer for binding an external
+ // texture.
+
+ // TODO(alecmouri): Add API to help with managing a texture pool.
};
class BindNativeBufferAsFramebuffer {
diff --git a/services/surfaceflinger/RenderEngine/tests/Android.bp b/services/surfaceflinger/RenderEngine/tests/Android.bp
new file mode 100644
index 0000000..65b7c82
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/tests/Android.bp
@@ -0,0 +1,36 @@
+// Copyright 2018 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.
+
+cc_test {
+ name: "librenderengine_test",
+ defaults: ["surfaceflinger_defaults"],
+ test_suites: ["device-tests"],
+ srcs: [
+ "RenderEngineTest.cpp",
+ ],
+ static_libs: [
+ "libgmock",
+ "librenderengine",
+ ],
+ shared_libs: [
+ "libcutils",
+ "libEGL",
+ "libGLESv2",
+ "libgui",
+ "liblog",
+ "libnativewindow",
+ "libui",
+ "libutils",
+ ],
+}
diff --git a/services/surfaceflinger/RenderEngine/tests/RenderEngineTest.cpp b/services/surfaceflinger/RenderEngine/tests/RenderEngineTest.cpp
new file mode 100644
index 0000000..345c7ea
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/tests/RenderEngineTest.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <renderengine/RenderEngine.h>
+#include <ui/PixelFormat.h>
+
+namespace android {
+
+class RenderEngineTest : public ::testing::Test {
+public:
+ RenderEngineTest() {
+ // Initialize with some sane defaults.
+ // TODO(alecmouri): This should probably be the same instance used by
+ // SurfaceFlinger eventually.
+ mRE = renderengine::RenderEngine::create(static_cast<int32_t>(ui::PixelFormat::RGBA_8888),
+ 0);
+ }
+
+ status_t drawEmptyLayers() {
+ renderengine::DisplaySettings settings;
+ std::vector<renderengine::LayerSettings> layers;
+ // Meaningless buffer since we don't do any drawing
+ sp<GraphicBuffer> buffer = new GraphicBuffer();
+ base::unique_fd fence;
+ return mRE->drawLayers(settings, layers, buffer->getNativeBuffer(), &fence);
+ }
+
+private:
+ std::unique_ptr<renderengine::RenderEngine> mRE;
+};
+
+TEST_F(RenderEngineTest, drawLayers_noLayersToDraw_works) {
+ status_t result = drawEmptyLayers();
+ ASSERT_EQ(NO_ERROR, result);
+}
+
+} // namespace android