Bind to FBO when using GPU composition
We'll manage the ANativeWindow directly to pull buffers for drawing.
Some additional minor changes have snuck in to clean up unnecessary GL
calls. Checking simpleperf there is now 0 GL overhead during HWC
composed frames.
Bug: 117680609
Change-Id: If639ce2c6cd600eabb957d278815f80b413d92b3
Test: libsurfaceflinger_unittest, SurfaceFlinger_test, go/wm-smoke
Test: Android Auto works in my car
Test: Manual inspection of simulated virtual displays
diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLES20RenderEngine.cpp
index 70a4322..e244a83 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.cpp
+++ b/libs/renderengine/gl/GLES20RenderEngine.cpp
@@ -275,6 +275,8 @@
// 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) {
@@ -301,10 +303,10 @@
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
- engine = std::make_unique<GLES20RenderEngine>(featureFlags);
+ engine = std::make_unique<GLES20RenderEngine>(featureFlags, display, config, ctxt,
+ dummy);
break;
}
- engine->setEGLHandles(display, config, ctxt);
ALOGI("OpenGL ES informations:");
ALOGI("vendor : %s", extensions.getVendor());
@@ -314,9 +316,6 @@
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;
}
@@ -359,11 +358,13 @@
return config;
}
-GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
+GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
+ EGLContext ctxt, EGLSurface dummy)
: renderengine::impl::RenderEngine(featureFlags),
- mEGLDisplay(EGL_NO_DISPLAY),
- mEGLConfig(nullptr),
- mEGLContext(EGL_NO_CONTEXT),
+ mEGLDisplay(display),
+ mEGLConfig(config),
+ mEGLContext(ctxt),
+ mDummySurface(dummy),
mVpWidth(0),
mVpHeight(0),
mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
@@ -636,12 +637,6 @@
// 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 {
@@ -974,12 +969,6 @@
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 148df2f..aebb319 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.h
+++ b/libs/renderengine/gl/GLES20RenderEngine.h
@@ -47,7 +47,8 @@
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
+ GLES20RenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
+ EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
~GLES20RenderEngine() override;
std::unique_ptr<Framebuffer> createFramebuffer() override;
@@ -120,11 +121,12 @@
// with PQ or HLG transfer function.
bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
bool needsXYZTransformMatrix() const;
- void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
+ void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
EGLDisplay mEGLDisplay;
EGLConfig mEGLConfig;
EGLContext mEGLContext;
+ EGLSurface mDummySurface;
GLuint mProtectedTexName;
GLint mMaxViewportDims[2];
GLint mMaxTextureSize;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index e8092a9..9bd07d2 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -183,6 +183,7 @@
"libhidltransport",
"liblayers_proto",
"liblog",
+ "libsync",
"libtimestats_proto",
"libutils",
],
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index be19b9f..ac51d53 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -35,6 +35,8 @@
#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>
@@ -221,6 +223,7 @@
mDisplayToken(args.displayToken),
mId(args.displayId),
mNativeWindow(args.nativeWindow),
+ mGraphicBuffer(nullptr),
mDisplaySurface(args.displaySurface),
mSurface{std::move(args.renderSurface)},
mDisplayInstallOrientation(args.displayInstallOrientation),
@@ -284,6 +287,10 @@
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);
@@ -321,7 +328,6 @@
void DisplayDevice::flip() const
{
- mFlinger->getRenderEngine().checkErrors();
mPageFlipCount++;
}
@@ -356,9 +362,71 @@
return mDisplaySurface->prepareFrame(compositionType);
}
-void DisplayDevice::swapBuffers(HWComposer& hwc) const {
+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) {
if (hwc.hasClientComposition(mId) || hwc.hasFlipClientTargetRequest(mId)) {
- mSurface->swapBuffers();
+ // 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;
+ }
}
status_t result = mDisplaySurface->advanceFrame();
@@ -367,7 +435,7 @@
}
}
-void DisplayDevice::onSwapBuffersCompleted() const {
+void DisplayDevice::onPresentDisplayCompleted() {
mDisplaySurface->onFrameCommitted();
}
@@ -384,6 +452,13 @@
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();
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index bcd3330..560a958 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -28,13 +28,14 @@
#include <gui/LayerState.h>
#include <hardware/hwcomposer_defs.h>
#include <math/mat4.h>
+#include <renderengine/RenderEngine.h>
#include <renderengine/Surface.h>
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
#include <ui/Region.h>
#include <ui/Transform.h>
-#include <utils/RefBase.h>
#include <utils/Mutex.h>
+#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/Timers.h>
@@ -146,10 +147,13 @@
ui::Dataspace* outDataspace, ui::ColorMode* outMode,
ui::RenderIntent* outIntent) const;
- void swapBuffers(HWComposer& hwc) 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();
// called after h/w composer has completed its set() call
- void onSwapBuffersCompleted() const;
+ void onPresentDisplayCompleted();
Rect getBounds() const {
return Rect(mDisplayWidth, mDisplayHeight);
@@ -160,6 +164,11 @@
const std::string& getDisplayName() const { return mDisplayName; }
bool makeCurrent() const;
+ // 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();
void setViewportAndProjection() const;
const sp<Fence>& getClientTargetAcquireFence() const;
@@ -204,7 +213,12 @@
// 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;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 27d3dc5..5f3fcd6 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -107,8 +107,6 @@
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 9d16958..2858b7b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -45,6 +45,7 @@
#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>
@@ -676,10 +677,6 @@
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
@@ -1405,7 +1402,6 @@
// mCurrentState and mDrawingState and re-apply all changes when we make the
// transition.
mDrawingState.displays.clear();
- getRenderEngine().resetCurrentSurface();
mDisplays.clear();
}
@@ -1715,7 +1711,7 @@
auto& engine(getRenderEngine());
engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
- display->swapBuffers(getHwComposer());
+ display->queueBuffer(getHwComposer());
}
}
@@ -2187,8 +2183,7 @@
if (displayId) {
getHwComposer().presentAndGetReleaseFences(*displayId);
}
- display->onSwapBuffersCompleted();
- display->makeCurrent();
+ display->onPresentDisplayCompleted();
for (auto& layer : display->getVisibleLayersSortedByZ()) {
sp<Fence> releaseFence = Fence::NO_FENCE;
@@ -2341,16 +2336,11 @@
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
- // 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.
+ // here, in case the display is composed entirely by HWC.
if (state.isVirtual()) {
nativeWindow->setSwapInterval(nativeWindow.get(), 0);
}
@@ -2410,12 +2400,6 @@
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());
}
@@ -2962,7 +2946,7 @@
mGeometryInvalid = true;
}
-void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& display,
+void SurfaceFlinger::doDisplayComposition(const sp<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
@@ -2978,10 +2962,10 @@
if (!doComposeSurfaces(display)) return;
// swap buffers (presentation)
- display->swapBuffers(getHwComposer());
+ display->queueBuffer(getHwComposer());
}
-bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& display) {
+bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& display) {
ALOGV("doComposeSurfaces");
const Region bounds(display->bounds());
@@ -2994,9 +2978,31 @@
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();
@@ -3025,18 +3031,7 @@
colorMatrix *= mEnhancedSaturationMatrix;
}
- 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;
- }
+ display->setViewportAndProjection();
// Never touch the framebuffer if we don't have any framebuffer layers
if (hasDeviceComposition) {
@@ -3129,11 +3124,15 @@
firstLayer = false;
}
- // Clear color transform matrix at the end of the frame.
- getRenderEngine().setColorTransform(mat4());
-
- // disable scissor at the end of the frame
- getBE().mRenderEngine->disableScissor();
+ // 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();
+ }
return true;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e449e20..ca40913 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -716,10 +716,10 @@
void doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything);
void doTracing(const char* where);
void logLayerStats();
- void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion);
+ void doDisplayComposition(const sp<DisplayDevice>& display, const Region& dirtyRegion);
// This fails if using GL and the surface has been destroyed.
- bool doComposeSurfaces(const sp<const DisplayDevice>& display);
+ bool doComposeSurfaces(const sp<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 ebb58dc..2ea2654 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -46,6 +46,7 @@
using testing::AtLeast;
using testing::ByMove;
using testing::DoAll;
+using testing::Invoke;
using testing::IsNull;
using testing::Mock;
using testing::NotNull;
@@ -142,6 +143,9 @@
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();
@@ -266,13 +270,9 @@
EXPECT_CALL(*test->mRenderEngine, checkErrors()).WillRepeatedly(Return());
EXPECT_CALL(*test->mRenderEngine, isCurrent()).WillRepeatedly(Return(true));
- 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->mRenderEngine, flush()).WillRepeatedly(Invoke([]() {
+ return base::unique_fd(0);
+ }));
EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1);
EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1);
@@ -323,8 +323,6 @@
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) {
@@ -344,12 +342,18 @@
setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
ui::Transform::ROT_0))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*test->mRenderEngine, setCurrentSurface(Ref(*test->mRenderSurface)))
- .WillOnce(Return(true))
- .RetiresOnSaturation();
- EXPECT_CALL(*test->mRenderSurface, swapBuffers()).Times(1);
+ .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)));
}
template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index a8cd867..e4eb1d5 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -120,6 +120,7 @@
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
@@ -340,7 +341,6 @@
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.
@@ -349,17 +349,15 @@
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)));
+ // Creating a DisplayDevice requires getting default dimensions from the
+ // native window.
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) {
@@ -1070,9 +1068,6 @@
// 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);
@@ -1132,6 +1127,7 @@
.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,
@@ -1725,7 +1721,6 @@
EXPECT_CALL(*surface, setAsyncMode(true)).Times(1);
- EXPECT_CALL(*mProducer, connect(_, _, _, _)).Times(1);
EXPECT_CALL(*mProducer, disconnect(_, _)).Times(1);
Case::Display::setupHwcVirtualDisplayCreationCallExpectations(this);
@@ -1950,10 +1945,17 @@
auto nativeWindow = new mock::NativeWindow();
auto displaySurface = new mock::DisplaySurface();
auto renderSurface = new renderengine::mock::Surface();
+ sp<GraphicBuffer> buf = new GraphicBuffer();
auto display = Case::Display::makeFakeExistingDisplayInjector(this);
display.setNativeWindow(nativeWindow);
display.setDisplaySurface(displaySurface);
display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
+ // 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.inject();
// There is a change to the viewport state
@@ -1965,9 +1967,7 @@
// --------------------------------------------------------------------
// 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
@@ -1989,10 +1989,17 @@
auto nativeWindow = new mock::NativeWindow();
auto displaySurface = new mock::DisplaySurface();
auto renderSurface = new renderengine::mock::Surface();
+ sp<GraphicBuffer> buf = new GraphicBuffer();
auto display = Case::Display::makeFakeExistingDisplayInjector(this);
display.setNativeWindow(nativeWindow);
display.setDisplaySurface(displaySurface);
display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
+ // 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.inject();
// There is a change to the viewport state
@@ -2004,9 +2011,7 @@
// --------------------------------------------------------------------
// 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/mock/system/window/MockNativeWindow.h b/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
index 561fd58..4950a4b 100644
--- a/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
+++ b/services/surfaceflinger/tests/unittests/mock/system/window/MockNativeWindow.h
@@ -36,6 +36,7 @@
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));