Merge changes from topic "sfinput3"
* changes:
InputFlinger: Receive setInputWindows over IPC
InputDispatcher: Look up channel by token.
InputDispatcher: Track InputChannels by IBinder token.
Add setInputWindowInfo to SurfaceComposerClient::Transaction
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index d6ca0bf..4459cef 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -97,6 +97,14 @@
chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_grow/enable
chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_heap_shrink/enable
chmod 0666 /sys/kernel/tracing/events/kmem/ion_heap_shrink/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/signal/signal_generate/enable
+ chmod 0666 /sys/kernel/tracing/events/signal/signal_generate/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/signal/signal_deliver/enable
+ chmod 0666 /sys/kernel/tracing/events/signal/signal_deliver/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/mm_event/mm_event_record/enable
+ chmod 0666 /sys/kernel/tracing/events/mm_event/mm_event_record/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/lowmemory_kill/enable
+ chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/lowmemory_kill/enable
# disk
chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
diff --git a/cmds/dumpstate/DumpstateUtil.cpp b/cmds/dumpstate/DumpstateUtil.cpp
index 600a500..97c8ae2 100644
--- a/cmds/dumpstate/DumpstateUtil.cpp
+++ b/cmds/dumpstate/DumpstateUtil.cpp
@@ -101,13 +101,16 @@
}
CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::AsRoot() {
- values.account_mode_ = SU_ROOT;
+ if (!PropertiesHelper::IsUnroot()) {
+ values.account_mode_ = SU_ROOT;
+ }
return *this;
}
CommandOptions::CommandOptionsBuilder& CommandOptions::CommandOptionsBuilder::AsRootIfAvailable() {
- if (!PropertiesHelper::IsUserBuild())
- values.account_mode_ = SU_ROOT;
+ if (!PropertiesHelper::IsUserBuild()) {
+ return AsRoot();
+ }
return *this;
}
@@ -176,6 +179,7 @@
std::string PropertiesHelper::build_type_ = "";
int PropertiesHelper::dry_run_ = -1;
+int PropertiesHelper::unroot_ = -1;
bool PropertiesHelper::IsUserBuild() {
if (build_type_.empty()) {
@@ -191,6 +195,13 @@
return dry_run_ == 1;
}
+bool PropertiesHelper::IsUnroot() {
+ if (unroot_ == -1) {
+ unroot_ = android::base::GetBoolProperty("dumpstate.unroot", false) ? 1 : 0;
+ }
+ return unroot_ == 1;
+}
+
int DumpFileToFd(int out_fd, const std::string& title, const std::string& path) {
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
if (fd.get() < 0) {
diff --git a/cmds/dumpstate/DumpstateUtil.h b/cmds/dumpstate/DumpstateUtil.h
index 8342099..d69ffbf 100644
--- a/cmds/dumpstate/DumpstateUtil.h
+++ b/cmds/dumpstate/DumpstateUtil.h
@@ -97,9 +97,16 @@
public:
/* Sets the command to always run, even on `dry-run` mode. */
CommandOptionsBuilder& Always();
- /* Sets the command's PrivilegeMode as `SU_ROOT` */
+ /*
+ * Sets the command's PrivilegeMode as `SU_ROOT` unless overridden by system property
+ * 'dumpstate.unroot'.
+ */
CommandOptionsBuilder& AsRoot();
- /* If !IsUserBuild(), sets the command's PrivilegeMode as `SU_ROOT` */
+ /*
+ * Runs AsRoot() on userdebug builds. No-op on user builds since 'su' is
+ * not available. This is used for commands that return some useful information even
+ * when run as shell.
+ */
CommandOptionsBuilder& AsRootIfAvailable();
/* Sets the command's PrivilegeMode as `DROP_ROOT` */
CommandOptionsBuilder& DropRoot();
@@ -162,9 +169,17 @@
*/
static bool IsDryRun();
+ /**
+ * Checks whether root availability should be overridden.
+ *
+ * Useful to verify how dumpstate would work in a device with an user build.
+ */
+ static bool IsUnroot();
+
private:
static std::string build_type_;
static int dry_run_;
+ static int unroot_;
};
/*
diff --git a/cmds/dumpstate/README.md b/cmds/dumpstate/README.md
index 0302ea5..d5b2953 100644
--- a/cmds/dumpstate/README.md
+++ b/cmds/dumpstate/README.md
@@ -28,22 +28,22 @@
## To build, deploy, and run unit tests
-First create `/data/nativetest`:
+First create `/data/nativetest64`:
```
-adb shell mkdir /data/nativetest
+adb shell mkdir /data/nativetest64
```
Then run:
```
-mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest/dumpstate_test* /data/nativetest && adb shell /data/nativetest/dumpstate_test/dumpstate_test
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_test* /data/nativetest64 && adb shell /data/nativetest/dumpstate_test/dumpstate_test
```
And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`):
```
-mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest/dumpstate_test* /data/nativetest && adb shell /data/nativetest/dumpstate_test/dumpstate_test --gtest_filter=DumpstateTest.RunCommandNoArgs
+mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_test* /data/nativetest64 && adb shell /data/nativetest/dumpstate_test/dumpstate_test --gtest_filter=DumpstateTest.RunCommandNoArgs
```
## To take quick bugreports
@@ -52,6 +52,12 @@
adb shell setprop dumpstate.dry_run true
```
+## To emulate a device with user build
+
+```
+adb shell setprop dumpstate.unroot true
+```
+
## To change the `dumpstate` version
```
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 904c0e9..1a45436 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1977,7 +1977,8 @@
// Reset the property
android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
- options->extra_options = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
+ options->notification_description =
+ android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
if (!options->notification_description.empty()) {
// Reset the property
android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index b675c51..2cb9800 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -85,6 +85,10 @@
PropertiesHelper::build_type_ = build_type;
}
+ void SetUnroot(bool unroot) const {
+ PropertiesHelper::unroot_ = unroot;
+ }
+
bool IsStandalone() const {
return calls_ == 1;
}
@@ -650,6 +654,32 @@
EXPECT_THAT(err, StrEq("stderr\n"));
}
+TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
+ if (!IsStandalone()) {
+ // TODO: temporarily disabled because it might cause other tests to fail after dropping
+ // to Shell - need to refactor tests to avoid this problem)
+ MYLOGE(
+ "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
+ "on test suite\n")
+ return;
+ }
+ if (PropertiesHelper::IsUserBuild()) {
+ ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
+ return;
+ }
+
+ // Same test as above, but with unroot property set, which will override su availability.
+ SetUnroot(true);
+ DropRoot();
+
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
+ CommandOptions::WithTimeout(1).AsRoot().Build()));
+
+ // AsRoot is ineffective.
+ EXPECT_THAT(out, StrEq("2000\nstdout\n"));
+ EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
+}
+
TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
if (!IsStandalone()) {
// TODO: temporarily disabled because it might cause other tests to fail after dropping
@@ -692,6 +722,32 @@
EXPECT_THAT(err, StrEq("stderr\n"));
}
+TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
+ if (!IsStandalone()) {
+ // TODO: temporarily disabled because it might cause other tests to fail after dropping
+ // to Shell - need to refactor tests to avoid this problem)
+ MYLOGE(
+ "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
+ "on test suite\n")
+ return;
+ }
+ if (PropertiesHelper::IsUserBuild()) {
+ ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
+ return;
+ }
+ // Same test as above, but with unroot property set, which will override su availability.
+ SetUnroot(true);
+
+ DropRoot();
+
+ EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
+ CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
+
+ // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
+ EXPECT_THAT(out, StrEq("2000\nstdout\n"));
+ EXPECT_THAT(err, StrEq("stderr\n"));
+}
+
TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
EXPECT_THAT(out,
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index bc1a71c..532f7f1 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2245,8 +2245,30 @@
int32_t hasComm = readInt32();
int fd = readFileDescriptor();
if (hasComm != 0) {
- // skip
- readFileDescriptor();
+ // detach (owned by the binder driver)
+ int comm = readFileDescriptor();
+
+ // warning: this must be kept in sync with:
+ // frameworks/base/core/java/android/os/ParcelFileDescriptor.java
+ enum ParcelFileDescriptorStatus {
+ DETACHED = 2,
+ };
+
+#if BYTE_ORDER == BIG_ENDIAN
+ const int32_t message = ParcelFileDescriptorStatus::DETACHED;
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN
+ const int32_t message = __builtin_bswap32(ParcelFileDescriptorStatus::DETACHED);
+#endif
+
+ ssize_t written = TEMP_FAILURE_RETRY(
+ ::write(comm, &message, sizeof(message)));
+
+ if (written == -1 || written != sizeof(message)) {
+ ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s",
+ written, strerror(errno));
+ return BAD_TYPE;
+ }
}
return fd;
}
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index f3fb9c3..f9c8c8a 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -22,6 +22,7 @@
#include "status_internal.h"
#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
using DeathRecipient = ::android::IBinder::DeathRecipient;
@@ -346,6 +347,14 @@
return recipient->unlinkToDeath(binder, cookie);
}
+uid_t AIBinder_getCallingUid() {
+ return ::android::IPCThreadState::self()->getCallingUid();
+}
+
+pid_t AIBinder_getCallingPid() {
+ return ::android::IPCThreadState::self()->getCallingPid();
+}
+
void AIBinder_incStrong(AIBinder* binder) {
if (binder == nullptr) {
LOG(ERROR) << __func__ << ": on null binder";
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index d711ad8..9c6c55e 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -28,6 +28,7 @@
#include <stdint.h>
#include <sys/cdefs.h>
+#include <sys/types.h>
#include <android/binder_parcel.h>
#include <android/binder_status.h>
@@ -270,6 +271,31 @@
void* cookie) __INTRODUCED_IN(29);
/**
+ * This returns the calling UID assuming that this thread is called from a thread that is processing
+ * a binder transaction (for instance, in the implementation of AIBinder_Class_onTransact).
+ *
+ * This can be used with higher-level system services to determine the caller's identity and check
+ * permissions.
+ *
+ * \return calling uid or the current process's UID if this thread isn't processing a transaction.
+ */
+uid_t AIBinder_getCallingUid();
+
+/**
+ * This returns the calling PID assuming that this thread is called from a thread that is processing
+ * a binder transaction (for instance, in the implementation of AIBinder_Class_onTransact).
+ *
+ * This can be used with higher-level system services to determine the caller's identity and check
+ * permissions. However, when doing this, one should be aware of possible TOCTOU problems when the
+ * calling process dies and is replaced with another process with elevated permissions and the same
+ * PID.
+ *
+ * \return calling pid or the current process's PID if this thread isn't processing a transaction.
+ * If the transaction being processed is a oneway transaction, then this method will return 0.
+ */
+pid_t AIBinder_getCallingPid();
+
+/**
* This can only be called if a strong reference to this object already exists in process.
*
* \param binder the binder object to add a refcount to.
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d2c1a3d..7a75942 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -7,6 +7,8 @@
AIBinder_debugGetRefCount;
AIBinder_decStrong;
AIBinder_fromJavaBinder;
+ AIBinder_getCallingPid;
+ AIBinder_getCallingUid;
AIBinder_getClass;
AIBinder_getUserData;
AIBinder_incStrong;
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index beaf9ee..7efc8bd 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -50,6 +50,7 @@
"gl/GLExtensions.cpp",
"gl/GLFramebuffer.cpp",
"gl/GLImage.cpp",
+ "gl/GLSurface.cpp",
"gl/Program.cpp",
"gl/ProgramCache.cpp",
],
diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLES20RenderEngine.cpp
index d35762d..70a4322 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.cpp
+++ b/libs/renderengine/gl/GLES20RenderEngine.cpp
@@ -41,6 +41,7 @@
#include "GLExtensions.h"
#include "GLFramebuffer.h"
#include "GLImage.h"
+#include "GLSurface.h"
#include "Program.h"
#include "ProgramCache.h"
@@ -274,8 +275,6 @@
// now figure out what version of GL did we actually get
// NOTE: a dummy surface is not needed if KHR_create_context is supported
- // TODO(alecmouri): don't create this surface if EGL_KHR_surfaceless_context
- // is supported.
EGLConfig dummyConfig = config;
if (dummyConfig == EGL_NO_CONFIG) {
@@ -302,10 +301,10 @@
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
- engine = std::make_unique<GLES20RenderEngine>(featureFlags, display, config, ctxt,
- dummy);
+ engine = std::make_unique<GLES20RenderEngine>(featureFlags);
break;
}
+ engine->setEGLHandles(display, config, ctxt);
ALOGI("OpenGL ES informations:");
ALOGI("vendor : %s", extensions.getVendor());
@@ -315,6 +314,9 @@
ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
+ eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(display, dummy);
+
return engine;
}
@@ -357,13 +359,11 @@
return config;
}
-GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
- EGLContext ctxt, EGLSurface dummy)
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
: renderengine::impl::RenderEngine(featureFlags),
- mEGLDisplay(display),
- mEGLConfig(config),
- mEGLContext(ctxt),
- mDummySurface(dummy),
+ mEGLDisplay(EGL_NO_DISPLAY),
+ mEGLConfig(nullptr),
+ mEGLContext(EGL_NO_CONTEXT),
mVpWidth(0),
mVpHeight(0),
mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
@@ -422,6 +422,10 @@
return std::make_unique<GLFramebuffer>(*this);
}
+std::unique_ptr<Surface> GLES20RenderEngine::createSurface() {
+ return std::make_unique<GLSurface>(*this);
+}
+
std::unique_ptr<Image> GLES20RenderEngine::createImage() {
return std::make_unique<GLImage>(*this);
}
@@ -434,6 +438,31 @@
return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
}
+bool GLES20RenderEngine::setCurrentSurface(const Surface& surface) {
+ // Surface is an abstract interface. GLES20RenderEngine only ever
+ // creates GLSurface's, so it is safe to just cast to the actual
+ // type.
+ bool success = true;
+ const GLSurface& glSurface = static_cast<const GLSurface&>(surface);
+ EGLSurface eglSurface = glSurface.getEGLSurface();
+ if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
+ success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE;
+ if (success && glSurface.getAsync()) {
+ eglSwapInterval(mEGLDisplay, 0);
+ }
+ if (success) {
+ mSurfaceHeight = glSurface.getHeight();
+ }
+ }
+
+ return success;
+}
+
+void GLES20RenderEngine::resetCurrentSurface() {
+ eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ mSurfaceHeight = 0;
+}
+
base::unique_fd GLES20RenderEngine::flush() {
if (!GLExtensions::getInstance().hasNativeFenceSync()) {
return base::unique_fd();
@@ -547,7 +576,7 @@
void GLES20RenderEngine::setScissor(const Rect& region) {
// Invert y-coordinate to map to GL-space.
- int32_t canvasHeight = mFboHeight;
+ int32_t canvasHeight = mRenderToFbo ? mFboHeight : mSurfaceHeight;
int32_t glBottom = canvasHeight - region.bottom;
glScissor(region.left, glBottom, region.getWidth(), region.getHeight());
@@ -590,6 +619,7 @@
glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
+ mRenderToFbo = true;
mFboHeight = glFramebuffer->getBufferHeight();
uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -601,10 +631,17 @@
}
void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
+ mRenderToFbo = false;
mFboHeight = 0;
// back to main framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ // Workaround for b/77935566 to force the EGL driver to release the
+ // screenshot buffer
+ setScissor(Rect::EMPTY_RECT);
+ clearWithColor(0.0, 0.0, 0.0, 0.0);
+ disableScissor();
}
void GLES20RenderEngine::checkErrors() const {
@@ -629,7 +666,9 @@
int32_t r = sourceCrop.right;
int32_t b = sourceCrop.bottom;
int32_t t = sourceCrop.top;
- std::swap(t, b);
+ if (mRenderToFbo) {
+ std::swap(t, b);
+ }
mat4 m = mat4::ortho(l, r, b, t, 0, 1);
// Apply custom rotation to the projection.
@@ -935,6 +974,12 @@
return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
}
+void GLES20RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
+ mEGLDisplay = display;
+ mEGLConfig = config;
+ mEGLContext = ctxt;
+}
+
} // namespace gl
} // namespace renderengine
} // namespace android
diff --git a/libs/renderengine/gl/GLES20RenderEngine.h b/libs/renderengine/gl/GLES20RenderEngine.h
index 6c50938..148df2f 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.h
+++ b/libs/renderengine/gl/GLES20RenderEngine.h
@@ -40,21 +40,24 @@
namespace gl {
class GLImage;
+class GLSurface;
class GLES20RenderEngine : public impl::RenderEngine {
public:
static std::unique_ptr<GLES20RenderEngine> create(int hwcFormat, uint32_t featureFlags);
static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
- GLES20RenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
- EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
+ GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
~GLES20RenderEngine() override;
std::unique_ptr<Framebuffer> createFramebuffer() override;
+ std::unique_ptr<Surface> createSurface() override;
std::unique_ptr<Image> createImage() override;
void primeCache() const override;
bool isCurrent() const override;
+ bool setCurrentSurface(const Surface& surface) override;
+ void resetCurrentSurface() override;
base::unique_fd flush() override;
bool finish() override;
bool waitFence(base::unique_fd fenceFd) override;
@@ -117,12 +120,11 @@
// with PQ or HLG transfer function.
bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
bool needsXYZTransformMatrix() const;
- void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
+ void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
EGLDisplay mEGLDisplay;
EGLConfig mEGLConfig;
EGLContext mEGLContext;
- EGLSurface mDummySurface;
GLuint mProtectedTexName;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
@@ -143,6 +145,8 @@
mat4 mBt2020ToSrgb;
mat4 mBt2020ToDisplayP3;
+ bool mRenderToFbo = false;
+ int32_t mSurfaceHeight = 0;
int32_t mFboHeight = 0;
// Current dataspace of layer being rendered
diff --git a/libs/renderengine/gl/GLSurface.cpp b/libs/renderengine/gl/GLSurface.cpp
new file mode 100644
index 0000000..2d694e9
--- /dev/null
+++ b/libs/renderengine/gl/GLSurface.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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 "GLSurface.h"
+
+#include <android/native_window.h>
+#include <log/log.h>
+#include <ui/PixelFormat.h>
+#include "GLES20RenderEngine.h"
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+GLSurface::GLSurface(const GLES20RenderEngine& engine)
+ : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
+ // RE does not assume any config when EGL_KHR_no_config_context is supported
+ if (mEGLConfig == EGL_NO_CONFIG_KHR) {
+ mEGLConfig =
+ GLES20RenderEngine::chooseEglConfig(mEGLDisplay, PIXEL_FORMAT_RGBA_8888, false);
+ }
+}
+
+GLSurface::~GLSurface() {
+ setNativeWindow(nullptr);
+}
+
+void GLSurface::setNativeWindow(ANativeWindow* window) {
+ if (mEGLSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEGLDisplay, mEGLSurface);
+ mEGLSurface = EGL_NO_SURFACE;
+ mSurfaceWidth = 0;
+ mSurfaceHeight = 0;
+ }
+
+ mWindow = window;
+ if (mWindow) {
+ mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
+ mSurfaceWidth = ANativeWindow_getWidth(window);
+ mSurfaceHeight = ANativeWindow_getHeight(window);
+ }
+}
+
+void GLSurface::swapBuffers() const {
+ if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
+ EGLint error = eglGetError();
+
+ const char format[] = "eglSwapBuffers(%p, %p) failed with 0x%08x";
+ if (mCritical || error == EGL_CONTEXT_LOST) {
+ LOG_ALWAYS_FATAL(format, mEGLDisplay, mEGLSurface, error);
+ } else {
+ ALOGE(format, mEGLDisplay, mEGLSurface, error);
+ }
+ }
+}
+
+EGLint GLSurface::queryConfig(EGLint attrib) const {
+ EGLint value;
+ if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
+ value = 0;
+ }
+
+ return value;
+}
+
+int32_t GLSurface::queryRedSize() const {
+ return queryConfig(EGL_RED_SIZE);
+}
+
+int32_t GLSurface::queryGreenSize() const {
+ return queryConfig(EGL_GREEN_SIZE);
+}
+
+int32_t GLSurface::queryBlueSize() const {
+ return queryConfig(EGL_BLUE_SIZE);
+}
+
+int32_t GLSurface::queryAlphaSize() const {
+ return queryConfig(EGL_ALPHA_SIZE);
+}
+
+int32_t GLSurface::getWidth() const {
+ return mSurfaceWidth;
+}
+
+int32_t GLSurface::getHeight() const {
+ return mSurfaceHeight;
+}
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/gl/GLSurface.h b/libs/renderengine/gl/GLSurface.h
new file mode 100644
index 0000000..092d371
--- /dev/null
+++ b/libs/renderengine/gl/GLSurface.h
@@ -0,0 +1,76 @@
+/*
+ * 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 <cstdint>
+
+#include <EGL/egl.h>
+#include <android-base/macros.h>
+#include <renderengine/Surface.h>
+
+struct ANativeWindow;
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+class GLES20RenderEngine;
+
+class GLSurface final : public renderengine::Surface {
+public:
+ GLSurface(const GLES20RenderEngine& engine);
+ ~GLSurface() override;
+
+ // renderengine::Surface implementation
+ void setCritical(bool enable) override { mCritical = enable; }
+ void setAsync(bool enable) override { mAsync = enable; }
+
+ void setNativeWindow(ANativeWindow* window) override;
+ void swapBuffers() const override;
+
+ int32_t queryRedSize() const override;
+ int32_t queryGreenSize() const override;
+ int32_t queryBlueSize() const override;
+ int32_t queryAlphaSize() const override;
+
+ bool getAsync() const { return mAsync; }
+ EGLSurface getEGLSurface() const { return mEGLSurface; }
+
+ int32_t getWidth() const override;
+ int32_t getHeight() const override;
+
+private:
+ EGLint queryConfig(EGLint attrib) const;
+
+ EGLDisplay mEGLDisplay;
+ EGLConfig mEGLConfig;
+
+ bool mCritical = false;
+ bool mAsync = false;
+
+ int32_t mSurfaceWidth = 0;
+ int32_t mSurfaceHeight = 0;
+
+ ANativeWindow* mWindow = nullptr;
+ EGLSurface mEGLSurface = EGL_NO_SURFACE;
+
+ DISALLOW_COPY_AND_ASSIGN(GLSurface);
+};
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 22891c4..becb3c3 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -48,6 +48,7 @@
class BindNativeBufferAsFramebuffer;
class Image;
class Mesh;
+class Surface;
class Texture;
namespace impl {
@@ -71,6 +72,7 @@
// 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;
virtual void primeCache() const = 0;
@@ -82,6 +84,8 @@
virtual bool useWaitSync() const = 0;
virtual bool isCurrent() const = 0;
+ virtual bool setCurrentSurface(const Surface& surface) = 0;
+ virtual void resetCurrentSurface() = 0;
// helpers
// flush submits RenderEngine command stream for execution and returns a
diff --git a/libs/renderengine/include/renderengine/Surface.h b/libs/renderengine/include/renderengine/Surface.h
new file mode 100644
index 0000000..ba7331d
--- /dev/null
+++ b/libs/renderengine/include/renderengine/Surface.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 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 <cstdint>
+
+struct ANativeWindow;
+
+namespace android {
+namespace renderengine {
+
+class Surface {
+public:
+ virtual ~Surface() = default;
+
+ virtual void setCritical(bool enable) = 0;
+ virtual void setAsync(bool enable) = 0;
+
+ virtual void setNativeWindow(ANativeWindow* window) = 0;
+ virtual void swapBuffers() const = 0;
+
+ virtual int32_t queryRedSize() const = 0;
+ virtual int32_t queryGreenSize() const = 0;
+ virtual int32_t queryBlueSize() const = 0;
+ virtual int32_t queryAlphaSize() const = 0;
+
+ virtual int32_t getWidth() const = 0;
+ virtual int32_t getHeight() const = 0;
+};
+
+} // namespace renderengine
+} // namespace android
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 7ba2d94..0c9e04b 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -865,11 +865,11 @@
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 ", "
"policyFlags=0x%x, action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, "
- "metaState=0x%x, repeatCount=%d, downTime=%" PRId64 ", displayId=%" PRId32,
+ "metaState=0x%x, repeatCount=%d, downTime=%" PRId64,
prefix,
entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags,
entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
- entry->repeatCount, entry->downTime, entry->displayId);
+ entry->repeatCount, entry->downTime);
#endif
}
@@ -941,13 +941,13 @@
", policyFlags=0x%x, "
"action=0x%x, actionButton=0x%x, flags=0x%x, "
"metaState=0x%x, buttonState=0x%x,"
- "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64", displayId=%" PRId32,
+ "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
prefix,
entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags,
entry->action, entry->actionButton, entry->flags,
entry->metaState, entry->buttonState,
entry->edgeFlags, entry->xPrecision, entry->yPrecision,
- entry->downTime, entry->displayId);
+ entry->downTime);
for (uint32_t i = 0; i < entry->pointerCount; i++) {
ALOGD(" Pointer %d: id=%d, toolType=%d, "
@@ -2540,11 +2540,10 @@
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("notifyKey - eventTime=%" PRId64
", deviceId=%d, source=0x%x, displayId=%" PRId32 "policyFlags=0x%x, action=0x%x, "
- "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64
- ", displayId=%" PRId32,
+ "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64,
args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
args->action, args->flags, args->keyCode, args->scanCode,
- args->metaState, args->downTime, args->displayId);
+ args->metaState, args->downTime);
#endif
if (!validateKeyEvent(args->action)) {
return;
@@ -2619,10 +2618,10 @@
ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
", policyFlags=0x%x, "
"action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
- "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", displayId=%" PRId32
- , args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
+ "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
+ args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
- args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, args->displayId);
+ args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
for (uint32_t i = 0; i < args->pointerCount; i++) {
ALOGD(" Pointer %d: id=%d, toolType=%d, "
"x=%f, y=%f, pressure=%f, size=%f, "
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 9abb040..f168db9 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -184,7 +184,6 @@
"libhidltransport",
"liblayers_proto",
"liblog",
- "libsync",
"libtimestats_proto",
"libutils",
],
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index d16febf..5342bcf 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -35,8 +35,6 @@
#include <gui/Surface.h>
#include <hardware/gralloc.h>
#include <renderengine/RenderEngine.h>
-#include <sync/sync.h>
-#include <system/window.h>
#include <ui/DebugUtils.h>
#include <ui/DisplayInfo.h>
#include <ui/PixelFormat.h>
@@ -223,8 +221,8 @@
mDisplayToken(args.displayToken),
mId(args.displayId),
mNativeWindow(args.nativeWindow),
- mGraphicBuffer(nullptr),
mDisplaySurface(args.displaySurface),
+ mSurface{std::move(args.renderSurface)},
mDisplayInstallOrientation(args.displayInstallOrientation),
mPageFlipCount(0),
mIsVirtual(args.isVirtual),
@@ -246,6 +244,7 @@
ALOGE_IF(!mNativeWindow, "No native window was set for display");
ALOGE_IF(!mDisplaySurface, "No display surface was set for display");
+ ALOGE_IF(!mSurface, "No render surface was set for display");
std::vector<Hdr> types = args.hdrCapabilities.getSupportedHdrTypes();
for (Hdr hdrType : types) {
@@ -285,10 +284,6 @@
mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance);
ANativeWindow* const window = mNativeWindow.get();
-
- int status = native_window_api_connect(mNativeWindow.get(), NATIVE_WINDOW_API_EGL);
- ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status);
-
mDisplayWidth = ANativeWindow_getWidth(window);
mDisplayHeight = ANativeWindow_getHeight(window);
@@ -326,6 +321,7 @@
void DisplayDevice::flip() const
{
+ mFlinger->getRenderEngine().checkErrors();
mPageFlipCount++;
}
@@ -360,71 +356,9 @@
return mDisplaySurface->prepareFrame(compositionType);
}
-sp<GraphicBuffer> DisplayDevice::dequeueBuffer() {
- int fd;
- ANativeWindowBuffer* buffer;
-
- status_t res = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd);
-
- if (res != NO_ERROR) {
- ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d",
- getDisplayName().c_str(), res);
- // Return fast here as we can't do much more - any rendering we do
- // now will just be wrong.
- return mGraphicBuffer;
- }
-
- ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].",
- mGraphicBuffer->getNativeBuffer()->handle);
- mGraphicBuffer = GraphicBuffer::from(buffer);
-
- // Block until the buffer is ready
- // TODO(alecmouri): it's perhaps more appropriate to block renderengine so
- // that the gl driver can block instead.
- if (fd >= 0) {
- sync_wait(fd, -1);
- close(fd);
- }
-
- return mGraphicBuffer;
-}
-
-void DisplayDevice::queueBuffer(HWComposer& hwc) {
+void DisplayDevice::swapBuffers(HWComposer& hwc) const {
if (hwc.hasClientComposition(mId) || hwc.hasFlipClientTargetRequest(mId)) {
- // hasFlipClientTargetRequest could return true even if we haven't
- // dequeued a buffer before. Try dequeueing one if we don't have a
- // buffer ready.
- if (mGraphicBuffer == nullptr) {
- ALOGI("Attempting to queue a client composited buffer without one "
- "previously dequeued for display [%s]. Attempting to dequeue "
- "a scratch buffer now",
- mDisplayName.c_str());
- // We shouldn't deadlock here, since mGraphicBuffer == nullptr only
- // after a successful call to queueBuffer, or if dequeueBuffer has
- // never been called.
- dequeueBuffer();
- }
-
- if (mGraphicBuffer == nullptr) {
- ALOGE("No buffer is ready for display [%s]", mDisplayName.c_str());
- } else {
- int fd = mBufferReady.release();
-
- status_t res = mNativeWindow->queueBuffer(mNativeWindow.get(),
- mGraphicBuffer->getNativeBuffer(), fd);
- if (res != NO_ERROR) {
- ALOGE("Error when queueing buffer for display [%s]: %d", mDisplayName.c_str(), res);
- // We risk blocking on dequeueBuffer if the primary display failed
- // to queue up its buffer, so crash here.
- if (isPrimary()) {
- LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", res);
- } else {
- mNativeWindow->cancelBuffer(mNativeWindow.get(),
- mGraphicBuffer->getNativeBuffer(), fd);
- }
- }
- mGraphicBuffer = nullptr;
- }
+ mSurface->swapBuffers();
}
status_t result = mDisplaySurface->advanceFrame();
@@ -433,10 +367,16 @@
}
}
-void DisplayDevice::onPresentDisplayCompleted() {
+void DisplayDevice::onSwapBuffersCompleted() const {
mDisplaySurface->onFrameCommitted();
}
+bool DisplayDevice::makeCurrent() const {
+ bool success = mFlinger->getRenderEngine().setCurrentSurface(*mSurface);
+ setViewportAndProjection();
+ return success;
+}
+
void DisplayDevice::setViewportAndProjection() const {
size_t w = mDisplayWidth;
size_t h = mDisplayHeight;
@@ -444,13 +384,6 @@
mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, ui::Transform::ROT_0);
}
-void DisplayDevice::finishBuffer() {
- mBufferReady = mFlinger->getRenderEngine().flush();
- if (mBufferReady.get() < 0) {
- mFlinger->getRenderEngine().finish();
- }
-}
-
const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
return mDisplaySurface->getClientTargetAcquireFence();
}
@@ -599,8 +532,12 @@
void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
dirtyRegion.set(getBounds());
+ mSurface->setNativeWindow(nullptr);
+
mDisplaySurface->resizeBuffers(newWidth, newHeight);
+ ANativeWindow* const window = mNativeWindow.get();
+ mSurface->setNativeWindow(window);
mDisplayWidth = newWidth;
mDisplayHeight = newHeight;
}
@@ -716,11 +653,12 @@
ANativeWindow* const window = mNativeWindow.get();
result.appendFormat("+ %s\n", getDebugName().c_str());
result.appendFormat(" layerStack=%u, (%4dx%4d), ANativeWindow=%p "
- "format=%d, orient=%2d (type=%08x), flips=%u, isSecure=%d, "
- "powerMode=%d, activeConfig=%d, numLayers=%zu\n",
+ "(%d:%d:%d:%d), orient=%2d (type=%08x), "
+ "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
mLayerStack, mDisplayWidth, mDisplayHeight, window,
- ANativeWindow_getFormat(window), mOrientation, tr.getType(),
- getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+ mSurface->queryRedSize(), mSurface->queryGreenSize(),
+ mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation,
+ tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
mVisibleLayersSortedByZ.size());
result.appendFormat(" v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
"transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
@@ -731,9 +669,9 @@
auto const surface = static_cast<Surface*>(window);
ui::Dataspace dataspace = surface->getBuffersDataSpace();
result.appendFormat(" wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n",
- mHasWideColorGamut, mHasHdr10, decodeColorMode(mActiveColorMode).c_str(),
- dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(),
- dataspace);
+ mHasWideColorGamut, mHasHdr10,
+ decodeColorMode(mActiveColorMode).c_str(),
+ dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(), dataspace);
String8 surfaceDump;
mDisplaySurface->dumpAsString(surfaceDump);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index eb2c5c3..bcd3330 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -24,25 +24,25 @@
#include <string>
#include <unordered_map>
-#include <android/native_window.h>
#include <binder/IBinder.h>
#include <gui/LayerState.h>
#include <hardware/hwcomposer_defs.h>
#include <math/mat4.h>
-#include <renderengine/RenderEngine.h>
-#include <system/window.h>
+#include <renderengine/Surface.h>
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
#include <ui/Region.h>
#include <ui/Transform.h>
-#include <utils/Mutex.h>
#include <utils/RefBase.h>
+#include <utils/Mutex.h>
#include <utils/String8.h>
#include <utils/Timers.h>
#include "DisplayHardware/DisplayIdentification.h"
#include "RenderArea.h"
+struct ANativeWindow;
+
namespace android {
class DisplaySurface;
@@ -146,13 +146,10 @@
ui::Dataspace* outDataspace, ui::ColorMode* outMode,
ui::RenderIntent* outIntent) const;
- // Queues the drawn buffer for consumption by HWC.
- void queueBuffer(HWComposer& hwc);
- // Allocates a buffer as scratch space for GPU composition
- sp<GraphicBuffer> dequeueBuffer();
+ void swapBuffers(HWComposer& hwc) const;
// called after h/w composer has completed its set() call
- void onPresentDisplayCompleted();
+ void onSwapBuffersCompleted() const;
Rect getBounds() const {
return Rect(mDisplayWidth, mDisplayHeight);
@@ -162,11 +159,7 @@
void setDisplayName(const std::string& displayName);
const std::string& getDisplayName() const { return mDisplayName; }
- // Acquires a new buffer for GPU composition.
- void readyNewBuffer();
- // Marks the current buffer has finished, so that it can be presented and
- // swapped out.
- void finishBuffer();
+ bool makeCurrent() const;
void setViewportAndProjection() const;
const sp<Fence>& getClientTargetAcquireFence() const;
@@ -211,13 +204,9 @@
// ANativeWindow this display is rendering into
sp<ANativeWindow> mNativeWindow;
- // Current buffer that this display can render to.
- sp<GraphicBuffer> mGraphicBuffer;
sp<DisplaySurface> mDisplaySurface;
- // File descriptor indicating that mGraphicBuffer is ready for display, i.e.
- // that drawing to the buffer is now complete.
- base::unique_fd mBufferReady;
+ std::unique_ptr<renderengine::Surface> mSurface;
int mDisplayWidth;
int mDisplayHeight;
const int mDisplayInstallOrientation;
@@ -337,6 +326,7 @@
bool isSecure{false};
sp<ANativeWindow> nativeWindow;
sp<DisplaySurface> displaySurface;
+ std::unique_ptr<renderengine::Surface> renderSurface;
int displayInstallOrientation{DisplayState::eOrientationDefault};
bool hasWideColorGamut{false};
HdrCapabilities hdrCapabilities;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 5f3fcd6..27d3dc5 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -107,6 +107,8 @@
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
sink->setAsyncMode(true);
+ IGraphicBufferProducer::QueueBufferOutput output;
+ mSource[SOURCE_SCRATCH]->connect(nullptr, NATIVE_WINDOW_API_EGL, false, &output);
}
VirtualDisplaySurface::~VirtualDisplaySurface() {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e84e21a..35ba391 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -45,7 +45,6 @@
#include <gui/BufferQueue.h>
#include <gui/GuiConfig.h>
#include <gui/IDisplayEventConnection.h>
-#include <gui/IProducerListener.h>
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
#include <renderengine/RenderEngine.h>
@@ -677,6 +676,10 @@
LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()),
"Internal display is disconnected.");
+ // make the default display GLContext current so that we can create textures
+ // when creating Layers (which may happens before we render something)
+ display->makeCurrent();
+
if (useVrFlinger) {
auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
// This callback is called from the vr flinger dispatch thread. We
@@ -1406,6 +1409,7 @@
// mCurrentState and mDrawingState and re-apply all changes when we make the
// transition.
mDrawingState.displays.clear();
+ getRenderEngine().resetCurrentSurface();
mDisplays.clear();
}
@@ -1715,7 +1719,7 @@
auto& engine(getRenderEngine());
engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
- display->queueBuffer(getHwComposer());
+ display->swapBuffers(getHwComposer());
}
}
@@ -2190,7 +2194,8 @@
if (displayId) {
getHwComposer().presentAndGetReleaseFences(*displayId);
}
- display->onPresentDisplayCompleted();
+ display->onSwapBuffersCompleted();
+ display->makeCurrent();
for (auto& layer : display->getVisibleLayersSortedByZ()) {
sp<Fence> releaseFence = Fence::NO_FENCE;
@@ -2337,9 +2342,22 @@
auto nativeWindow = nativeWindowSurface->getNativeWindow();
creationArgs.nativeWindow = nativeWindow;
+ /*
+ * Create our display's surface
+ */
+ std::unique_ptr<renderengine::Surface> renderSurface = getRenderEngine().createSurface();
+ renderSurface->setCritical(isInternalDisplay);
+ renderSurface->setAsync(state.isVirtual());
+ renderSurface->setNativeWindow(nativeWindow.get());
+ creationArgs.renderSurface = std::move(renderSurface);
+
// Make sure that composition can never be stalled by a virtual display
// consumer that isn't processing buffers fast enough. We have to do this
- // here, in case the display is composed entirely by HWC.
+ // in two places:
+ // * Here, in case the display is composed entirely by HWC.
+ // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
+ // window's swap interval in eglMakeCurrent, so they'll override the
+ // interval we set here.
if (state.isVirtual()) {
nativeWindow->setSwapInterval(nativeWindow.get(), 0);
}
@@ -2399,6 +2417,12 @@
const auto externalDisplayId = getExternalDisplayId();
// in drawing state but not in current state
+ // Call makeCurrent() on the primary display so we can
+ // be sure that nothing associated with this display
+ // is current.
+ if (const auto defaultDisplay = getDefaultDisplayDeviceLocked()) {
+ defaultDisplay->makeCurrent();
+ }
if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) {
display->disconnect(getHwComposer());
}
@@ -2949,7 +2973,7 @@
mGeometryInvalid = true;
}
-void SurfaceFlinger::doDisplayComposition(const sp<DisplayDevice>& display,
+void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& display,
const Region& inDirtyRegion) {
// We only need to actually compose the display if:
// 1) It is being handled by hardware composer, which may need this to
@@ -2964,10 +2988,10 @@
if (!doComposeSurfaces(display)) return;
// swap buffers (presentation)
- display->queueBuffer(getHwComposer());
+ display->swapBuffers(getHwComposer());
}
-bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& display) {
+bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& display) {
ALOGV("doComposeSurfaces");
const Region bounds(display->bounds());
@@ -2980,31 +3004,9 @@
bool applyColorMatrix = false;
bool needsEnhancedColorMatrix = false;
- // Framebuffer will live in this scope for GPU composition.
- std::unique_ptr<renderengine::BindNativeBufferAsFramebuffer> fbo;
-
if (hasClientComposition) {
ALOGV("hasClientComposition");
- sp<GraphicBuffer> buf = display->dequeueBuffer();
-
- if (buf == nullptr) {
- ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
- "client composition for this frame",
- display->getDisplayName().c_str());
- return false;
- }
-
- // Bind the framebuffer in this scope.
- fbo = std::make_unique<renderengine::BindNativeBufferAsFramebuffer>(getRenderEngine(),
- buf->getNativeBuffer());
-
- if (fbo->getStatus() != NO_ERROR) {
- ALOGW("Binding buffer for display [%s] failed with status: %d",
- display->getDisplayName().c_str(), fbo->getStatus());
- return false;
- }
-
Dataspace outputDataspace = Dataspace::UNKNOWN;
if (display->hasWideColorGamut()) {
outputDataspace = display->getCompositionDataSpace();
@@ -3033,7 +3035,18 @@
colorMatrix *= mEnhancedSaturationMatrix;
}
- display->setViewportAndProjection();
+ if (!display->makeCurrent()) {
+ ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
+ display->getDisplayName().c_str());
+ getRenderEngine().resetCurrentSurface();
+
+ // |mStateLock| not needed as we are on the main thread
+ const auto defaultDisplay = getDefaultDisplayDeviceLocked();
+ if (!defaultDisplay || !defaultDisplay->makeCurrent()) {
+ ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
+ }
+ return false;
+ }
// Never touch the framebuffer if we don't have any framebuffer layers
if (hasDeviceComposition) {
@@ -3126,15 +3139,11 @@
firstLayer = false;
}
- // Perform some cleanup steps if we used client composition.
- if (hasClientComposition) {
- getRenderEngine().setColorTransform(mat4());
- getBE().mRenderEngine->disableScissor();
- display->finishBuffer();
- // Clear out error flags here so that we don't wait until next
- // composition to log.
- getRenderEngine().checkErrors();
- }
+ // Clear color transform matrix at the end of the frame.
+ getRenderEngine().setColorTransform(mat4());
+
+ // disable scissor at the end of the frame
+ getBE().mRenderEngine->disableScissor();
return true;
}
@@ -3184,19 +3193,15 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
+status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
Mutex::Autolock _l(mStateLock);
- return removeLayerLocked(mStateLock, layer, topLevelOnly);
+ return removeLayerLocked(mStateLock, layer);
}
-status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer,
- bool topLevelOnly) {
+status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer) {
const auto& p = layer->getParent();
ssize_t index;
if (p != nullptr) {
- if (topLevelOnly) {
- return NO_ERROR;
- }
index = p->removeChild(layer);
} else {
index = mCurrentState.layersSortedByZ.remove(layer);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f5218b1..8b389bc 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -592,8 +592,8 @@
void onHandleDestroyed(const sp<Layer>& layer);
// remove a layer from SurfaceFlinger immediately
- status_t removeLayer(const sp<Layer>& layer, bool topLevelOnly = false);
- status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer, bool topLevelOnly = false);
+ status_t removeLayer(const sp<Layer>& layer);
+ status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer);
// add a layer to SurfaceFlinger
status_t addClientLayer(const sp<Client>& client,
@@ -721,10 +721,10 @@
void doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything);
void doTracing(const char* where);
void logLayerStats();
- void doDisplayComposition(const sp<DisplayDevice>& display, const Region& dirtyRegion);
+ void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion);
// This fails if using GL and the surface has been destroyed.
- bool doComposeSurfaces(const sp<DisplayDevice>& display);
+ bool doComposeSurfaces(const sp<const DisplayDevice>& display);
void postFramebuffer(const sp<DisplayDevice>& display);
void postFrame();
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index cfaf495..ab1b252 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -46,7 +46,6 @@
using testing::AtLeast;
using testing::ByMove;
using testing::DoAll;
-using testing::Invoke;
using testing::IsNull;
using testing::Mock;
using testing::NotNull;
@@ -94,10 +93,6 @@
EXPECT_CALL(*mPrimaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0));
EXPECT_CALL(*mPrimaryDispSync, getPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
- EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
- EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0)));
mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
setupComposer(0);
@@ -144,11 +139,9 @@
sp<DisplayDevice> mDisplay;
sp<DisplayDevice> mExternalDisplay;
sp<mock::DisplaySurface> mDisplaySurface = new mock::DisplaySurface();
+ renderengine::mock::Surface* mRenderSurface = new renderengine::mock::Surface();
mock::NativeWindow* mNativeWindow = new mock::NativeWindow();
- sp<GraphicBuffer> mBuffer = new GraphicBuffer();
- ANativeWindowBuffer* mNativeWindowBuffer = mBuffer->getNativeBuffer();
-
mock::EventThread* mEventThread = new mock::EventThread();
mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
@@ -249,6 +242,8 @@
test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, DEFAULT_DISPLAY_ID,
false /* isVirtual */, true /* isPrimary */)
.setDisplaySurface(test->mDisplaySurface)
+ .setRenderSurface(std::unique_ptr<renderengine::Surface>(
+ test->mRenderSurface))
.setNativeWindow(test->mNativeWindow)
.setSecure(Derived::IS_SECURE)
.setPowerMode(Derived::INIT_POWER_MODE)
@@ -271,9 +266,13 @@
EXPECT_CALL(*test->mRenderEngine, checkErrors()).WillRepeatedly(Return());
EXPECT_CALL(*test->mRenderEngine, isCurrent()).WillRepeatedly(Return(true));
- EXPECT_CALL(*test->mRenderEngine, flush()).WillRepeatedly(Invoke([]() {
- return base::unique_fd(0);
- }));
+ EXPECT_CALL(*test->mRenderEngine, setCurrentSurface(Ref(*test->mRenderSurface)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*test->mRenderEngine,
+ setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
+ Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ ui::Transform::ROT_0))
+ .Times(1);
EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1);
EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1);
@@ -324,6 +323,8 @@
static void setupHwcCompositionCallExpectations(CompositionTest* test) {
EXPECT_CALL(*test->mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC)).Times(1);
+
+ EXPECT_CALL(*test->mRenderEngine, disableScissor()).Times(1);
}
static void setupRECompositionCallExpectations(CompositionTest* test) {
@@ -343,18 +344,12 @@
setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
ui::Transform::ROT_0))
- .Times(1);
- EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull())).WillOnce(Return(true));
- EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull())).WillOnce(Return(true));
- EXPECT_CALL(*test->mRenderEngine, createFramebuffer())
- .WillOnce(Return(
- ByMove(std::unique_ptr<renderengine::Framebuffer>(test->mReFrameBuffer))));
- EXPECT_CALL(*test->mRenderEngine, bindFrameBuffer(test->mReFrameBuffer)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, unbindFrameBuffer(test->mReFrameBuffer)).Times(1);
- EXPECT_CALL(*test->mNativeWindow, queueBuffer(_, _)).WillOnce(Return(0));
- EXPECT_CALL(*test->mNativeWindow, dequeueBuffer(_, _))
- .WillOnce(DoAll(SetArgPointee<0>(test->mNativeWindowBuffer), SetArgPointee<1>(-1),
- Return(0)));
+ .Times(1)
+ .RetiresOnSaturation();
+ EXPECT_CALL(*test->mRenderEngine, setCurrentSurface(Ref(*test->mRenderSurface)))
+ .WillOnce(Return(true))
+ .RetiresOnSaturation();
+ EXPECT_CALL(*test->mRenderSurface, swapBuffers()).Times(1);
}
template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index ac6a78b..32fce67 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -120,7 +120,6 @@
mock::EventThread* mEventThread = new mock::EventThread();
mock::EventControlThread* mEventControlThread = new mock::EventControlThread();
sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow();
- sp<GraphicBuffer> mBuffer = new GraphicBuffer();
// These mocks are created by the test, but are destroyed by SurfaceFlinger
// by virtue of being stored into a std::unique_ptr. However we still need
@@ -135,6 +134,7 @@
sp<mock::GraphicBufferConsumer> mConsumer;
sp<mock::GraphicBufferProducer> mProducer;
surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
+ renderengine::mock::Surface* mRenderSurface = nullptr;
};
DisplayTransactionTest::DisplayTransactionTest() {
@@ -340,11 +340,26 @@
static void setupNativeWindowSurfaceCreationCallExpectations(DisplayTransactionTest* test) {
EXPECT_CALL(*test->mNativeWindowSurface, getNativeWindow())
.WillOnce(Return(test->mNativeWindow));
+ EXPECT_CALL(*test->mNativeWindow, perform(19)).WillRepeatedly(Return(NO_ERROR));
+ // For simplicity, we only expect to create a single render surface for
+ // each test.
+ ASSERT_TRUE(test->mRenderSurface == nullptr);
+ test->mRenderSurface = new renderengine::mock::Surface();
+ EXPECT_CALL(*test->mRenderEngine, createSurface())
+ .WillOnce(Return(ByMove(
+ std::unique_ptr<renderengine::Surface>(test->mRenderSurface))));
+
+ // Creating a DisplayDevice requires getting default dimensions from the
+ // native window.
EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
.WillRepeatedly(DoAll(SetArgPointee<1>(WIDTH), Return(0)));
EXPECT_CALL(*test->mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
.WillRepeatedly(DoAll(SetArgPointee<1>(HEIGHT), Return(0)));
+
+ EXPECT_CALL(*test->mRenderSurface, setAsync(static_cast<bool>(ASYNC))).Times(1);
+ EXPECT_CALL(*test->mRenderSurface, setCritical(static_cast<bool>(CRITICAL))).Times(1);
+ EXPECT_CALL(*test->mRenderSurface, setNativeWindow(test->mNativeWindow.get())).Times(1);
}
static void setupFramebufferConsumerBufferQueueCallExpectations(DisplayTransactionTest* test) {
@@ -1055,6 +1070,9 @@
// The call disable vsyncs
EXPECT_CALL(*mEventControlThread, setVsyncEnabled(false)).Times(1);
+ // The call clears the current render engine surface
+ EXPECT_CALL(*mRenderEngine, resetCurrentSurface());
+
// The call ends any display resyncs
EXPECT_CALL(*mPrimaryDispSync, endResync()).Times(1);
@@ -1114,7 +1132,6 @@
.WillRepeatedly(DoAll(SetArgPointee<1>(1080 /* arbitrary */), Return(0)));
EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
.WillRepeatedly(DoAll(SetArgPointee<1>(1920 /* arbitrary */), Return(0)));
- EXPECT_CALL(*mNativeWindow, perform(13)).Times(1);
auto displayDevice = mInjector.inject();
displayDevice->getBestColorMode(mInputDataspace, mInputRenderIntent, &mOutDataspace,
@@ -1708,6 +1725,7 @@
EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
+ EXPECT_CALL(*mProducer, connect(_, _, _, _)).Times(1);
EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
@@ -1931,16 +1949,11 @@
// A display is set up
auto nativeWindow = new mock::NativeWindow();
auto displaySurface = new mock::DisplaySurface();
- sp<GraphicBuffer> buf = new GraphicBuffer();
+ auto renderSurface = new renderengine::mock::Surface();
auto display = Case::Display::makeFakeExistingDisplayInjector(this);
display.setNativeWindow(nativeWindow);
display.setDisplaySurface(displaySurface);
- // Setup injection expections
- EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
- .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
- EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
- .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
- EXPECT_CALL(*nativeWindow, perform(13)).Times(1);
+ display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
display.inject();
// There is a change to the viewport state
@@ -1952,7 +1965,9 @@
// --------------------------------------------------------------------
// Call Expectations
+ EXPECT_CALL(*renderSurface, setNativeWindow(nullptr)).Times(1);
EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
+ EXPECT_CALL(*renderSurface, setNativeWindow(nativeWindow)).Times(1);
// --------------------------------------------------------------------
// Invocation
@@ -1973,16 +1988,11 @@
// A display is set up
auto nativeWindow = new mock::NativeWindow();
auto displaySurface = new mock::DisplaySurface();
- sp<GraphicBuffer> buf = new GraphicBuffer();
+ auto renderSurface = new renderengine::mock::Surface();
auto display = Case::Display::makeFakeExistingDisplayInjector(this);
display.setNativeWindow(nativeWindow);
display.setDisplaySurface(displaySurface);
- // Setup injection expections
- EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_WIDTH, _))
- .WillOnce(DoAll(SetArgPointee<1>(oldWidth), Return(0)));
- EXPECT_CALL(*nativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
- .WillOnce(DoAll(SetArgPointee<1>(oldHeight), Return(0)));
- EXPECT_CALL(*nativeWindow, perform(13)).Times(1);
+ display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
display.inject();
// There is a change to the viewport state
@@ -1994,7 +2004,9 @@
// --------------------------------------------------------------------
// Call Expectations
+ EXPECT_CALL(*renderSurface, setNativeWindow(nullptr)).Times(1);
EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
+ EXPECT_CALL(*renderSurface, setNativeWindow(nativeWindow)).Times(1);
// --------------------------------------------------------------------
// Invocation
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 85c835e..a519f1f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -474,6 +474,11 @@
return *this;
}
+ auto& setRenderSurface(std::unique_ptr<renderengine::Surface> renderSurface) {
+ mCreationArgs.renderSurface = std::move(renderSurface);
+ return *this;
+ }
+
auto& setSecure(bool secure) {
mCreationArgs.isSecure = secure;
return *this;
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
index fbfbc3f..af54df6 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
@@ -26,6 +26,9 @@
RenderEngine::RenderEngine() = default;
RenderEngine::~RenderEngine() = default;
+Surface::Surface() = default;
+Surface::~Surface() = default;
+
Image::Image() = default;
Image::~Image() = default;
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 90c3c20..afca63a 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -23,6 +23,7 @@
#include <renderengine/LayerSettings.h>
#include <renderengine/Mesh.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/Surface.h>
#include <renderengine/Texture.h>
#include <ui/GraphicBuffer.h>
@@ -36,12 +37,15 @@
~RenderEngine() override;
MOCK_METHOD0(createFramebuffer, std::unique_ptr<Framebuffer>());
+ MOCK_METHOD0(createSurface, std::unique_ptr<renderengine::Surface>());
MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
MOCK_CONST_METHOD0(primeCache, void());
MOCK_METHOD1(dump, void(String8&));
MOCK_CONST_METHOD0(useNativeFenceSync, bool());
MOCK_CONST_METHOD0(useWaitSync, bool());
MOCK_CONST_METHOD0(isCurrent, bool());
+ MOCK_METHOD1(setCurrentSurface, bool(const renderengine::Surface&));
+ MOCK_METHOD0(resetCurrentSurface, void());
MOCK_METHOD0(flush, base::unique_fd());
MOCK_METHOD0(finish, bool());
MOCK_METHOD1(waitFence, bool(base::unique_fd*));
@@ -78,6 +82,23 @@
ANativeWindowBuffer* const, base::unique_fd*));
};
+class Surface : public renderengine::Surface {
+public:
+ Surface();
+ ~Surface() override;
+
+ MOCK_METHOD1(setCritical, void(bool));
+ MOCK_METHOD1(setAsync, void(bool));
+ MOCK_METHOD1(setNativeWindow, void(ANativeWindow*));
+ MOCK_CONST_METHOD0(swapBuffers, void());
+ MOCK_CONST_METHOD0(queryRedSize, int32_t());
+ MOCK_CONST_METHOD0(queryGreenSize, int32_t());
+ MOCK_CONST_METHOD0(queryBlueSize, int32_t());
+ MOCK_CONST_METHOD0(queryAlphaSize, int32_t());
+ MOCK_CONST_METHOD0(getWidth, int32_t());
+ MOCK_CONST_METHOD0(getHeight, int32_t());
+};
+
class Image : public renderengine::Image {
public:
Image();
diff --git a/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h b/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
index 4950a4b..561fd58 100644
--- a/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
+++ b/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
@@ -36,7 +36,6 @@
MOCK_METHOD1(queueBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
MOCK_CONST_METHOD2(query, int(int, int*));
MOCK_METHOD1(perform, int(int));
- MOCK_METHOD2(perform, int(int, int));
MOCK_METHOD1(cancelBuffer_DEPRECATED, int(struct ANativeWindowBuffer*));
MOCK_METHOD2(dequeueBuffer, int(struct ANativeWindowBuffer**, int*));
MOCK_METHOD2(queueBuffer, int(struct ANativeWindowBuffer*, int));