diff options
author | Doug Horn <doughorn@google.com> | 2021-01-08 10:23:00 -0800 |
---|---|---|
committer | Doug Horn <doughorn@google.com> | 2021-01-08 10:23:02 -0800 |
commit | dbb2b627ab440cf49a69307936c3118b739bce7c (patch) | |
tree | 93fcb424424da529b190ffd9bf322022fa16b3ba | |
parent | cae131fb6cd51548dc3e2496cac515ca730ed02f (diff) | |
download | vulkan-cereal-dbb2b627ab440cf49a69307936c3118b739bce7c.tar.gz |
try running post/compose only on the ui thread
lets us use emulator screen and virtual sensors page built from macos
10.15 sdk
Manual cherry-pick of aosp/1247446
Change-Id: I2bfa598a25dad450fecbee718b567a892acff0fd
-rw-r--r-- | host-common/window_agent.h | 3 | ||||
-rw-r--r-- | stream-servers/FrameBuffer.cpp | 23 | ||||
-rw-r--r-- | stream-servers/PostWorker.cpp | 209 | ||||
-rw-r--r-- | stream-servers/PostWorker.h | 54 | ||||
-rw-r--r-- | stream-servers/ReadbackWorker.cpp | 16 | ||||
-rw-r--r-- | stream-servers/ReadbackWorker.h | 15 | ||||
-rw-r--r-- | stream-servers/glestranslator/EGL/EglImp.cpp | 1 |
7 files changed, 303 insertions, 18 deletions
diff --git a/host-common/window_agent.h b/host-common/window_agent.h index ab3274d8..bc85c987 100644 --- a/host-common/window_agent.h +++ b/host-common/window_agent.h @@ -32,6 +32,8 @@ static const int kWindowMessageTimeoutInfinite = -1; typedef struct EmulatorWindow EmulatorWindow; +typedef void (*UiUpdateFunc)(void* data); + typedef struct QAndroidEmulatorWindowAgent { // Get a pointer to the emulator window structure. EmulatorWindow* (*getEmulatorWindow)(); @@ -85,4 +87,5 @@ typedef struct QAndroidEmulatorWindowAgent { bool (*startExtendedWindow)(void); bool (*quitExtendedWindow)(void); bool (*setUiTheme)(int settingsTheme); + void (*runOnUiThread)(UiUpdateFunc f, void* data, bool wait); } QAndroidEmulatorWindowAgent; diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp index 9b987839..2d561f6b 100644 --- a/stream-servers/FrameBuffer.cpp +++ b/stream-servers/FrameBuffer.cpp @@ -841,19 +841,38 @@ FrameBuffer::postWorkerFunc(const Post& post) { } void FrameBuffer::sendPostWorkerCmd(FrameBuffer::Post post) { +#ifdef __APPLE__ + bool postOnlyOnMainThread = m_subWin; +#else + bool postOnlyOnMainThread = false; +#endif + if (!m_postThread.isStarted()) { + if (postOnlyOnMainThread) { + EGLContext prevContext = s_egl.eglGetCurrentContext(); + EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); + EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); + m_prevContext = prevContext; + m_prevReadSurf = prevReadSurf; + m_prevDrawSurf = prevDrawSurf; + } m_postWorker.reset(new PostWorker([this]() { if (m_subWin) { return bindSubwin_locked(); } else { return bindFakeWindow_locked(); } - })); + }, + postOnlyOnMainThread, + m_eglContext, + m_eglSurface)); m_postThread.start(); } m_postThread.enqueue(Post(post)); - m_postThread.waitQueuedItems(); + if (!postOnlyOnMainThread) { + m_postThread.waitQueuedItems(); + } } void FrameBuffer::setPostCallback( diff --git a/stream-servers/PostWorker.cpp b/stream-servers/PostWorker.cpp index d3797737..49486142 100644 --- a/stream-servers/PostWorker.cpp +++ b/stream-servers/PostWorker.cpp @@ -1,3 +1,18 @@ +/* +* Copyright (C) 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. +*/ #include "PostWorker.h" #include "ColorBuffer.h" @@ -16,10 +31,25 @@ #define DD(fmt, ...) (void)0 #endif +static void sDefaultRunOnUiThread(UiUpdateFunc f, void* data, bool wait) { + (void)f; + (void)data; + (void)wait; +} -PostWorker::PostWorker(PostWorker::BindSubwinCallback&& cb) : +PostWorker::PostWorker( + PostWorker::BindSubwinCallback&& cb, + bool mainThreadPostingOnly, + EGLContext eglContext, + EGLSurface eglSurface) : mFb(FrameBuffer::getFB()), - mBindSubwin(cb) {} + mBindSubwin(cb), + m_mainThreadPostingOnly(mainThreadPostingOnly), + m_runOnUiThread(m_mainThreadPostingOnly ? + emugl::get_emugl_window_operations().runOnUiThread : + sDefaultRunOnUiThread), + mContext(eglContext), + mSurface(eglSurface) {} void PostWorker::fillMultiDisplayPostStruct(ComposeLayer* l, hwc_rect_t displayArea, @@ -33,9 +63,9 @@ void PostWorker::fillMultiDisplayPostStruct(ComposeLayer* l, l->crop = cropArea; } -void PostWorker::post(ColorBuffer* cb) { +void PostWorker::postImpl(ColorBuffer* cb) { // bind the subwindow eglSurface - if (!m_initialized) { + if (!m_mainThreadPostingOnly && !m_initialized) { m_initialized = mBindSubwin(); } @@ -138,10 +168,12 @@ void PostWorker::post(ColorBuffer* cb) { // This rebinds the subwindow context (to account for // when the refresh is a display change, for instance) // and resets the posting viewport. -void PostWorker::viewport(int width, int height) { +void PostWorker::viewportImpl(int width, int height) { // rebind the subwindow eglSurface unconditionally--- // this could be from a display change - m_initialized = mBindSubwin(); + if (!m_mainThreadPostingOnly) { + m_initialized = mBindSubwin(); + } float dpr = mFb->getDpr(); m_viewportWidth = width * dpr; @@ -153,18 +185,17 @@ void PostWorker::viewport(int width, int height) { // last posted color buffer to show to the user. Instead of // displaying whatever happens to be in the back buffer, // clear() is useful for outputting consistent colors. -void PostWorker::clear() { +void PostWorker::clearImpl() { #ifndef __linux__ - // Bug: 166317060 (Except it crashes on iris_dri.so) s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); s_egl.eglSwapBuffers(mFb->getDisplay(), mFb->getWindowSurface()); #endif } -void PostWorker::compose(ComposeDevice* p) { +void PostWorker::composeImpl(ComposeDevice* p) { // bind the subwindow eglSurface - if (!m_initialized) { + if (!m_mainThreadPostingOnly && !m_initialized) { m_initialized = mBindSubwin(); } @@ -203,9 +234,9 @@ void PostWorker::compose(ComposeDevice* p) { mFb->getTextureDraw()->cleanupForDrawLayer(); } -void PostWorker::compose(ComposeDevice_v2* p) { +void PostWorker::composev2Impl(ComposeDevice_v2* p) { // bind the subwindow eglSurface - if (!m_initialized) { + if (!m_mainThreadPostingOnly && !m_initialized) { m_initialized = mBindSubwin(); } @@ -244,6 +275,26 @@ void PostWorker::compose(ComposeDevice_v2* p) { mFb->getTextureDraw()->cleanupForDrawLayer(); } +void PostWorker::bind() { + if (m_mainThreadPostingOnly) { + if (mFb->getDisplay() != EGL_NO_DISPLAY) { + EGLint res = s_egl.eglMakeCurrent(mFb->getDisplay(), mFb->getWindowSurface(), mFb->getWindowSurface(), mContext); + if (!res) fprintf(stderr, "%s: error in binding: 0x%x\n", __func__, s_egl.eglGetError()); + } else { + fprintf(stderr, "%s: no display!\n", __func__); + } + } else { + mBindSubwin(); + } +} + +void PostWorker::unbind() { + if (mFb->getDisplay() != EGL_NO_DISPLAY) { + s_egl.eglMakeCurrent(mFb->getDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + } +} + void PostWorker::composeLayer(ComposeLayer* l) { if (l->composeMode == HWC2_COMPOSITION_DEVICE) { ColorBufferPtr cb = mFb->findColorBuffer(l->cbHandle); @@ -279,3 +330,137 @@ PostWorker::~PostWorker() { EGL_NO_CONTEXT); } } + +void PostWorker::post(ColorBuffer* cb) { + if (m_mainThreadPostingOnly) { + PostArgs args = { + .postCb = cb, + }; + + m_toUiThread.send(args); + + m_runOnUiThread([](void* data) { + PostWorker* p = (PostWorker*)data; + PostArgs uiThreadArgs; + p->m_toUiThread.receive(&uiThreadArgs); + p->bind(); + p->postImpl(uiThreadArgs.postCb); + p->m_fromUiThread.send(0); + }, + this, + false /* no wait */); + + int response; + m_fromUiThread.receive(&response); + + } else { + postImpl(cb); + } +} + +void PostWorker::viewport(int width, int height) { + if (m_mainThreadPostingOnly) { + PostArgs args = { + .width = width, + .height = height, + }; + + m_toUiThread.send(args); + + m_runOnUiThread([](void* data) { + PostWorker* p = (PostWorker*)data; + PostArgs uiThreadArgs; + p->m_toUiThread.receive(&uiThreadArgs); + p->bind(); + p->viewportImpl(uiThreadArgs.width, uiThreadArgs.height); + p->m_fromUiThread.send(0); + }, + this, + false /* no wait */); + + int response; + m_fromUiThread.receive(&response); + + } else { + viewportImpl(width, height); + } +} + +void PostWorker::compose(ComposeDevice* p) { + if (m_mainThreadPostingOnly) { + PostArgs args = { + .composeDevice = p, + }; + + m_toUiThread.send(args); + + m_runOnUiThread([](void* data) { + PostWorker* p = (PostWorker*)data; + PostArgs uiThreadArgs; + p->m_toUiThread.receive(&uiThreadArgs); + p->bind(); + p->composeImpl(uiThreadArgs.composeDevice); + p->m_fromUiThread.send(0); + }, + this, + false /* no wait */); + + int response; + m_fromUiThread.receive(&response); + } else { + composeImpl(p); + } +} + +void PostWorker::compose(ComposeDevice_v2* p) { + if (m_mainThreadPostingOnly) { + PostArgs args = { + .composeDevice_v2 = p, + }; + + m_toUiThread.send(args); + + m_runOnUiThread([](void* data) { + PostWorker* p = (PostWorker*)data; + PostArgs uiThreadArgs; + p->m_toUiThread.receive(&uiThreadArgs); + p->bind(); + p->composev2Impl(uiThreadArgs.composeDevice_v2); + p->m_fromUiThread.send(0); + }, + this, + false /* no wait */); + + int response; + m_fromUiThread.receive(&response); + } else { + composev2Impl(p); + } +} + +void PostWorker::clear() { + if (m_mainThreadPostingOnly) { + PostArgs args = { + .postCb = 0, + }; + + m_toUiThread.send(args); + + m_runOnUiThread([](void* data) { + PostWorker* p = (PostWorker*)data; + PostArgs uiThreadArgs; + p->m_toUiThread.receive(&uiThreadArgs); + p->bind(); + p->clearImpl(); + p->m_fromUiThread.send(0); + }, + this, + false /* no wait */); + + int response; + m_fromUiThread.receive(&response); + } else { + clearImpl(); + } +} + diff --git a/stream-servers/PostWorker.h b/stream-servers/PostWorker.h index f4a1d3cb..d416847e 100644 --- a/stream-servers/PostWorker.h +++ b/stream-servers/PostWorker.h @@ -1,5 +1,24 @@ +/* +* Copyright (C) 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 "base/Compiler.h" +#include "base/MessageChannel.h" +#include "host-common/window_agent.h" + #include <EGL/egl.h> #include <GLES/gl.h> #include <GLES3/gl3.h> @@ -19,7 +38,10 @@ class PostWorker { public: using BindSubwinCallback = std::function<bool(void)>; - PostWorker(BindSubwinCallback&& cb); + PostWorker(BindSubwinCallback&& cb, + bool mainThreadPostingOnly, + EGLContext eglContext, + EGLSurface eglSurface); ~PostWorker(); // post: posts the next color buffer. @@ -51,6 +73,17 @@ public: void* pixels); private: + // Impl versions of the above, so we can run it from separate threads + void postImpl(ColorBuffer* cb); + void viewportImpl(int width, int height); + void composeImpl(ComposeDevice* p); + void composev2Impl(ComposeDevice_v2* p); + void clearImpl(); + + // Subwindow binding + void bind(); + void unbind(); + void composeLayer(ComposeLayer* l); void fillMultiDisplayPostStruct(ComposeLayer* l, hwc_rect_t displayArea, @@ -58,8 +91,15 @@ private: hwc_transform_t transform); private: - EGLContext mContext; - EGLSurface mSurf; + using UiThreadRunner = std::function<void(UiUpdateFunc, void*, bool)>; + struct PostArgs { + ColorBuffer* postCb; + int width; + int height; + ComposeDevice* composeDevice; + ComposeDevice_v2* composeDevice_v2; + }; + RenderThreadInfo* mTLS; FrameBuffer* mFb; @@ -69,5 +109,13 @@ private: int m_viewportWidth = 0; int m_viewportHeight = 0; GLuint m_composeFbo = 0; + + bool m_mainThreadPostingOnly = false; + UiThreadRunner m_runOnUiThread = 0; + android::base::MessageChannel<PostArgs, 1> m_toUiThread; + android::base::MessageChannel<int, 1> m_fromUiThread; + EGLContext mContext = EGL_NO_CONTEXT; + EGLSurface mSurface = EGL_NO_SURFACE; + DISALLOW_COPY_AND_ASSIGN(PostWorker); }; diff --git a/stream-servers/ReadbackWorker.cpp b/stream-servers/ReadbackWorker.cpp index 21a21b00..de885b68 100644 --- a/stream-servers/ReadbackWorker.cpp +++ b/stream-servers/ReadbackWorker.cpp @@ -1,4 +1,18 @@ - +/* +* Copyright (C) 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. +*/ #include "ReadbackWorker.h" #include <string.h> // for memcpy diff --git a/stream-servers/ReadbackWorker.h b/stream-servers/ReadbackWorker.h index 9739cf8b..b463cac1 100644 --- a/stream-servers/ReadbackWorker.h +++ b/stream-servers/ReadbackWorker.h @@ -1,3 +1,18 @@ +/* +* Copyright (C) 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 <EGL/egl.h> // for EGLContext, EGLSurface diff --git a/stream-servers/glestranslator/EGL/EglImp.cpp b/stream-servers/glestranslator/EGL/EglImp.cpp index 74a750c1..8909bc57 100644 --- a/stream-servers/glestranslator/EGL/EglImp.cpp +++ b/stream-servers/glestranslator/EGL/EglImp.cpp @@ -1559,6 +1559,7 @@ EGLAPI void* EGLAPIENTRY eglSetImageFenceANDROID(EGLDisplay dpy, EGLImageKHR ima unsigned int imagehndl = SafeUIntFromPointer(image); ImagePtr img = getEGLImage(imagehndl); const GLESiface* iface = g_eglInfo->getIface(GLES_2_0); + if (!img) return iface->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); if (img->sync) { iface->deleteSync((GLsync)img->sync); |