diff options
| author | 2018-11-15 02:11:10 +0000 | |
|---|---|---|
| committer | 2018-11-15 02:11:10 +0000 | |
| commit | 682188b59314324d7e3b573d950de0bbba6927fb (patch) | |
| tree | f3341302aeebee1a285243cf89a24c173eedb214 | |
| parent | 7b0e9118785103c763042e56642e1234935e1e58 (diff) | |
| parent | 8d4f90aaadf9f3be77d258d2acd67b6186352811 (diff) | |
Merge changes Iea02806d,I45af7b49,Id50e0d23
* changes:
Revert "Bind to FBO when using GPU composition"
Revert "Remove gl surfaces from DisplayDevice."
Revert "Delete renderengine::Surface"
19 files changed, 457 insertions, 203 deletions
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index beaf9ee70d..7efc8bd64d 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -50,6 +50,7 @@ filegroup { "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 d35762d447..70a4322c5f 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 @@ std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat, // 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 @@ std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat, 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 @@ std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat, 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 @@ EGLConfig GLES20RenderEngine::chooseEglConfig(EGLDisplay display, int format, bo 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 @@ std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() { 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 @@ bool GLES20RenderEngine::isCurrent() const { 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::fillRegionWithColor(const Region& region, float red, fl 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 @@ status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) { 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 @@ status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) { } 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 @@ void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect s 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 @@ bool GLES20RenderEngine::needsXYZTransformMatrix() const { 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 6c50938863..148df2fbb4 100644 --- a/libs/renderengine/gl/GLES20RenderEngine.h +++ b/libs/renderengine/gl/GLES20RenderEngine.h @@ -40,21 +40,24 @@ class Texture; 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 @@ private: // 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 @@ private: 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 0000000000..2d694e9124 --- /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 0000000000..092d371ee9 --- /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 22891c42c4..becb3c3a10 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -48,6 +48,7 @@ namespace renderengine { class BindNativeBufferAsFramebuffer; class Image; class Mesh; +class Surface; class Texture; namespace impl { @@ -71,6 +72,7 @@ public: // 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 @@ public: 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 0000000000..ba7331daab --- /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/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 9abb040a9c..f168db9f7b 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -184,7 +184,6 @@ cc_defaults { "libhidltransport", "liblayers_proto", "liblog", - "libsync", "libtimestats_proto", "libutils", ], diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index d16febfaa2..5342bcf0a5 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 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) 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 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) 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 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) 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 @@ uint32_t DisplayDevice::getPageFlipCount() const { void DisplayDevice::flip() const { + mFlinger->getRenderEngine().checkErrors(); mPageFlipCount++; } @@ -360,71 +356,9 @@ status_t DisplayDevice::prepareFrame(HWComposer& hwc, 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::queueBuffer(HWComposer& hwc) { } } -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 @@ void DisplayDevice::setViewportAndProjection() const { 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 @@ status_t DisplayDevice::orientationToTransfrom( 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 @@ void DisplayDevice::dump(String8& result) const { 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 @@ void DisplayDevice::dump(String8& result) const { 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 eb2c5c3f94..bcd3330cf2 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 @@ public: 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 @@ public: 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 @@ private: // 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 @@ struct DisplayDeviceCreationArgs { 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 5f3fcd6e88..27d3dc5609 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -107,6 +107,8 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, 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 e84e21a462..25c60fe3d3 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 @@ void SurfaceFlinger::init() { 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 @@ void SurfaceFlinger::resetDisplayState() { // mCurrentState and mDrawingState and re-apply all changes when we make the // transition. mDrawingState.displays.clear(); + getRenderEngine().resetCurrentSurface(); mDisplays.clear(); } @@ -1715,7 +1719,7 @@ void SurfaceFlinger::doDebugFlashRegions(const sp<DisplayDevice>& display, bool auto& engine(getRenderEngine()); engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1); - display->queueBuffer(getHwComposer()); + display->swapBuffers(getHwComposer()); } } @@ -2190,7 +2194,8 @@ void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& display) 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 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( 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 @@ void SurfaceFlinger::processDisplayChangesLocked() { 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 @@ void SurfaceFlinger::invalidateHwcGeometry() 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 @@ void SurfaceFlinger::doDisplayComposition(const sp<DisplayDevice>& display, 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 SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& display) { 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 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& display) { 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 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& display) { 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; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f5218b175a..6ffe0259d4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -721,10 +721,10 @@ private: 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 cfaf495767..ab1b2522cf 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -46,7 +46,6 @@ using testing::_; 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 @@ public: 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 @@ public: 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 @@ struct BaseDisplayVariant { 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 @@ struct BaseDisplayVariant { 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 @@ struct BaseDisplayVariant { 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 @@ struct BaseDisplayVariant { 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 ac6a78b75f..32fce677af 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -120,7 +120,6 @@ public: 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 @@ public: sp<mock::GraphicBufferConsumer> mConsumer; sp<mock::GraphicBufferProducer> mProducer; surfaceflinger::mock::NativeWindowSurface* mNativeWindowSurface = nullptr; + renderengine::mock::Surface* mRenderSurface = nullptr; }; DisplayTransactionTest::DisplayTransactionTest() { @@ -340,11 +340,26 @@ struct DisplayVariant { 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 @@ TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) { // 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 @@ public: .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 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAdded) { 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 @@ TEST_F(HandleTransactionLockedTest, processesDisplayWidthChanges) { // 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 @@ TEST_F(HandleTransactionLockedTest, processesDisplayWidthChanges) { // -------------------------------------------------------------------- // 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 @@ TEST_F(HandleTransactionLockedTest, processesDisplayHeightChanges) { // 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 @@ TEST_F(HandleTransactionLockedTest, processesDisplayHeightChanges) { // -------------------------------------------------------------------- // 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 85c835e2e5..a519f1fb52 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -474,6 +474,11 @@ public: 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 fbfbc3fc99..af54df6d2b 100644 --- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp +++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp @@ -26,6 +26,9 @@ namespace mock { 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 90c3c20b68..afca63ad39 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 @@ public: ~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 @@ public: 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 4950a4b9e2..561fd5869e 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 @@ public: 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)); |