summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Horn <doughorn@google.com>2021-01-08 10:23:00 -0800
committerDoug Horn <doughorn@google.com>2021-01-08 10:23:02 -0800
commitdbb2b627ab440cf49a69307936c3118b739bce7c (patch)
tree93fcb424424da529b190ffd9bf322022fa16b3ba
parentcae131fb6cd51548dc3e2496cac515ca730ed02f (diff)
downloadvulkan-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.h3
-rw-r--r--stream-servers/FrameBuffer.cpp23
-rw-r--r--stream-servers/PostWorker.cpp209
-rw-r--r--stream-servers/PostWorker.h54
-rw-r--r--stream-servers/ReadbackWorker.cpp16
-rw-r--r--stream-servers/ReadbackWorker.h15
-rw-r--r--stream-servers/glestranslator/EGL/EglImp.cpp1
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);