Merge "Revert "gfxstream: introduce GFXSTREAM_ENABLE_HOST_GLES compiler flag"" into main
diff --git a/Android.bp b/Android.bp
index a4ce1a4..b67833a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -123,7 +123,6 @@
"-DUSING_ANDROID_BP",
"-D_FILE_OFFSET_BITS=64",
"-DVK_GFXSTREAM_STRUCTURE_TYPE_EXT",
- "-DGFXSTREAM_ENABLE_HOST_GLES=1",
"-Wno-unreachable-code-loop-increment",
"-Wno-unused-parameter",
"-Wno-unused-function",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6a29a17..b23070c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,8 +41,6 @@
if(VIRGL_RENDERER_UNSTABLE_APIS)
add_definitions(-DVIRGL_RENDERER_UNSTABLE_APIS)
endif()
-
-add_definitions(-DGFXSTREAM_ENABLE_HOST_GLES=1)
option(ASTC_CPU_DECODING "Enable decoding ASTC textures on the CPU" OFF)
diff --git a/host/Buffer.cpp b/host/Buffer.cpp
index b60a1ec..1858924 100644
--- a/host/Buffer.cpp
+++ b/host/Buffer.cpp
@@ -14,10 +14,7 @@
#include "Buffer.h"
-#if GFXSTREAM_ENABLE_HOST_GLES
#include "gl/EmulationGl.h"
-#endif
-
#include "vulkan/BufferVk.h"
#include "vulkan/VkCommonOperations.h"
@@ -34,7 +31,6 @@
uint64_t size, HandleType handle) {
std::shared_ptr<Buffer> buffer(new Buffer(handle, size));
-#if GFXSTREAM_ENABLE_HOST_GLES
if (emulationGl) {
buffer->mBufferGl = emulationGl->createBuffer(size, handle);
if (!buffer->mBufferGl) {
@@ -42,7 +38,6 @@
return nullptr;
}
}
-#endif
if (emulationVk && emulationVk->live) {
const bool vulkanOnly = emulationGl == nullptr;
@@ -54,11 +49,10 @@
}
if (!vulkanOnly) {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (!buffer->mBufferGl) {
GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Missing BufferGl?";
}
-#endif
+
// TODO: external memory sharing.
}
}
@@ -74,7 +68,6 @@
std::shared_ptr<Buffer> buffer(new Buffer(handle, size));
-#if GFXSTREAM_ENABLE_HOST_GLES
if (emulationGl) {
buffer->mBufferGl = emulationGl->loadBuffer(stream);
if (!buffer->mBufferGl) {
@@ -82,7 +75,6 @@
return nullptr;
}
}
-#endif
buffer->mNeedRestore = true;
@@ -93,11 +85,9 @@
stream->putBe32(mHandle);
stream->putBe64(mSize);
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mBufferGl) {
mBufferGl->onSave(stream);
}
-#endif
}
void Buffer::restore() {}
@@ -105,13 +95,10 @@
void Buffer::readToBytes(uint64_t offset, uint64_t size, void* outBytes) {
touch();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mBufferGl) {
mBufferGl->read(offset, size, outBytes);
return;
}
-#endif
-
if (mBufferVk) {
mBufferVk->readToBytes(offset, size, outBytes);
return;
@@ -123,13 +110,10 @@
bool Buffer::updateFromBytes(uint64_t offset, uint64_t size, const void* bytes) {
touch();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mBufferGl) {
mBufferGl->subUpdate(offset, size, bytes);
return true;
}
-#endif
-
if (mBufferVk) {
return mBufferVk->updateFromBytes(offset, size, bytes);
}
diff --git a/host/Buffer.h b/host/Buffer.h
index 414ff05..5db0db3 100644
--- a/host/Buffer.h
+++ b/host/Buffer.h
@@ -18,11 +18,8 @@
#include "Handle.h"
#include "aemu/base/files/Stream.h"
-#include "snapshot/LazySnapshotObj.h"
-
-#if GFXSTREAM_ENABLE_HOST_GLES
#include "gl/BufferGl.h"
-#endif
+#include "snapshot/LazySnapshotObj.h"
namespace gfxstream {
namespace gl {
@@ -64,10 +61,8 @@
const uint64_t mSize;
const HandleType mHandle;
-#if GFXSTREAM_ENABLE_HOST_GLES
// If GL emulation is enabled.
std::unique_ptr<gl::BufferGl> mBufferGl;
-#endif
// If Vk emulation is enabled.
std::unique_ptr<vk::BufferVk> mBufferVk;
diff --git a/host/ColorBuffer.cpp b/host/ColorBuffer.cpp
index 3cdecbf..6a8f58d 100644
--- a/host/ColorBuffer.cpp
+++ b/host/ColorBuffer.cpp
@@ -14,10 +14,7 @@
#include "ColorBuffer.h"
-#if GFXSTREAM_ENABLE_HOST_GLES
#include "gl/EmulationGl.h"
-#endif
-
#include "host-common/GfxstreamFatalError.h"
#include "host-common/logging.h"
#include "vulkan/ColorBufferVk.h"
@@ -58,7 +55,6 @@
std::shared_ptr<ColorBuffer> colorBuffer(
new ColorBuffer(handle, width, height, format, frameworkFormat));
-#if GFXSTREAM_ENABLE_HOST_GLES
if (emulationGl) {
colorBuffer->mColorBufferGl =
emulationGl->createColorBuffer(width, height, format, frameworkFormat, handle);
@@ -67,7 +63,6 @@
return nullptr;
}
}
-#endif
if (emulationVk && emulationVk->live) {
const bool vulkanOnly = colorBuffer->mColorBufferGl == nullptr;
@@ -86,7 +81,6 @@
}
}
-#if GFXSTREAM_ENABLE_HOST_GLES
bool b271028352Workaround = emulationGl && strstr(emulationGl->getGlesRenderer().c_str(), "Intel");
if (colorBuffer->mColorBufferGl && colorBuffer->mColorBufferVk &&
@@ -103,7 +97,6 @@
}
}
}
-#endif
return colorBuffer;
}
@@ -120,7 +113,6 @@
std::shared_ptr<ColorBuffer> colorBuffer(
new ColorBuffer(handle, width, height, format, frameworkFormat));
-#if GFXSTREAM_ENABLE_HOST_GLES
if (emulationGl) {
colorBuffer->mColorBufferGl = emulationGl->loadColorBuffer(stream);
if (!colorBuffer->mColorBufferGl) {
@@ -128,7 +120,6 @@
return nullptr;
}
}
-#endif
colorBuffer->mNeedRestore = true;
@@ -142,32 +133,25 @@
stream->putBe32(static_cast<uint32_t>(mFormat));
stream->putBe32(static_cast<uint32_t>(mFrameworkFormat));
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
mColorBufferGl->onSave(stream);
}
-#endif
}
void ColorBuffer::restore() {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
mColorBufferGl->restore();
}
-#endif
}
void ColorBuffer::readToBytes(int x, int y, int width, int height, GLenum pixelsFormat,
GLenum pixelsType, void* outPixels) {
touch();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
mColorBufferGl->readPixels(x, y, width, height, pixelsFormat, pixelsType, outPixels);
return;
}
-#endif
-
if (mColorBufferVk) {
mColorBufferVk->readToBytes(x, y, width, height, outPixels);
return;
@@ -181,13 +165,11 @@
void* outPixels) {
touch();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
mColorBufferGl->readPixelsScaled(pixelsWidth, pixelsHeight, pixelsFormat, pixelsType,
pixelsRotation, rect, outPixels);
return;
}
-#endif
GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Unimplemented.";
}
@@ -196,13 +178,10 @@
uint32_t pixelsSize) {
touch();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
mColorBufferGl->readPixelsYUVCached(x, y, width, height, outPixels, pixelsSize);
return;
}
-#endif
-
if (mColorBufferVk) {
mColorBufferVk->readToBytes(x, y, width, height, outPixels);
return;
@@ -216,14 +195,11 @@
GLenum pixelsType, const void* pixels, void* metadata) {
touch();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
mColorBufferGl->subUpdateFromFrameworkFormat(x, y, width, height, frameworkFormat,
pixelsFormat, pixelsType, pixels, metadata);
return true;
}
-#endif
-
if (mColorBufferVk) {
return mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
}
@@ -236,12 +212,9 @@
GLenum pixelsType, const void* pixels) {
touch();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
return mColorBufferGl->subUpdate(x, y, width, height, pixelsFormat, pixelsType, pixels);
}
-#endif
-
if (mColorBufferVk) {
return mColorBufferVk->updateFromBytes(x, y, width, height, pixels);
}
@@ -251,13 +224,11 @@
}
bool ColorBuffer::updateGlFromBytes(const void* bytes, std::size_t bytesSize) {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
touch();
return mColorBufferGl->replaceContents(bytes, bytesSize);
}
-#endif
return true;
}
@@ -265,12 +236,10 @@
std::unique_ptr<BorrowedImageInfo> ColorBuffer::borrowForComposition(UsedApi api, bool isTarget) {
switch (api) {
case UsedApi::kGl: {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (!mColorBufferGl) {
GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
}
return mColorBufferGl->getBorrowedImageInfo();
-#endif
}
case UsedApi::kVk: {
if (!mColorBufferVk) {
@@ -286,12 +255,10 @@
std::unique_ptr<BorrowedImageInfo> ColorBuffer::borrowForDisplay(UsedApi api) {
switch (api) {
case UsedApi::kGl: {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (!mColorBufferGl) {
GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
}
return mColorBufferGl->getBorrowedImageInfo();
-#endif
}
case UsedApi::kVk: {
if (!mColorBufferVk) {
@@ -326,6 +293,7 @@
if (mGlAndVkAreSharingExternalMemory) {
return true;
}
+
std::vector<uint8_t> contents;
if (!vk::readColorBufferToBytes(mHandle, &contents)) {
ERR("Failed to get VK contents for ColorBuffer:%d", mHandle);
@@ -336,12 +304,10 @@
return false;
}
-#if GFXSTREAM_ENABLE_HOST_GLES
if (!mColorBufferGl->replaceContents(contents.data(), contents.size())) {
ERR("Failed to set GL contents for ColorBuffer:%d", mHandle);
return false;
}
-#endif
return true;
}
@@ -355,14 +321,12 @@
return true;
}
-#if GFXSTREAM_ENABLE_HOST_GLES
if (mColorBufferGl) {
if (!mColorBufferGl->replaceContents(bytes, bytesSize)) {
ERR("Failed to update ColorBuffer:%d GL backing from VK bytes.", mHandle);
return false;
}
}
-#endif
return true;
}
@@ -390,7 +354,6 @@
return true;
}
-#if GFXSTREAM_ENABLE_HOST_GLES
std::size_t contentsSize = 0;
if (!mColorBufferGl->readContents(&contentsSize, nullptr)) {
ERR("Failed to get GL contents size for ColorBuffer:%d", mHandle);
@@ -408,7 +371,6 @@
ERR("Failed to set VK contents for ColorBuffer:%d", mHandle);
return false;
}
-#endif
return true;
}
@@ -437,7 +399,6 @@
}
}
-#if GFXSTREAM_ENABLE_HOST_GLES
bool ColorBuffer::glOpBlitFromCurrentReadBuffer() {
if (!mColorBufferGl) {
GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "ColorBufferGl not available.";
@@ -568,6 +529,5 @@
mColorBufferGl->postViewportScaledWithOverlay(rotation, dx, dy);
}
-#endif
} // namespace gfxstream
diff --git a/host/ColorBuffer.h b/host/ColorBuffer.h
index 7056267..f519fe7 100644
--- a/host/ColorBuffer.h
+++ b/host/ColorBuffer.h
@@ -21,15 +21,10 @@
#include "Handle.h"
#include "Hwc2.h"
#include "aemu/base/files/Stream.h"
+#include "gl/ColorBufferGl.h"
#include "render-utils/Renderer.h"
#include "snapshot/LazySnapshotObj.h"
-#if GFXSTREAM_ENABLE_HOST_GLES
-#include "gl/ColorBufferGl.h"
-#else
-#include "GlesCompat.h"
-#endif
-
namespace gfxstream {
namespace gl {
class EmulationGl;
@@ -91,7 +86,6 @@
bool invalidateForVk();
bool importNativeResource(void* nativeResource, uint32_t type, bool preserveContent);
-#if GFXSTREAM_ENABLE_HOST_GLES
GLuint glOpGetTexture();
bool glOpBlitFromCurrentReadBuffer();
bool glOpBindToTexture();
@@ -107,7 +101,6 @@
bool glOpIsFastBlitSupported() const;
void glOpPostLayer(const ComposeLayer& l, int frameWidth, int frameHeight);
void glOpPostViewportScaledWithOverlay(float rotation, float dx, float dy);
-#endif
private:
ColorBuffer(HandleType, uint32_t width, uint32_t height, GLenum format,
@@ -119,12 +112,8 @@
const GLenum mFormat;
const FrameworkFormat mFrameworkFormat;
-#if GFXSTREAM_ENABLE_HOST_GLES
// If GL emulation is enabled.
std::unique_ptr<gl::ColorBufferGl> mColorBufferGl;
-#else
- std::unique_ptr<uint32_t> mColorBufferGl = nullptr;
-#endif
// If Vk emulation is enabled.
std::unique_ptr<vk::ColorBufferVk> mColorBufferVk;
diff --git a/host/FrameBuffer.cpp b/host/FrameBuffer.cpp
index 54f78b9..f7f0016 100644
--- a/host/FrameBuffer.cpp
+++ b/host/FrameBuffer.cpp
@@ -27,9 +27,15 @@
#endif
#include "ContextHelper.h"
+#include "GLESVersionDetector.h"
#include "Hwc2.h"
#include "NativeSubWindow.h"
+#include "OpenGLESDispatch/DispatchTables.h"
+#include "OpenGLESDispatch/EGLDispatch.h"
+#include "PostWorkerGl.h"
+#include "RenderControl.h"
#include "RenderThreadInfo.h"
+#include "RenderThreadInfoGl.h"
#include "SyncThread.h"
#include "aemu/base/LayoutResolver.h"
#include "aemu/base/Metrics.h"
@@ -40,19 +46,9 @@
#include "aemu/base/memory/MemoryTracker.h"
#include "aemu/base/synchronization/Lock.h"
#include "aemu/base/system/System.h"
-
-#if GFXSTREAM_ENABLE_HOST_GLES
-#include "GLESVersionDetector.h"
-#include "OpenGLESDispatch/DispatchTables.h"
-#include "OpenGLESDispatch/EGLDispatch.h"
-#include "PostWorkerGl.h"
-#include "RenderControl.h"
-#include "RenderThreadInfoGl.h"
#include "gl/YUVConverter.h"
#include "gl/gles2_dec/gles2_dec.h"
#include "gl/glestranslator/EGL/EglGlobalInfo.h"
-#endif
-
#include "host-common/GfxstreamFatalError.h"
#include "host-common/crash_reporter.h"
#include "host-common/feature_control.h"
@@ -77,8 +73,6 @@
using emugl::CreateHealthMonitor;
using emugl::FatalError;
using emugl::GfxApiLogger;
-
-#if GFXSTREAM_ENABLE_HOST_GLES
using gl::DisplaySurfaceGl;
using gl::EmulatedEglConfig;
using gl::EmulatedEglConfigList;
@@ -101,7 +95,6 @@
using gl::TextureDraw;
using gl::YUVConverter;
using gl::YUVPlane;
-#endif
using gfxstream::vk::AstcEmulationMode;
using gfxstream::vk::VkEmulationFeatures;
@@ -334,7 +327,6 @@
}
}
-#if GFXSTREAM_ENABLE_HOST_GLES
// Do not initialize GL emulation if the guest is using ANGLE.
if (!feature_is_enabled(kFeature_GuestUsesAngle)) {
fb->m_emulationGl = EmulationGl::create(width, height, useSubWindow, egl2egl);
@@ -343,7 +335,6 @@
return false;
}
}
-#endif
fb->m_guestUsesAngle =
feature_is_enabled(
@@ -413,13 +404,11 @@
fb->m_graphicsDeviceExtensions = deviceExtensionsStringBuilder.str();
} else if (fb->m_emulationGl) {
-#if GFXSTREAM_ENABLE_HOST_GLES
fb->m_graphicsAdapterVendor = fb->m_emulationGl->getGlesVendor();
fb->m_graphicsAdapterName = fb->m_emulationGl->getGlesRenderer();
fb->m_graphicsApiVersion = fb->m_emulationGl->getGlesVersionString();
fb->m_graphicsApiExtensions = fb->m_emulationGl->getGlesExtensionsString();
fb->m_graphicsDeviceExtensions = "N/A";
-#endif
} else {
fb->m_graphicsAdapterVendor = "N/A";
fb->m_graphicsAdapterName = "N/A";
@@ -443,7 +432,6 @@
if (!fb->m_emulationGl) {
vulkanInteropSupported = false;
} else {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (!fb->m_emulationGl->isGlesVulkanInteropSupported()) {
vulkanInteropSupported = false;
}
@@ -451,7 +439,6 @@
if (!glesDeviceUuid || glesDeviceUuid != fb->m_vulkanUUID) {
vulkanInteropSupported = false;
}
-#endif
}
// TODO: 0-copy gl interop on swiftshader vk
if (android::base::getEnvironmentVariable("ANDROID_EMU_VK_ICD") == "swiftshader") {
@@ -462,13 +449,11 @@
fb->m_vulkanInteropSupported = vulkanInteropSupported;
GL_LOG("interop? %d", fb->m_vulkanInteropSupported);
-#if GFXSTREAM_ENABLE_HOST_GLES
if (vulkanInteropSupported && fb->m_emulationGl && fb->m_emulationGl->isMesa()) {
// Mesa currently expects dedicated allocations for external memory sharing
// between GL and VK. See b/265186355.
vkEmulationFeatures->useDedicatedAllocations = true;
}
-#endif
GL_LOG("glvk interop final: %d", fb->m_vulkanInteropSupported);
vkEmulationFeatures->glInteropSupported = fb->m_vulkanInteropSupported;
@@ -489,19 +474,15 @@
fb->m_compositor = vkEmu->compositorVk.get();
} else {
GL_LOG("Performing composition using CompositorGl.");
-#if GFXSTREAM_ENABLE_HOST_GLES
auto compositorGl = fb->m_emulationGl->getCompositor();
fb->m_compositor = compositorGl;
-#endif
}
-#if GFXSTREAM_ENABLE_HOST_GLES
if (fb->m_emulationGl) {
auto displayGl = fb->m_emulationGl->getDisplay();
fb->m_displayGl = displayGl;
fb->m_displaySurfaceUsers.push_back(displayGl);
}
-#endif
INFO("Graphics Adapter Vendor %s", fb->m_graphicsAdapterVendor.c_str());
INFO("Graphics Adapter %s", fb->m_graphicsAdapterName.c_str());
@@ -514,13 +495,11 @@
} else {
const bool shouldPostOnlyOnMainThread = postOnlyOnMainThread();
-#if GFXSTREAM_ENABLE_HOST_GLES
PostWorkerGl* postWorkerGl =
new PostWorkerGl(shouldPostOnlyOnMainThread, fb.get(), fb->m_compositor,
fb->m_displayGl, fb->m_emulationGl.get());
fb->m_postWorker.reset(postWorkerGl);
fb->m_displaySurfaceUsers.push_back(postWorkerGl);
-#endif
}
// Start up the single sync thread. If we are using Vulkan native
@@ -555,6 +534,12 @@
}
}
+void FrameBuffer::fillGLESUsages(android_studio::EmulatorGLESUsages* usages) {
+ if (s_egl.eglFillUsages) {
+ s_egl.eglFillUsages(usages);
+ }
+}
+
FrameBuffer::FrameBuffer(int p_width, int p_height, bool useSubWindow)
: m_framebufferWidth(p_width),
m_framebufferHeight(p_height),
@@ -615,14 +600,12 @@
}
m_colorBufferDelayedCloseList.clear();
-#if GFXSTREAM_ENABLE_HOST_GLES
m_windows.clear();
m_contexts.clear();
for (auto it : m_platformEglContexts) {
destroySharedTrivialContext(it.second.context, it.second.surface);
}
-#endif
vk::teardownGlobalVkEmulation();
@@ -939,11 +922,9 @@
m_displaySurface =
vk::createDisplaySurface(m_subWin, m_windowWidth, m_windowHeight);
} else if (m_emulationGl) {
-#if GFXSTREAM_ENABLE_HOST_GLES
m_displaySurface = m_emulationGl->createWindowSurface(m_windowWidth,
m_windowHeight,
m_subWin);
-#endif
} else {
GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
<< "Unhandled window surface creation.";
@@ -1098,10 +1079,8 @@
HandleType id;
do {
id = ++s_nextHandle;
- } while (id == 0 ||
-#if GFXSTREAM_ENABLE_HOST_GLES
- m_contexts.find(id) != m_contexts.end() || m_windows.find(id) != m_windows.end() ||
-#endif
+ } while (id == 0 || m_contexts.find(id) != m_contexts.end() ||
+ m_windows.find(id) != m_windows.end() ||
m_colorbuffers.find(id) != m_colorbuffers.end() ||
m_buffers.find(id) != m_buffers.end());
@@ -1224,10 +1203,296 @@
return handle;
}
+HandleType FrameBuffer::createEmulatedEglContext(int config,
+ HandleType shareContextHandle,
+ GLESApi version) {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation unavailable.";
+ }
+
+ AutoLock mutex(m_lock);
+ android::base::AutoWriteLock contextLock(m_contextStructureLock);
+ // Hold the ColorBuffer map lock so that the new handle won't collide with a ColorBuffer handle.
+ AutoLock colorBufferMapLock(m_colorBufferMapLock);
+
+ EmulatedEglContextPtr shareContext = nullptr;
+ if (shareContextHandle != 0) {
+ auto shareContextIt = m_contexts.find(shareContextHandle);
+ if (shareContextIt == m_contexts.end()) {
+ ERR("Failed to find share EmulatedEglContext:%d", shareContextHandle);
+ return 0;
+ }
+ shareContext = shareContextIt->second;
+ }
+
+ HandleType contextHandle = genHandle_locked();
+ auto context = m_emulationGl->createEmulatedEglContext(config,
+ shareContext.get(),
+ version,
+ contextHandle);
+ if (!context) {
+ ERR("Failed to create EmulatedEglContext.");
+ return 0;
+ }
+
+ m_contexts[contextHandle] = std::move(context);
+
+ RenderThreadInfo* tinfo = RenderThreadInfo::get();
+ uint64_t puid = tinfo->m_puid;
+ // The new emulator manages render contexts per guest process.
+ // Fall back to per-thread management if the system image does not
+ // support it.
+ if (puid) {
+ m_procOwnedEmulatedEglContexts[puid].insert(contextHandle);
+ } else { // legacy path to manage context lifetime by threads
+ if (!tinfo->m_glInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+ tinfo->m_glInfo->m_contextSet.insert(contextHandle);
+ }
+
+ return contextHandle;
+}
+
+void FrameBuffer::destroyEmulatedEglContext(HandleType contextHandle) {
+ AutoLock mutex(m_lock);
+ sweepColorBuffersLocked();
+
+ android::base::AutoWriteLock contextLock(m_contextStructureLock);
+ m_contexts.erase(contextHandle);
+ RenderThreadInfo* tinfo = RenderThreadInfo::get();
+ uint64_t puid = tinfo->m_puid;
+ // The new emulator manages render contexts per guest process.
+ // Fall back to per-thread management if the system image does not
+ // support it.
+ if (puid) {
+ auto it = m_procOwnedEmulatedEglContexts.find(puid);
+ if (it != m_procOwnedEmulatedEglContexts.end()) {
+ it->second.erase(contextHandle);
+ }
+ } else {
+ if (!tinfo->m_glInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+ tinfo->m_glInfo->m_contextSet.erase(contextHandle);
+ }
+}
+
+HandleType FrameBuffer::createEmulatedEglWindowSurface(int p_config,
+ int p_width,
+ int p_height) {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation unavailable.";
+ }
+
+ AutoLock mutex(m_lock);
+ // Hold the ColorBuffer map lock so that the new handle won't collide with a ColorBuffer handle.
+ AutoLock colorBufferMapLock(m_colorBufferMapLock);
+
+ HandleType handle = genHandle_locked();
+
+ auto window = m_emulationGl->createEmulatedEglWindowSurface(p_config,
+ p_width,
+ p_height,
+ handle);
+ if (!window) {
+ ERR("Failed to create EmulatedEglWindowSurface.");
+ return 0;
+ }
+
+ m_windows[handle] = { std::move(window), 0 };
+
+ RenderThreadInfo* info = RenderThreadInfo::get();
+ if (!info->m_glInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "RRenderThreadInfoGl not available.";
+ }
+
+ uint64_t puid = info->m_puid;
+ if (puid) {
+ m_procOwnedEmulatedEglWindowSurfaces[puid].insert(handle);
+ } else { // legacy path to manage window surface lifetime by threads
+ info->m_glInfo->m_windowSet.insert(handle);
+ }
+
+ return handle;
+}
+
+void FrameBuffer::destroyEmulatedEglWindowSurface(HandleType p_surface) {
+ if (m_shuttingDown) {
+ return;
+ }
+ AutoLock mutex(m_lock);
+ destroyEmulatedEglWindowSurfaceLocked(p_surface);
+}
+
+std::vector<HandleType> FrameBuffer::destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface) {
+ std::vector<HandleType> colorBuffersToCleanUp;
+ const auto w = m_windows.find(p_surface);
+ if (w != m_windows.end()) {
+ RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+ if (!m_guestManagedColorBufferLifetime) {
+ if (m_refCountPipeEnabled) {
+ if (decColorBufferRefCountLocked(w->second.second)) {
+ colorBuffersToCleanUp.push_back(w->second.second);
+ }
+ } else {
+ if (closeColorBufferLocked(w->second.second)) {
+ colorBuffersToCleanUp.push_back(w->second.second);
+ }
+ }
+ }
+ m_windows.erase(w);
+ RenderThreadInfo* tinfo = RenderThreadInfo::get();
+ uint64_t puid = tinfo->m_puid;
+ if (puid) {
+ auto ite = m_procOwnedEmulatedEglWindowSurfaces.find(puid);
+ if (ite != m_procOwnedEmulatedEglWindowSurfaces.end()) {
+ ite->second.erase(p_surface);
+ }
+ } else {
+ if (!tinfo->m_glInfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+ tinfo->m_glInfo->m_windowSet.erase(p_surface);
+ }
+ }
+ return colorBuffersToCleanUp;
+}
+
+void FrameBuffer::createEmulatedEglFenceSync(EGLenum type,
+ int destroyWhenSignaled,
+ uint64_t* outSync,
+ uint64_t* outSyncThread) {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "GL/EGL emulation not available.";
+ }
+
+ // TODO(b/233939967): move RenderThreadInfoGl usage to EmulationGl.
+ RenderThreadInfoGl* const info = RenderThreadInfoGl::get();
+ if (!info) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "RenderThreadInfoGl not available.";
+ }
+ if (!info->currContext) {
+ auto fb = FrameBuffer::getFB();
+ uint32_t syncContext;
+ uint32_t syncSurface;
+ createTrivialContext(0, // There is no context to share.
+ &syncContext,
+ &syncSurface);
+ bindContext(syncContext,
+ syncSurface,
+ syncSurface);
+ // This context is then cleaned up when the render thread exits.
+ }
+
+ auto sync = m_emulationGl->createEmulatedEglFenceSync(type, destroyWhenSignaled);
+ if (!sync) {
+ return;
+ }
+
+ if (outSync) {
+ *outSync = (uint64_t)(uintptr_t)sync.release();
+ }
+ if (outSyncThread) {
+ *outSyncThread = reinterpret_cast<uint64_t>(SyncThread::get());
+ }
+}
+
+void FrameBuffer::drainGlRenderThreadResources() {
+ // If we're already exiting then snapshot should not contain
+ // this thread information at all.
+ if (isShuttingDown()) {
+ return;
+ }
+
+ // Release references to the current thread's context/surfaces if any
+ bindContext(0, 0, 0);
+
+ drainGlRenderThreadSurfaces();
+ drainGlRenderThreadContexts();
+
+ if (!s_egl.eglReleaseThread()) {
+ ERR("Error: RenderThread @%p failed to eglReleaseThread()", this);
+ }
+}
+
+void FrameBuffer::drainGlRenderThreadContexts() {
+ if (isShuttingDown()) {
+ return;
+ }
+
+ RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
+ if (!tinfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
+ if (tinfo->m_contextSet.empty()) {
+ return;
+ }
+
+ AutoLock mutex(m_lock);
+ android::base::AutoWriteLock contextLock(m_contextStructureLock);
+ for (const HandleType contextHandle : tinfo->m_contextSet) {
+ m_contexts.erase(contextHandle);
+ }
+ tinfo->m_contextSet.clear();
+}
+
+void FrameBuffer::drainGlRenderThreadSurfaces() {
+ if (isShuttingDown()) {
+ return;
+ }
+
+ RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
+ if (!tinfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
+ if (tinfo->m_windowSet.empty()) {
+ return;
+ }
+
+ std::vector<HandleType> colorBuffersToCleanup;
+
+ AutoLock mutex(m_lock);
+ RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+ for (const HandleType winHandle : tinfo->m_windowSet) {
+ const auto winIt = m_windows.find(winHandle);
+ if (winIt != m_windows.end()) {
+ if (const HandleType oldColorBufferHandle = winIt->second.second) {
+ if (!m_guestManagedColorBufferLifetime) {
+ if (m_refCountPipeEnabled) {
+ if (decColorBufferRefCountLocked(oldColorBufferHandle)) {
+ colorBuffersToCleanup.push_back(oldColorBufferHandle);
+ }
+ } else {
+ if (closeColorBufferLocked(oldColorBufferHandle)) {
+ colorBuffersToCleanup.push_back(oldColorBufferHandle);
+ }
+ }
+ }
+ m_windows.erase(winIt);
+ }
+ }
+ }
+ tinfo->m_windowSet.clear();
+}
+
int FrameBuffer::openColorBuffer(HandleType p_colorbuffer) {
// When guest feature flag RefCountPipe is on, no reference counting is
// needed.
- if (m_refCountPipeEnabled) return 0;
+ if (m_refCountPipeEnabled)
+ return 0;
RenderThreadInfo* tInfo = RenderThreadInfo::get();
@@ -1296,7 +1561,8 @@
m_buffers.erase(it);
}
-bool FrameBuffer::closeColorBufferLocked(HandleType p_colorbuffer, bool forced) {
+bool FrameBuffer::closeColorBufferLocked(HandleType p_colorbuffer,
+ bool forced) {
// When guest feature flag RefCountPipe is on, no reference counting is
// needed.
if (m_refCountPipeEnabled) {
@@ -1466,7 +1732,6 @@
std::vector<HandleType> colorBuffersToCleanup;
{
std::unique_ptr<RecursiveScopedContextBind> bind = nullptr;
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
}
@@ -1496,8 +1761,6 @@
m_procOwnedEmulatedEglWindowSurfaces.erase(procIte);
}
}
-#endif
-
// Clean up color buffers.
// A color buffer needs to be closed as many times as it is opened by
// the guest process, to give the correct reference count.
@@ -1516,7 +1779,6 @@
}
}
-#if GFXSTREAM_ENABLE_HOST_GLES
// Clean up EGLImage handles
if (m_emulationGl) {
auto procImagesIt = m_procOwnedEmulatedEglImages.find(puid);
@@ -1527,10 +1789,7 @@
m_procOwnedEmulatedEglImages.erase(procImagesIt);
}
}
-#endif
}
-
-#if GFXSTREAM_ENABLE_HOST_GLES
// Unbind before cleaning up contexts
// Cleanup render contexts
if (m_emulationGl) {
@@ -1542,7 +1801,6 @@
m_procOwnedEmulatedEglContexts.erase(procIte);
}
}
-#endif
return colorBuffersToCleanup;
}
@@ -1553,6 +1811,77 @@
cbRef->closedTs = 0;
}
+bool FrameBuffer::flushEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface) {
+ AutoLock mutex(m_lock);
+
+ auto it = m_windows.find(p_surface);
+ if (it == m_windows.end()) {
+ ERR("FB::flushEmulatedEglWindowSurfaceColorBuffer: window handle %#x not found",
+ p_surface);
+ // bad surface handle
+ return false;
+ }
+
+ EmulatedEglWindowSurface* surface = it->second.first.get();
+ surface->flushColorBuffer();
+
+ return true;
+}
+
+HandleType FrameBuffer::getEmulatedEglWindowSurfaceColorBufferHandle(HandleType p_surface) {
+ AutoLock mutex(m_lock);
+
+ auto it = m_EmulatedEglWindowSurfaceToColorBuffer.find(p_surface);
+ if (it == m_EmulatedEglWindowSurfaceToColorBuffer.end()) {
+ return 0;
+ }
+
+ return it->second;
+}
+
+bool FrameBuffer::setEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface,
+ HandleType p_colorbuffer) {
+ AutoLock mutex(m_lock);
+
+ EmulatedEglWindowSurfaceMap::iterator w(m_windows.find(p_surface));
+ if (w == m_windows.end()) {
+ // bad surface handle
+ ERR("bad window surface handle %#x", p_surface);
+ return false;
+ }
+
+ {
+ AutoLock colorBufferMapLock(m_colorBufferMapLock);
+ ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
+ if (c == m_colorbuffers.end()) {
+ ERR("bad color buffer handle %#x", p_colorbuffer);
+ // bad colorbuffer handle
+ return false;
+ }
+
+ (*w).second.first->setColorBuffer((*c).second.cb);
+ markOpened(&c->second);
+ if (!m_guestManagedColorBufferLifetime) {
+ c->second.refcount++;
+ }
+ }
+ if (w->second.second) {
+ if (!m_guestManagedColorBufferLifetime) {
+ if (m_refCountPipeEnabled) {
+ decColorBufferRefCountLocked(w->second.second);
+ } else {
+ closeColorBufferLocked(w->second.second);
+ }
+ }
+ }
+
+ (*w).second.second = p_colorbuffer;
+
+ m_EmulatedEglWindowSurfaceToColorBuffer[p_surface] = p_colorbuffer;
+
+ return true;
+}
+
void FrameBuffer::readBuffer(HandleType handle, uint64_t offset, uint64_t size, void* bytes) {
AutoLock mutex(m_lock);
@@ -1591,6 +1920,92 @@
colorBuffer->readYuvToBytes(x, y, width, height, pixels, pixels_size);
}
+void FrameBuffer::createYUVTextures(uint32_t type,
+ uint32_t count,
+ int width,
+ int height,
+ uint32_t* output) {
+ FrameworkFormat format = static_cast<FrameworkFormat>(type);
+ AutoLock mutex(m_lock);
+ RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+ for (uint32_t i = 0; i < count; ++i) {
+ if (format == FRAMEWORK_FORMAT_NV12) {
+ YUVConverter::createYUVGLTex(GL_TEXTURE0, width, height,
+ format, YUVPlane::Y, &output[2 * i]);
+ YUVConverter::createYUVGLTex(GL_TEXTURE1, width / 2, height / 2,
+ format, YUVPlane::UV, &output[2 * i + 1]);
+ } else if (format == FRAMEWORK_FORMAT_YUV_420_888) {
+ YUVConverter::createYUVGLTex(GL_TEXTURE0, width, height,
+ format, YUVPlane::Y, &output[3 * i]);
+ YUVConverter::createYUVGLTex(GL_TEXTURE1, width / 2, height / 2,
+ format, YUVPlane::U, &output[3 * i + 1]);
+ YUVConverter::createYUVGLTex(GL_TEXTURE2, width / 2, height / 2,
+ format, YUVPlane::V, &output[3 * i + 2]);
+ }
+ }
+}
+
+void FrameBuffer::destroyYUVTextures(uint32_t type,
+ uint32_t count,
+ uint32_t* textures) {
+ AutoLock mutex(m_lock);
+ RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+ if (type == FRAMEWORK_FORMAT_NV12) {
+ s_gles2.glDeleteTextures(2 * count, textures);
+ } else if (type == FRAMEWORK_FORMAT_YUV_420_888) {
+ s_gles2.glDeleteTextures(3 * count, textures);
+ }
+}
+
+void FrameBuffer::updateYUVTextures(uint32_t type,
+ uint32_t* textures,
+ void* privData,
+ void* func) {
+ AutoLock mutex(m_lock);
+ RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
+
+ yuv_updater_t updater = (yuv_updater_t)func;
+ uint32_t gtextures[3] = {0, 0, 0};
+
+ if (type == FRAMEWORK_FORMAT_NV12) {
+ gtextures[0] = s_gles2.glGetGlobalTexName(textures[0]);
+ gtextures[1] = s_gles2.glGetGlobalTexName(textures[1]);
+ } else if (type == FRAMEWORK_FORMAT_YUV_420_888) {
+ gtextures[0] = s_gles2.glGetGlobalTexName(textures[0]);
+ gtextures[1] = s_gles2.glGetGlobalTexName(textures[1]);
+ gtextures[2] = s_gles2.glGetGlobalTexName(textures[2]);
+ }
+
+#ifdef __APPLE__
+ EGLContext prevContext = s_egl.eglGetCurrentContext();
+ auto mydisp = EglGlobalInfo::getInstance()->getDisplayFromDisplayType(EGL_DEFAULT_DISPLAY);
+ void* nativecontext = mydisp->getLowLevelContext(prevContext);
+ struct MediaNativeCallerData callerdata;
+ callerdata.ctx = nativecontext;
+ callerdata.converter = nsConvertVideoFrameToNV12Textures;
+ void* pcallerdata = &callerdata;
+#else
+ void* pcallerdata = nullptr;
+#endif
+
+ updater(privData, type, gtextures, pcallerdata);
+}
+
+void FrameBuffer::swapTexturesAndUpdateColorBuffer(uint32_t p_colorbuffer, int x, int y, int width,
+ int height, uint32_t format, uint32_t type,
+ uint32_t texture_type, uint32_t* textures) {
+ {
+ AutoLock mutex(m_lock);
+ ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
+ if (!colorBuffer) {
+ // bad colorbuffer handle
+ return;
+ }
+ colorBuffer->glOpSwapYuvTexturesAndUpdate(
+ format, type, static_cast<FrameworkFormat>(texture_type), textures);
+ }
+}
+
bool FrameBuffer::updateBuffer(HandleType p_buffer, uint64_t offset, uint64_t size, void* bytes) {
AutoLock mutex(m_lock);
@@ -1648,6 +2063,20 @@
return true;
}
+bool FrameBuffer::readColorBufferContents(
+ HandleType p_colorbuffer, size_t* numBytes, void* pixels) {
+
+ AutoLock mutex(m_lock);
+
+ ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
+ if (!colorBuffer) {
+ // bad colorbuffer handle
+ return false;
+ }
+
+ return colorBuffer->glOpReadContents(numBytes, pixels);
+}
+
bool FrameBuffer::getColorBufferInfo(
HandleType p_colorbuffer, int* width, int* height, GLint* internalformat,
FrameworkFormat* frameworkFormat) {
@@ -1684,12 +2113,272 @@
return true;
}
+bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) {
+ AutoLock mutex(m_lock);
+
+ ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
+ if (!colorBuffer) {
+ // bad colorbuffer handle
+ return false;
+ }
+
+ return colorBuffer->glOpBindToTexture();
+}
+
+bool FrameBuffer::bindColorBufferToTexture2(HandleType p_colorbuffer) {
+ // This is only called when using multi window display
+ // It will deadlock when posting from main thread.
+ std::unique_ptr<AutoLock> mutex;
+ if (!postOnlyOnMainThread()) {
+ mutex = std::make_unique<AutoLock>(m_lock);
+ }
+
+ ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
+ if (!colorBuffer) {
+ // bad colorbuffer handle
+ return false;
+ }
+
+ return colorBuffer->glOpBindToTexture2();
+}
+
+bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) {
+ AutoLock mutex(m_lock);
+
+ ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
+ if (!colorBuffer) {
+ // bad colorbuffer handle
+ return false;
+ }
+
+ return colorBuffer->glOpBindToRenderbuffer();
+}
+
+bool FrameBuffer::bindContext(HandleType p_context,
+ HandleType p_drawSurface,
+ HandleType p_readSurface) {
+ if (m_shuttingDown) {
+ return false;
+ }
+
+ AutoLock mutex(m_lock);
+
+ EmulatedEglWindowSurfacePtr draw, read;
+ EmulatedEglContextPtr ctx;
+
+ //
+ // if this is not an unbind operation - make sure all handles are good
+ //
+ if (p_context || p_drawSurface || p_readSurface) {
+ ctx = getContext_locked(p_context);
+ if (!ctx)
+ return false;
+ EmulatedEglWindowSurfaceMap::iterator w(m_windows.find(p_drawSurface));
+ if (w == m_windows.end()) {
+ // bad surface handle
+ return false;
+ }
+ draw = (*w).second.first;
+
+ if (p_readSurface != p_drawSurface) {
+ EmulatedEglWindowSurfaceMap::iterator w(m_windows.find(p_readSurface));
+ if (w == m_windows.end()) {
+ // bad surface handle
+ return false;
+ }
+ read = (*w).second.first;
+ } else {
+ read = draw;
+ }
+ } else {
+ // if unbind operation, sweep color buffers
+ sweepColorBuffersLocked();
+ }
+
+ if (!s_egl.eglMakeCurrent(getDisplay(),
+ draw ? draw->getEGLSurface() : EGL_NO_SURFACE,
+ read ? read->getEGLSurface() : EGL_NO_SURFACE,
+ ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT)) {
+ ERR("eglMakeCurrent failed");
+ return false;
+ }
+
+ //
+ // Bind the surface(s) to the context
+ //
+ RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
+ if (!tinfo) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "Render thread GL not available.";
+ }
+
+ EmulatedEglWindowSurfacePtr bindDraw, bindRead;
+ if (draw.get() == NULL && read.get() == NULL) {
+ // Unbind the current read and draw surfaces from the context
+ bindDraw = tinfo->currDrawSurf;
+ bindRead = tinfo->currReadSurf;
+ } else {
+ bindDraw = draw;
+ bindRead = read;
+ }
+
+ if (bindDraw.get() != NULL && bindRead.get() != NULL) {
+ if (bindDraw.get() != bindRead.get()) {
+ bindDraw->bind(ctx, EmulatedEglWindowSurface::BIND_DRAW);
+ bindRead->bind(ctx, EmulatedEglWindowSurface::BIND_READ);
+ } else {
+ bindDraw->bind(ctx, EmulatedEglWindowSurface::BIND_READDRAW);
+ }
+ }
+
+ //
+ // update thread info with current bound context
+ //
+ tinfo->currContext = ctx;
+ tinfo->currDrawSurf = draw;
+ tinfo->currReadSurf = read;
+ if (ctx) {
+ if (ctx->clientVersion() > GLESApi_CM)
+ tinfo->m_gl2Dec.setContextData(&ctx->decoderContextData());
+ else
+ tinfo->m_glDec.setContextData(&ctx->decoderContextData());
+ } else {
+ tinfo->m_glDec.setContextData(NULL);
+ tinfo->m_gl2Dec.setContextData(NULL);
+ }
+ return true;
+}
+
+EmulatedEglContextPtr FrameBuffer::getContext_locked(HandleType p_context) {
+ return android::base::findOrDefault(m_contexts, p_context);
+}
+
+EmulatedEglWindowSurfacePtr FrameBuffer::getWindowSurface_locked(HandleType p_windowsurface) {
+ return android::base::findOrDefault(m_windows, p_windowsurface).first;
+}
+
+HandleType FrameBuffer::createEmulatedEglImage(HandleType contextHandle,
+ EGLenum target,
+ GLuint buffer) {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "GL/EGL emulation not enabled.";
+ }
+
+ AutoLock mutex(m_lock);
+
+ EmulatedEglContext* context = nullptr;
+ if (contextHandle) {
+ android::base::AutoWriteLock contextLock(m_contextStructureLock);
+
+ auto it = m_contexts.find(contextHandle);
+ if (it == m_contexts.end()) {
+ ERR("Failed to find EmulatedEglContext:%d", contextHandle);
+ return false;
+ }
+
+ context = it->second.get();
+ }
+
+ auto image = m_emulationGl->createEmulatedEglImage(context,
+ target,
+ reinterpret_cast<EGLClientBuffer>(buffer));
+ if (!image) {
+ ERR("Failed to create EmulatedEglImage");
+ return false;
+ }
+
+ HandleType imageHandle = image->getHandle();
+
+ m_images[imageHandle] = std::move(image);
+
+ RenderThreadInfo* tInfo = RenderThreadInfo::get();
+ uint64_t puid = tInfo->m_puid;
+ if (puid) {
+ m_procOwnedEmulatedEglImages[puid].insert(imageHandle);
+ }
+ return imageHandle;
+}
+
+EGLBoolean FrameBuffer::destroyEmulatedEglImage(HandleType imageHandle) {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "GL/EGL emulation not enabled.";
+ }
+
+ AutoLock mutex(m_lock);
+
+ auto imageIt = m_images.find(imageHandle);
+ if (imageIt == m_images.end()) {
+ ERR("Failed to find EmulatedEglImage:%d", imageHandle);
+ return false;
+ }
+ auto& image = imageIt->second;
+
+ EGLBoolean success = image->destroy();
+ m_images.erase(imageIt);
+
+ RenderThreadInfo* tInfo = RenderThreadInfo::get();
+ uint64_t puid = tInfo->m_puid;
+ if (puid) {
+ m_procOwnedEmulatedEglImages[puid].erase(imageHandle);
+ // We don't explicitly call m_procOwnedEmulatedEglImages.erase(puid) when the
+ // size reaches 0, since it could go between zero and one many times in
+ // the lifetime of a process. It will be cleaned up by
+ // cleanupProcGLObjects(puid) when the process is dead.
+ }
+ return success;
+}
+
+void FrameBuffer::createTrivialContext(HandleType shared,
+ HandleType* contextOut,
+ HandleType* surfOut) {
+ assert(contextOut);
+ assert(surfOut);
+
+ *contextOut = createEmulatedEglContext(0, shared, GLESApi_2);
+ // Zero size is formally allowed here, but SwiftShader doesn't like it and
+ // fails.
+ *surfOut = createEmulatedEglWindowSurface(0, 1, 1);
+}
+
+void FrameBuffer::createSharedTrivialContext(EGLContext* contextOut,
+ EGLSurface* surfOut) {
+ assert(contextOut);
+ assert(surfOut);
+
+ const EmulatedEglConfig* config = getConfigs()->get(0 /* p_config */);
+ if (!config) return;
+
+ int maj, min;
+ emugl::getGlesVersion(&maj, &min);
+
+ const EGLint contextAttribs[] = {
+ EGL_CONTEXT_MAJOR_VERSION_KHR, maj,
+ EGL_CONTEXT_MINOR_VERSION_KHR, min,
+ EGL_NONE };
+
+ *contextOut = s_egl.eglCreateContext(
+ getDisplay(), config->getHostEglConfig(), getGlobalEGLContext(), contextAttribs);
+
+ const EGLint pbufAttribs[] = {
+ EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+
+ *surfOut = s_egl.eglCreatePbufferSurface(getDisplay(), config->getHostEglConfig(), pbufAttribs);
+}
+
+void FrameBuffer::destroySharedTrivialContext(EGLContext context,
+ EGLSurface surface) {
+ if (getDisplay() != EGL_NO_DISPLAY) {
+ s_egl.eglDestroyContext(getDisplay(), context);
+ s_egl.eglDestroySurface(getDisplay(), surface);
+ }
+}
+
bool FrameBuffer::post(HandleType p_colorbuffer, bool needLockAndBind) {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_guestUsesAngle) {
flushColorBufferFromGl(p_colorbuffer);
}
-#endif
auto res = postImplSync(p_colorbuffer, needLockAndBind);
if (res) setGuestPostedAFrame();
@@ -1698,11 +2387,9 @@
void FrameBuffer::postWithCallback(HandleType p_colorbuffer, Post::CompletionCallback callback,
bool needLockAndBind) {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_guestUsesAngle) {
flushColorBufferFromGl(p_colorbuffer);
}
-#endif
AsyncResult res = postImpl(p_colorbuffer, callback, needLockAndBind);
if (res.Succeeded()) {
@@ -1717,7 +2404,9 @@
}
}
-bool FrameBuffer::postImplSync(HandleType p_colorbuffer, bool needLockAndBind, bool repaint) {
+bool FrameBuffer::postImplSync(HandleType p_colorbuffer,
+ bool needLockAndBind,
+ bool repaint) {
std::promise<void> promise;
std::future<void> completeFuture = promise.get_future();
auto posted = postImpl(
@@ -1734,16 +2423,16 @@
return posted.Succeeded();
}
-AsyncResult FrameBuffer::postImpl(HandleType p_colorbuffer, Post::CompletionCallback callback,
- bool needLockAndBind, bool repaint) {
+AsyncResult FrameBuffer::postImpl(HandleType p_colorbuffer,
+ Post::CompletionCallback callback,
+ bool needLockAndBind,
+ bool repaint) {
std::unique_ptr<RecursiveScopedContextBind> bind;
if (needLockAndBind) {
m_lock.lock();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
}
-#endif
}
AsyncResult ret = AsyncResult::FAIL_AND_CALLBACK_NOT_SCHEDULED;
@@ -1820,20 +2509,21 @@
if (asyncReadbackSupported()) {
ensureReadbackWorker();
- const auto status = m_readbackWorker->doNextReadback(
- iter.first, cb.get(), iter.second.img, repaint, iter.second.readBgra);
+ const auto status = m_readbackWorker->doNextReadback(iter.first,
+ cb.get(),
+ iter.second.img,
+ repaint,
+ iter.second.readBgra);
if (status == ReadbackWorker::DoNextReadbackResult::OK_READY_FOR_READ) {
doPostCallback(iter.second.img, iter.first);
}
} else {
-#if GFXSTREAM_ENABLE_HOST_GLES
cb->glOpReadback(iter.second.img, iter.second.readBgra);
-#endif
doPostCallback(iter.second.img, iter.first);
}
}
DEC_REFCOUNT_AND_EXIT:
- if (!m_subWin) { // m_subWin is supposed to be false
+ if (!m_subWin) { // m_subWin is supposed to be false
decColorBufferRefCountLocked(p_colorbuffer);
}
@@ -1851,8 +2541,9 @@
ERR("Cannot find post callback function for display %d", displayId);
return;
}
- iter->second.cb(iter->second.context, displayId, iter->second.width, iter->second.height, -1,
- GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char*)pixels);
+ iter->second.cb(iter->second.context, displayId, iter->second.width,
+ iter->second.height, -1, GL_RGBA, GL_UNSIGNED_BYTE,
+ (unsigned char*)pixels);
}
void FrameBuffer::getPixels(void* pixels, uint32_t bytes, uint32_t displayId) {
@@ -1861,8 +2552,8 @@
ERR("Display %d not configured for recording yet", displayId);
return;
}
- std::future<void> completeFuture =
- m_readbackThread.enqueue({ReadbackCmd::GetPixels, displayId, pixels, bytes});
+ std::future<void> completeFuture = m_readbackThread.enqueue(
+ {ReadbackCmd::GetPixels, displayId, pixels, bytes});
completeFuture.wait();
}
@@ -1882,17 +2573,17 @@
}
void FrameBuffer::ensureReadbackWorker() {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (!m_readbackWorker) {
if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "GL/EGL emulation not enabled.";
}
m_readbackWorker = m_emulationGl->getReadbackWorker();
}
-#endif
}
-static void sFrameBuffer_ReadPixelsCallback(void* pixels, uint32_t bytes, uint32_t displayId) {
+static void sFrameBuffer_ReadPixelsCallback(
+ void* pixels, uint32_t bytes, uint32_t displayId) {
FrameBuffer::getFB()->getPixels(pixels, bytes, displayId);
}
@@ -1901,11 +2592,7 @@
}
bool FrameBuffer::asyncReadbackSupported() {
-#if GFXSTREAM_ENABLE_HOST_GLES
return m_emulationGl && m_emulationGl->isAsyncReadbackSupported();
-#else
- return false;
-#endif
}
Renderer::ReadPixelsCallback FrameBuffer::getReadPixelsCallback() {
@@ -1921,7 +2608,8 @@
if (m_displayVk) {
return true;
}
- if (m_lastPostedColorBuffer && sInitialized.load(std::memory_order_relaxed)) {
+ if (m_lastPostedColorBuffer &&
+ sInitialized.load(std::memory_order_relaxed)) {
GL_LOG("Has last posted colorbuffer and is initialized; post.");
return postImplSync(m_lastPostedColorBuffer, needLockAndBind, true);
} else {
@@ -1938,26 +2626,30 @@
// Exclude empty handle lists from saving as they add no value but only
// increase the snapshot size; keep the format compatible with
// android::base::saveCollection() though.
- const int count = std::count_if(
- c.begin(), c.end(),
- [](const typename Collection::value_type& pair) { return !pair.second.empty(); });
+ const int count =
+ std::count_if(c.begin(), c.end(),
+ [](const typename Collection::value_type& pair) {
+ return !pair.second.empty();
+ });
stream->putBe32(count);
for (const auto& pair : c) {
if (pair.second.empty()) {
continue;
}
stream->putBe64(pair.first);
- saveCollection(stream, pair.second, [](Stream* s, HandleType h) { s->putBe32(h); });
+ saveCollection(stream, pair.second,
+ [](Stream* s, HandleType h) { s->putBe32(h); });
}
}
template <class Collection>
static void loadProcOwnedCollection(Stream* stream, Collection* c) {
- loadCollection(stream, c, [](Stream* stream) -> typename Collection::value_type {
+ loadCollection(stream, c,
+ [](Stream* stream) -> typename Collection::value_type {
const int processId = stream->getBe64();
typename Collection::mapped_type handles;
loadCollection(stream, &handles, [](Stream* s) { return s->getBe32(); });
- return {processId, std::move(handles)};
+ return { processId, std::move(handles) };
});
}
@@ -1966,8 +2658,14 @@
int desiredHeight, int desiredRotation, Rect rect) {
AutoLock mutex(m_lock);
uint32_t w, h, cb, screenWidth, screenHeight;
- if (!emugl::get_emugl_multi_display_operations().getMultiDisplay(
- displayId, nullptr, nullptr, &w, &h, nullptr, nullptr, nullptr)) {
+ if (!emugl::get_emugl_multi_display_operations().getMultiDisplay(displayId,
+ nullptr,
+ nullptr,
+ &w,
+ &h,
+ nullptr,
+ nullptr,
+ nullptr)) {
ERR("Screenshot of invalid display %d", displayId);
*width = 0;
*height = 0;
@@ -2007,7 +2705,8 @@
return -1;
}
if ((rect.pos.x < 0 || rect.pos.y < 0) ||
- (desiredWidth < rect.pos.x + rect.size.w || desiredHeight < rect.pos.y + rect.size.h)) {
+ (desiredWidth < rect.pos.x + rect.size.w ||
+ desiredHeight < rect.pos.y + rect.size.h)) {
return -1;
}
}
@@ -2020,8 +2719,8 @@
*height = screenHeight;
}
- int needed =
- useSnipping ? (nChannels * rect.size.w * rect.size.h) : (nChannels * (*width) * (*height));
+ int needed = useSnipping ? (nChannels * rect.size.w * rect.size.h)
+ : (nChannels * (*width) * (*height));
if (*cPixels < needed) {
*cPixels = needed;
@@ -2102,8 +2801,8 @@
bool FrameBuffer::compose(uint32_t bufferSize, void* buffer, bool needPost) {
std::promise<void> promise;
std::future<void> completeFuture = promise.get_future();
- auto composeRes =
- composeWithCallback(bufferSize, buffer, [&](std::shared_future<void> waitForGpu) {
+ auto composeRes = composeWithCallback(
+ bufferSize, buffer, [&](std::shared_future<void> waitForGpu) {
waitForGpu.wait();
promise.set_value();
});
@@ -2142,47 +2841,48 @@
}
AsyncResult FrameBuffer::composeWithCallback(uint32_t bufferSize, void* buffer,
- Post::CompletionCallback callback) {
+ Post::CompletionCallback callback) {
ComposeDevice* p = (ComposeDevice*)buffer;
AutoLock mutex(m_lock);
switch (p->version) {
- case 1: {
- Post composeCmd;
- composeCmd.composeVersion = 1;
- composeCmd.composeBuffer.resize(bufferSize);
- memcpy(composeCmd.composeBuffer.data(), buffer, bufferSize);
- composeCmd.completionCallback = std::make_unique<Post::CompletionCallback>(callback);
- composeCmd.cmd = PostCmd::Compose;
- sendPostWorkerCmd(std::move(composeCmd));
- return AsyncResult::OK_AND_CALLBACK_SCHEDULED;
- }
+ case 1: {
+ Post composeCmd;
+ composeCmd.composeVersion = 1;
+ composeCmd.composeBuffer.resize(bufferSize);
+ memcpy(composeCmd.composeBuffer.data(), buffer, bufferSize);
+ composeCmd.completionCallback = std::make_unique<Post::CompletionCallback>(callback);
+ composeCmd.cmd = PostCmd::Compose;
+ sendPostWorkerCmd(std::move(composeCmd));
+ return AsyncResult::OK_AND_CALLBACK_SCHEDULED;
+ }
- case 2: {
- // support for multi-display
- ComposeDevice_v2* p2 = (ComposeDevice_v2*)buffer;
- if (p2->displayId != 0) {
- mutex.unlock();
- setDisplayColorBuffer(p2->displayId, p2->targetHandle);
- mutex.lock();
- }
- Post composeCmd;
- composeCmd.composeVersion = 2;
- composeCmd.composeBuffer.resize(bufferSize);
- memcpy(composeCmd.composeBuffer.data(), buffer, bufferSize);
- composeCmd.completionCallback = std::make_unique<Post::CompletionCallback>(callback);
- composeCmd.cmd = PostCmd::Compose;
- sendPostWorkerCmd(std::move(composeCmd));
- return AsyncResult::OK_AND_CALLBACK_SCHEDULED;
+ case 2: {
+ // support for multi-display
+ ComposeDevice_v2* p2 = (ComposeDevice_v2*)buffer;
+ if (p2->displayId != 0) {
+ mutex.unlock();
+ setDisplayColorBuffer(p2->displayId, p2->targetHandle);
+ mutex.lock();
}
+ Post composeCmd;
+ composeCmd.composeVersion = 2;
+ composeCmd.composeBuffer.resize(bufferSize);
+ memcpy(composeCmd.composeBuffer.data(), buffer, bufferSize);
+ composeCmd.completionCallback = std::make_unique<Post::CompletionCallback>(callback);
+ composeCmd.cmd = PostCmd::Compose;
+ sendPostWorkerCmd(std::move(composeCmd));
+ return AsyncResult::OK_AND_CALLBACK_SCHEDULED;
+ }
- default:
- ERR("yet to handle composition device version: %d", p->version);
- return AsyncResult::FAIL_AND_CALLBACK_NOT_SCHEDULED;
+ default:
+ ERR("yet to handle composition device version: %d", p->version);
+ return AsyncResult::FAIL_AND_CALLBACK_NOT_SCHEDULED;
}
}
-void FrameBuffer::onSave(Stream* stream, const android::snapshot::ITextureSaverPtr& textureSaver) {
+void FrameBuffer::onSave(Stream* stream,
+ const android::snapshot::ITextureSaverPtr& textureSaver) {
// Things we do not need to snapshot:
// m_eglSurface
// m_eglContext
@@ -2194,7 +2894,6 @@
AutoLock mutex(m_lock);
std::unique_ptr<RecursiveScopedContextBind> bind;
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
// Some snapshot commands try using GL.
bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
@@ -2208,12 +2907,12 @@
// and save all labeled textures and EGLImages.
if (s_egl.eglPreSaveContext && s_egl.eglSaveAllImages) {
for (const auto& ctx : m_contexts) {
- s_egl.eglPreSaveContext(getDisplay(), ctx.second->getEGLContext(), stream);
+ s_egl.eglPreSaveContext(getDisplay(), ctx.second->getEGLContext(),
+ stream);
}
s_egl.eglSaveAllImages(getDisplay(), stream, &textureSaver);
}
}
-#endif
// Don't save subWindow's x/y/w/h here - those are related to the current
// emulator UI state, not guest state that we're saving.
@@ -2243,11 +2942,10 @@
// previous eglPreSaveContext and eglSaveAllImages calls (for texture
// objects).
// TODO: skip reading from GPU even for texture objects.
-#if GFXSTREAM_ENABLE_HOST_GLES
- saveCollection(
- stream, m_contexts,
- [](Stream* s, const EmulatedEglContextMap::value_type& pair) { pair.second->onSave(s); });
-#endif
+ saveCollection(stream, m_contexts,
+ [](Stream* s, const EmulatedEglContextMap::value_type& pair) {
+ pair.second->onSave(s);
+ });
// We don't need to save |m_colorBufferCloseTsMap| here - there's enough
// information to reconstruct it when loading.
@@ -2265,23 +2963,16 @@
});
}
stream->putBe32(m_lastPostedColorBuffer);
-#if GFXSTREAM_ENABLE_HOST_GLES
saveCollection(stream, m_windows,
[](Stream* s, const EmulatedEglWindowSurfaceMap::value_type& pair) {
- pair.second.first->onSave(s);
- s->putBe32(pair.second.second); // Color buffer handle.
- });
-#endif
+ pair.second.first->onSave(s);
+ s->putBe32(pair.second.second); // Color buffer handle.
+ });
-#if GFXSTREAM_ENABLE_HOST_GLES
saveProcOwnedCollection(stream, m_procOwnedEmulatedEglWindowSurfaces);
-#endif
saveProcOwnedCollection(stream, m_procOwnedColorBuffers);
-#if GFXSTREAM_ENABLE_HOST_GLES
saveProcOwnedCollection(stream, m_procOwnedEmulatedEglImages);
saveProcOwnedCollection(stream, m_procOwnedEmulatedEglContexts);
-#endif
-
// TODO(b/309858017): remove if when ready to bump snapshot version
if (feature_is_enabled(kFeature_VulkanSnapshots)) {
stream->putBe64(m_procOwnedResources.size());
@@ -2296,11 +2987,11 @@
vk::VkDecoderGlobalState::get()->save(stream);
}
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
if (s_egl.eglPostSaveContext) {
for (const auto& ctx : m_contexts) {
- s_egl.eglPostSaveContext(getDisplay(), ctx.second->getEGLContext(), stream);
+ s_egl.eglPostSaveContext(getDisplay(), ctx.second->getEGLContext(),
+ stream);
}
// We need to run the post save step for m_eglContext
// to mark their texture handles dirty
@@ -2311,7 +3002,6 @@
EmulatedEglFenceSync::onSave(stream);
}
-#endif
}
bool FrameBuffer::onLoad(Stream* stream,
@@ -2322,7 +3012,6 @@
sweepColorBuffersLocked();
std::unique_ptr<RecursiveScopedContextBind> bind;
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
// Some snapshot commands try using GL.
bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
@@ -2330,27 +3019,21 @@
ERR("Failed to make context current for loading snapshot.");
}
}
-#endif
bool cleanupComplete = false;
{
AutoLock colorBufferMapLock(m_colorBufferMapLock);
- if (m_procOwnedCleanupCallbacks.empty() && m_procOwnedColorBuffers.empty() &&
-#if GFXSTREAM_ENABLE_HOST_GLES
- m_procOwnedEmulatedEglContexts.empty() && m_procOwnedEmulatedEglImages.empty() &&
+ if (m_procOwnedCleanupCallbacks.empty() &&
+ m_procOwnedColorBuffers.empty() &&
+ m_procOwnedEmulatedEglContexts.empty() &&
+ m_procOwnedEmulatedEglImages.empty() &&
m_procOwnedEmulatedEglWindowSurfaces.empty() &&
-#endif
- (
-#if GFXSTREAM_ENABLE_HOST_GLES
- !m_contexts.empty() || !m_windows.empty() ||
-#endif
- m_colorbuffers.size() > m_colorBufferDelayedCloseList.size())) {
+ (!m_contexts.empty() || !m_windows.empty() ||
+ m_colorbuffers.size() > m_colorBufferDelayedCloseList.size())) {
// we are likely on a legacy system image, which does not have
// process owned objects. We need to force cleanup everything
-#if GFXSTREAM_ENABLE_HOST_GLES
m_contexts.clear();
m_windows.clear();
-#endif
m_colorbuffers.clear();
cleanupComplete = true;
}
@@ -2358,34 +3041,30 @@
if (!cleanupComplete) {
std::vector<HandleType> colorBuffersToCleanup;
-#if GFXSTREAM_ENABLE_HOST_GLES
while (m_procOwnedEmulatedEglWindowSurfaces.size()) {
auto cleanupHandles = cleanupProcGLObjects_locked(
- m_procOwnedEmulatedEglWindowSurfaces.begin()->first, true);
- colorBuffersToCleanup.insert(colorBuffersToCleanup.end(), cleanupHandles.begin(),
- cleanupHandles.end());
+ m_procOwnedEmulatedEglWindowSurfaces.begin()->first, true);
+ colorBuffersToCleanup.insert(colorBuffersToCleanup.end(),
+ cleanupHandles.begin(), cleanupHandles.end());
}
-#endif
while (m_procOwnedColorBuffers.size()) {
- auto cleanupHandles =
- cleanupProcGLObjects_locked(m_procOwnedColorBuffers.begin()->first, true);
- colorBuffersToCleanup.insert(colorBuffersToCleanup.end(), cleanupHandles.begin(),
- cleanupHandles.end());
+ auto cleanupHandles = cleanupProcGLObjects_locked(
+ m_procOwnedColorBuffers.begin()->first, true);
+ colorBuffersToCleanup.insert(colorBuffersToCleanup.end(),
+ cleanupHandles.begin(), cleanupHandles.end());
}
-#if GFXSTREAM_ENABLE_HOST_GLES
while (m_procOwnedEmulatedEglImages.size()) {
- auto cleanupHandles =
- cleanupProcGLObjects_locked(m_procOwnedEmulatedEglImages.begin()->first, true);
- colorBuffersToCleanup.insert(colorBuffersToCleanup.end(), cleanupHandles.begin(),
- cleanupHandles.end());
+ auto cleanupHandles = cleanupProcGLObjects_locked(
+ m_procOwnedEmulatedEglImages.begin()->first, true);
+ colorBuffersToCleanup.insert(colorBuffersToCleanup.end(),
+ cleanupHandles.begin(), cleanupHandles.end());
}
while (m_procOwnedEmulatedEglContexts.size()) {
auto cleanupHandles = cleanupProcGLObjects_locked(
- m_procOwnedEmulatedEglContexts.begin()->first, true);
- colorBuffersToCleanup.insert(colorBuffersToCleanup.end(), cleanupHandles.begin(),
- cleanupHandles.end());
+ m_procOwnedEmulatedEglContexts.begin()->first, true);
+ colorBuffersToCleanup.insert(colorBuffersToCleanup.end(),
+ cleanupHandles.begin(), cleanupHandles.end());
}
-#endif
std::vector<std::function<void()>> cleanupCallbacks;
@@ -2413,10 +3092,8 @@
cleanupComplete = true;
}
m_colorBufferDelayedCloseList.clear();
-#if GFXSTREAM_ENABLE_HOST_GLES
assert(m_contexts.empty());
assert(m_windows.empty());
-#endif
{
AutoLock colorBufferMapLock(m_colorBufferMapLock);
if (!m_colorbuffers.empty()) {
@@ -2428,13 +3105,11 @@
#ifdef SNAPSHOT_PROFILE
uint64_t texTime = android::base::getUnixTimeUs();
#endif
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
if (s_egl.eglLoadAllImages) {
s_egl.eglLoadAllImages(getDisplay(), stream, &textureLoader);
}
}
-#endif
#ifdef SNAPSHOT_PROFILE
printf("Texture load time: %lld ms\n",
(long long)(android::base::getUnixTimeUs() - texTime) / 1000);
@@ -2450,7 +3125,7 @@
int idx = static_cast<int>(s->getBe32());
int w = static_cast<int>(s->getBe32());
int h = static_cast<int>(s->getBe32());
- int dpiX = static_cast<int>(s->getBe32());
+ int dpiX = static_cast<int>(s->getBe32());
int dpiY = static_cast<int>(s->getBe32());
return {idx, {w, h, dpiX, dpiY}};
});
@@ -2464,19 +3139,18 @@
m_statsNumFrames = stream->getBe32();
m_statsStartTime = stream->getBe64();
-#if GFXSTREAM_ENABLE_HOST_GLES
- loadCollection(
- stream, &m_contexts, [this](Stream* stream) -> EmulatedEglContextMap::value_type {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
- }
+ loadCollection(stream, &m_contexts,
+ [this](Stream* stream) -> EmulatedEglContextMap::value_type {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "GL/EGL emulation not enabled.";
+ }
- auto context = m_emulationGl->loadEmulatedEglContext(stream);
- auto contextHandle = context ? context->getHndl() : 0;
- return {contextHandle, std::move(context)};
- });
+ auto context = m_emulationGl->loadEmulatedEglContext(stream);
+ auto contextHandle = context ? context->getHndl() : 0;
+ return { contextHandle, std::move(context) };
+ });
assert(!android::base::find(m_contexts, 0));
-#endif
auto now = android::base::getUnixTimeUs();
{
@@ -2500,32 +3174,28 @@
{
AutoLock colorBufferMapLock(m_colorBufferMapLock);
-#if GFXSTREAM_ENABLE_HOST_GLES
- loadCollection(
- stream, &m_windows, [this](Stream* stream) -> EmulatedEglWindowSurfaceMap::value_type {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
- << "GL/EGL emulation not enabled.";
- }
+ loadCollection(stream, &m_windows,
+ [this](Stream* stream) -> EmulatedEglWindowSurfaceMap::value_type {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "GL/EGL emulation not enabled.";
+ }
- auto window =
- m_emulationGl->loadEmulatedEglWindowSurface(stream, m_colorbuffers, m_contexts);
+ auto window = m_emulationGl->loadEmulatedEglWindowSurface(
+ stream,
+ m_colorbuffers,
+ m_contexts);
- HandleType handle = window->getHndl();
- HandleType colorBufferHandle = stream->getBe32();
- return {handle, {std::move(window), colorBufferHandle}};
- });
-#endif
+ HandleType handle = window->getHndl();
+ HandleType colorBufferHandle = stream->getBe32();
+ return { handle, { std::move(window), colorBufferHandle } };
+ });
}
-#if GFXSTREAM_ENABLE_HOST_GLES
loadProcOwnedCollection(stream, &m_procOwnedEmulatedEglWindowSurfaces);
-#endif
loadProcOwnedCollection(stream, &m_procOwnedColorBuffers);
-#if GFXSTREAM_ENABLE_HOST_GLES
loadProcOwnedCollection(stream, &m_procOwnedEmulatedEglImages);
loadProcOwnedCollection(stream, &m_procOwnedEmulatedEglContexts);
-#endif
// TODO(b/309858017): remove if when ready to bump snapshot version
if (feature_is_enabled(kFeature_VulkanSnapshots)) {
size_t resourceCount = stream->getBe64();
@@ -2538,7 +3208,6 @@
}
}
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
if (s_egl.eglPostLoadAllImages) {
s_egl.eglPostLoadAllImages(getDisplay(), stream);
@@ -2546,11 +3215,9 @@
}
registerTriggerWait();
-#endif
{
std::unique_ptr<RecursiveScopedContextBind> bind;
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
// Some snapshot commands try using GL.
bind = std::make_unique<RecursiveScopedContextBind>(getPbufferSurfaceContextHelper());
@@ -2558,7 +3225,6 @@
ERR("Failed to make context current for loading snapshot.");
}
}
-#endif
AutoLock colorBufferMapLock(m_colorBufferMapLock);
for (auto& it : m_colorbuffers) {
@@ -2578,26 +3244,36 @@
repost(false);
-#if GFXSTREAM_ENABLE_HOST_GLES
if (m_emulationGl) {
EmulatedEglFenceSync::onLoad(stream);
}
-#endif
return true;
// TODO: restore memory management
}
-void FrameBuffer::lock() { m_lock.lock(); }
+void FrameBuffer::lock() {
+ m_lock.lock();
+}
-void FrameBuffer::unlock() { m_lock.unlock(); }
+void FrameBuffer::unlock() {
+ m_lock.unlock();
+}
+
+GLESDispatchMaxVersion FrameBuffer::getMaxGLESVersion() {
+ if (!m_emulationGl) {
+ return GLES_DISPATCH_MAX_VERSION_2;
+ }
+ return m_emulationGl->getGlesMaxDispatchVersion();
+}
ColorBufferPtr FrameBuffer::findColorBuffer(HandleType p_colorbuffer) {
AutoLock colorBufferMapLock(m_colorBufferMapLock);
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
if (c == m_colorbuffers.end()) {
return nullptr;
- } else {
+ }
+ else {
return c->second.cb;
}
}
@@ -2645,7 +3321,7 @@
return i->second.get();
}
-int FrameBuffer::createDisplay(uint32_t* displayId) {
+int FrameBuffer::createDisplay(uint32_t *displayId) {
return emugl::get_emugl_multi_display_operations().createDisplay(displayId);
}
@@ -2658,28 +3334,37 @@
}
int FrameBuffer::setDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer) {
- return emugl::get_emugl_multi_display_operations().setDisplayColorBuffer(displayId,
- colorBuffer);
+ return emugl::get_emugl_multi_display_operations().
+ setDisplayColorBuffer(displayId, colorBuffer);
}
int FrameBuffer::getDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer) {
- return emugl::get_emugl_multi_display_operations().getDisplayColorBuffer(displayId,
- colorBuffer);
+ return emugl::get_emugl_multi_display_operations().
+ getDisplayColorBuffer(displayId, colorBuffer);
}
int FrameBuffer::getColorBufferDisplay(uint32_t colorBuffer, uint32_t* displayId) {
- return emugl::get_emugl_multi_display_operations().getColorBufferDisplay(colorBuffer,
- displayId);
+ return emugl::get_emugl_multi_display_operations().
+ getColorBufferDisplay(colorBuffer, displayId);
}
-int FrameBuffer::getDisplayPose(uint32_t displayId, int32_t* x, int32_t* y, uint32_t* w,
+int FrameBuffer::getDisplayPose(uint32_t displayId,
+ int32_t* x,
+ int32_t* y,
+ uint32_t* w,
uint32_t* h) {
- return emugl::get_emugl_multi_display_operations().getDisplayPose(displayId, x, y, w, h);
+ return emugl::get_emugl_multi_display_operations().
+ getDisplayPose(displayId, x, y, w, h);
}
-int FrameBuffer::setDisplayPose(uint32_t displayId, int32_t x, int32_t y, uint32_t w, uint32_t h,
+int FrameBuffer::setDisplayPose(uint32_t displayId,
+ int32_t x,
+ int32_t y,
+ uint32_t w,
+ uint32_t h,
uint32_t dpi) {
- return emugl::get_emugl_multi_display_operations().setDisplayPose(displayId, x, y, w, h, dpi);
+ return emugl::get_emugl_multi_display_operations().
+ setDisplayPose(displayId, x, y, w, h, dpi);
}
void FrameBuffer::sweepColorBuffersLocked() {
@@ -2703,25 +3388,44 @@
return scheduledFuture;
}
-void FrameBuffer::waitForGpuVulkan(uint64_t deviceHandle, uint64_t fenceHandle) {
- (void)deviceHandle;
- if (!m_emulationGl) {
- // Guest ANGLE should always use the asyncWaitForGpuVulkanWithCb call. EmulatedEglFenceSync
- // is a wrapper over EGLSyncKHR and should not be used for pure Vulkan environment.
+void FrameBuffer::waitForGpu(uint64_t eglsync) {
+ EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(eglsync);
+
+ if (!fenceSync) {
+ ERR("err: fence sync 0x%llx not found", (unsigned long long)eglsync);
return;
}
-#if GFXSTREAM_ENABLE_HOST_GLES
+ SyncThread::get()->triggerBlockedWaitNoTimeline(fenceSync);
+}
+
+void FrameBuffer::waitForGpuVulkan(uint64_t deviceHandle, uint64_t fenceHandle) {
+ (void)deviceHandle;
+ if (!m_emulationGl) {
+ // Guest ANGLE should always use the asyncWaitForGpuVulkanWithCb call. EmulatedEglFenceSync is a
+ // wrapper over EGLSyncKHR and should not be used for pure Vulkan environment.
+ return;
+ }
+
// Note: this will always be nullptr.
EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(fenceHandle);
// Note: This will always signal right away.
SyncThread::get()->triggerBlockedWaitNoTimeline(fenceSync);
-#endif
}
-void FrameBuffer::asyncWaitForGpuVulkanWithCb(uint64_t deviceHandle, uint64_t fenceHandle,
- FenceCompletionCallback cb) {
+void FrameBuffer::asyncWaitForGpuWithCb(uint64_t eglsync, FenceCompletionCallback cb) {
+ EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(eglsync);
+
+ if (!fenceSync) {
+ ERR("err: fence sync 0x%llx not found", (unsigned long long)eglsync);
+ return;
+ }
+
+ SyncThread::get()->triggerWaitWithCompletionCallback(fenceSync, std::move(cb));
+}
+
+void FrameBuffer::asyncWaitForGpuVulkanWithCb(uint64_t deviceHandle, uint64_t fenceHandle, FenceCompletionCallback cb) {
(void)deviceHandle;
SyncThread::get()->triggerWaitVkWithCompletionCallback((VkFence)fenceHandle, std::move(cb));
}
@@ -2733,9 +3437,7 @@
void FrameBuffer::waitForGpuVulkanQsri(uint64_t image) {
(void)image;
// Signal immediately, because this was a sync wait and it's vulkan.
-#if GFXSTREAM_ENABLE_HOST_GLES
SyncThread::get()->triggerBlockedWaitNoTimeline(nullptr);
-#endif
}
void FrameBuffer::setGuestManagedColorBufferLifetime(bool guestManaged) {
@@ -2759,12 +3461,11 @@
bool preserveContent = (info & RESOURCE_USE_PRESERVE);
switch (type) {
-#if GFXSTREAM_ENABLE_HOST_GLES
case RESOURCE_TYPE_EGL_NATIVE_PIXMAP:
return colorBuffer->glOpImportEglNativePixmap(resource, preserveContent);
case RESOURCE_TYPE_EGL_IMAGE:
return colorBuffer->glOpImportEglImage(resource, preserveContent);
-#endif
+
// Note: Additional non-EGL resource-types can be added here, and will
// be propagated through color-buffer import functionality
case RESOURCE_TYPE_VK_EXT_MEMORY_HANDLE:
@@ -2777,6 +3478,51 @@
return true;
}
+void* FrameBuffer::platformCreateSharedEglContext(void) {
+ AutoLock lock(m_lock);
+
+ EGLContext context = 0;
+ EGLSurface surface = 0;
+ createSharedTrivialContext(&context, &surface);
+
+ void* underlyingContext = s_egl.eglGetNativeContextANDROID(getDisplay(), context);
+ if (!underlyingContext) {
+ ERR("Error: Underlying egl backend could not produce a native EGL context.");
+ return nullptr;
+ }
+
+ m_platformEglContexts[underlyingContext] = { context, surface };
+
+#if defined(__QNX__)
+ EGLDisplay currDisplay = eglGetCurrentDisplay();
+ EGLSurface currRead = eglGetCurrentSurface(EGL_READ);
+ EGLSurface currDraw = eglGetCurrentSurface(EGL_DRAW);
+ EGLSurface currContext = eglGetCurrentContext();
+ // Make this context current to ensure thread-state is initialized
+ s_egl.eglMakeCurrent(getDisplay(), surface, surface, context);
+ // Revert back to original state
+ s_egl.eglMakeCurrent(currDisplay, currRead, currDraw, currContext);
+#endif
+
+ return underlyingContext;
+}
+
+bool FrameBuffer::platformDestroySharedEglContext(void* underlyingContext) {
+ AutoLock lock(m_lock);
+
+ auto it = m_platformEglContexts.find(underlyingContext);
+ if (it == m_platformEglContexts.end()) {
+ ERR("Error: Could not find underlying egl context %p (perhaps already destroyed?)", underlyingContext);
+ return false;
+ }
+
+ destroySharedTrivialContext(it->second.context, it->second.surface);
+
+ m_platformEglContexts.erase(it);
+
+ return true;
+}
+
std::unique_ptr<BorrowedImageInfo> FrameBuffer::borrowColorBufferForComposition(
uint32_t colorBufferHandle, bool colorBufferIsTarget) {
ColorBufferPtr colorBufferPtr = findColorBuffer(colorBufferHandle);
@@ -2788,9 +3534,7 @@
if (m_useVulkanComposition) {
invalidateColorBufferForVk(colorBufferHandle);
} else {
-#if GFXSTREAM_ENABLE_HOST_GLES
invalidateColorBufferForGl(colorBufferHandle);
-#endif
}
const auto api = m_useVulkanComposition ? ColorBuffer::UsedApi::kVk : ColorBuffer::UsedApi::kGl;
@@ -2808,17 +3552,96 @@
if (m_useVulkanComposition) {
invalidateColorBufferForVk(colorBufferHandle);
} else {
-#if GFXSTREAM_ENABLE_HOST_GLES
invalidateColorBufferForGl(colorBufferHandle);
-#else
- ERR("Failed to invalidate ColorBuffer:%d", colorBufferHandle);
-#endif
}
const auto api = m_useVulkanComposition ? ColorBuffer::UsedApi::kVk : ColorBuffer::UsedApi::kGl;
return colorBufferPtr->borrowForDisplay(api);
}
+EmulationGl& FrameBuffer::getEmulationGl() {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "GL/EGL emulation not enabled.";
+ }
+ return *m_emulationGl;
+}
+
+EGLDisplay FrameBuffer::getDisplay() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+ return m_emulationGl->mEglDisplay;
+}
+
+EGLSurface FrameBuffer::getWindowSurface() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+
+ if (!m_emulationGl->mWindowSurface) {
+ return EGL_NO_SURFACE;
+ }
+
+ const auto* displaySurfaceGl =
+ reinterpret_cast<const DisplaySurfaceGl*>(
+ m_emulationGl->mWindowSurface->getImpl());
+
+ return displaySurfaceGl->getSurface();
+}
+
+EGLContext FrameBuffer::getContext() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+ return m_emulationGl->mEglContext;
+}
+
+EGLContext FrameBuffer::getConfig() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+ return m_emulationGl->mEglConfig;
+}
+
+EGLContext FrameBuffer::getGlobalEGLContext() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+
+ if (!m_emulationGl->mPbufferSurface) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "FrameBuffer pbuffer surface not available.";
+ }
+
+ const auto* displaySurfaceGl =
+ reinterpret_cast<const DisplaySurfaceGl*>(
+ m_emulationGl->mPbufferSurface->getImpl());
+
+ return displaySurfaceGl->getContextForShareContext();
+}
+
+ContextHelper* FrameBuffer::getPbufferSurfaceContextHelper() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+ if (!m_emulationGl->mPbufferSurface) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation pbuffer surface not available.";
+ }
+ const auto* displaySurfaceGl =
+ reinterpret_cast<const DisplaySurfaceGl*>(
+ m_emulationGl->mPbufferSurface->getImpl());
+
+ return displaySurfaceGl->getContextHelper();
+}
+
void FrameBuffer::logVulkanOutOfMemory(VkResult result, const char* function, int line,
std::optional<uint64_t> allocationSize) {
m_logger->logMetricEvent(MetricEventVulkanOutOfMemory{
@@ -2829,6 +3652,42 @@
});
}
+const EmulatedEglConfigList* FrameBuffer::getConfigs() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+
+ return &m_emulationGl->getEmulationEglConfigs();
+}
+
+TextureDraw* FrameBuffer::getTextureDraw() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+
+ return m_emulationGl->mTextureDraw.get();
+}
+
+bool FrameBuffer::isFastBlitSupported() const {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+
+ return m_emulationGl->isFastBlitSupported();
+}
+
+void FrameBuffer::disableFastBlitForTesting() {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+
+ m_emulationGl->disableFastBlitForTesting();
+}
+
void FrameBuffer::setVsyncHz(int vsyncHz) {
const uint64_t kOneSecondNs = 1000000000ULL;
m_vsyncHz = vsyncHz;
@@ -2847,7 +3706,8 @@
m_vsyncThread->schedule(task);
}
-void FrameBuffer::setDisplayConfigs(int configId, int w, int h, int dpiX, int dpiY) {
+void FrameBuffer::setDisplayConfigs(int configId, int w, int h,
+ int dpiX, int dpiY) {
AutoLock mutex(m_lock);
mDisplayConfigs[configId] = {w, h, dpiX, dpiY};
INFO("setDisplayConfigs w %d h %d dpiX %d dpiY %d", w, h, dpiX, dpiY);
@@ -2901,6 +3761,15 @@
return mDisplayActiveConfigId >= 0 ? mDisplayActiveConfigId : -1;
}
+bool FrameBuffer::flushColorBufferFromGl(HandleType colorBufferHandle) {
+ auto colorBuffer = findColorBuffer(colorBufferHandle);
+ if (!colorBuffer) {
+ ERR("Failed to find ColorBuffer:%d", colorBufferHandle);
+ return false;
+ }
+ return colorBuffer->flushFromGl();
+}
+
bool FrameBuffer::flushColorBufferFromVk(HandleType colorBufferHandle) {
auto colorBuffer = findColorBuffer(colorBufferHandle);
if (!colorBuffer) {
@@ -2910,8 +3779,7 @@
return colorBuffer->flushFromVk();
}
-bool FrameBuffer::flushColorBufferFromVkBytes(HandleType colorBufferHandle, const void* bytes,
- size_t bytesSize) {
+bool FrameBuffer::flushColorBufferFromVkBytes(HandleType colorBufferHandle, const void* bytes, size_t bytesSize) {
AutoLock mutex(m_lock);
auto colorBuffer = findColorBuffer(colorBufferHandle);
@@ -2922,6 +3790,15 @@
return colorBuffer->flushFromVkBytes(bytes, bytesSize);
}
+bool FrameBuffer::invalidateColorBufferForGl(HandleType colorBufferHandle) {
+ auto colorBuffer = findColorBuffer(colorBufferHandle);
+ if (!colorBuffer) {
+ ERR("Failed to find ColorBuffer:%d", colorBufferHandle);
+ return false;
+ }
+ return colorBuffer->invalidateForGl();
+}
+
bool FrameBuffer::invalidateColorBufferForVk(HandleType colorBufferHandle) {
// It reads contents from GL, which requires a context lock.
// Also we should not do this in PostWorkerGl, otherwise it will deadlock.
@@ -2937,900 +3814,22 @@
return colorBuffer->invalidateForVk();
}
-#if GFXSTREAM_ENABLE_HOST_GLES
-HandleType FrameBuffer::getEmulatedEglWindowSurfaceColorBufferHandle(HandleType p_surface) {
- AutoLock mutex(m_lock);
-
- auto it = m_EmulatedEglWindowSurfaceToColorBuffer.find(p_surface);
- if (it == m_EmulatedEglWindowSurfaceToColorBuffer.end()) {
- return 0;
- }
-
- return it->second;
-}
-
-void FrameBuffer::createTrivialContext(HandleType shared, HandleType* contextOut,
- HandleType* surfOut) {
- assert(contextOut);
- assert(surfOut);
-
- *contextOut = createEmulatedEglContext(0, shared, GLESApi_2);
- // Zero size is formally allowed here, but SwiftShader doesn't like it and
- // fails.
- *surfOut = createEmulatedEglWindowSurface(0, 1, 1);
-}
-
-void FrameBuffer::createSharedTrivialContext(EGLContext* contextOut, EGLSurface* surfOut) {
- assert(contextOut);
- assert(surfOut);
-
- const EmulatedEglConfig* config = getConfigs()->get(0 /* p_config */);
- if (!config) return;
-
- int maj, min;
- emugl::getGlesVersion(&maj, &min);
-
- const EGLint contextAttribs[] = {EGL_CONTEXT_MAJOR_VERSION_KHR, maj,
- EGL_CONTEXT_MINOR_VERSION_KHR, min, EGL_NONE};
-
- *contextOut = s_egl.eglCreateContext(getDisplay(), config->getHostEglConfig(),
- getGlobalEGLContext(), contextAttribs);
-
- const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
-
- *surfOut = s_egl.eglCreatePbufferSurface(getDisplay(), config->getHostEglConfig(), pbufAttribs);
-}
-
-void FrameBuffer::destroySharedTrivialContext(EGLContext context, EGLSurface surface) {
- if (getDisplay() != EGL_NO_DISPLAY) {
- s_egl.eglDestroyContext(getDisplay(), context);
- s_egl.eglDestroySurface(getDisplay(), surface);
- }
-}
-
-const EmulatedEglConfigList* FrameBuffer::getConfigs() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
-
- return &m_emulationGl->getEmulationEglConfigs();
-}
-
-bool FrameBuffer::setEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface,
- HandleType p_colorbuffer) {
- AutoLock mutex(m_lock);
-
- EmulatedEglWindowSurfaceMap::iterator w(m_windows.find(p_surface));
- if (w == m_windows.end()) {
- // bad surface handle
- ERR("bad window surface handle %#x", p_surface);
- return false;
- }
-
- {
- AutoLock colorBufferMapLock(m_colorBufferMapLock);
- ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
- if (c == m_colorbuffers.end()) {
- ERR("bad color buffer handle %#x", p_colorbuffer);
- // bad colorbuffer handle
- return false;
- }
-
- (*w).second.first->setColorBuffer((*c).second.cb);
- markOpened(&c->second);
- if (!m_guestManagedColorBufferLifetime) {
- c->second.refcount++;
- }
- }
- if (w->second.second) {
- if (!m_guestManagedColorBufferLifetime) {
- if (m_refCountPipeEnabled) {
- decColorBufferRefCountLocked(w->second.second);
- } else {
- closeColorBufferLocked(w->second.second);
- }
- }
- }
-
- (*w).second.second = p_colorbuffer;
-
- m_EmulatedEglWindowSurfaceToColorBuffer[p_surface] = p_colorbuffer;
-
- return true;
-}
-
-HandleType FrameBuffer::createEmulatedEglContext(int config, HandleType shareContextHandle,
- GLESApi version) {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation unavailable.";
- }
-
- AutoLock mutex(m_lock);
- android::base::AutoWriteLock contextLock(m_contextStructureLock);
- // Hold the ColorBuffer map lock so that the new handle won't collide with a ColorBuffer handle.
- AutoLock colorBufferMapLock(m_colorBufferMapLock);
-
- EmulatedEglContextPtr shareContext = nullptr;
- if (shareContextHandle != 0) {
- auto shareContextIt = m_contexts.find(shareContextHandle);
- if (shareContextIt == m_contexts.end()) {
- ERR("Failed to find share EmulatedEglContext:%d", shareContextHandle);
- return 0;
- }
- shareContext = shareContextIt->second;
- }
-
- HandleType contextHandle = genHandle_locked();
- auto context =
- m_emulationGl->createEmulatedEglContext(config, shareContext.get(), version, contextHandle);
- if (!context) {
- ERR("Failed to create EmulatedEglContext.");
- return 0;
- }
-
- m_contexts[contextHandle] = std::move(context);
-
- RenderThreadInfo* tinfo = RenderThreadInfo::get();
- uint64_t puid = tinfo->m_puid;
- // The new emulator manages render contexts per guest process.
- // Fall back to per-thread management if the system image does not
- // support it.
- if (puid) {
- m_procOwnedEmulatedEglContexts[puid].insert(contextHandle);
- } else { // legacy path to manage context lifetime by threads
- if (!tinfo->m_glInfo) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
- }
- tinfo->m_glInfo->m_contextSet.insert(contextHandle);
- }
-
- return contextHandle;
-}
-
-void FrameBuffer::destroyEmulatedEglContext(HandleType contextHandle) {
- AutoLock mutex(m_lock);
- sweepColorBuffersLocked();
-
- android::base::AutoWriteLock contextLock(m_contextStructureLock);
- m_contexts.erase(contextHandle);
- RenderThreadInfo* tinfo = RenderThreadInfo::get();
- uint64_t puid = tinfo->m_puid;
- // The new emulator manages render contexts per guest process.
- // Fall back to per-thread management if the system image does not
- // support it.
- if (puid) {
- auto it = m_procOwnedEmulatedEglContexts.find(puid);
- if (it != m_procOwnedEmulatedEglContexts.end()) {
- it->second.erase(contextHandle);
- }
- } else {
- if (!tinfo->m_glInfo) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
- }
- tinfo->m_glInfo->m_contextSet.erase(contextHandle);
- }
-}
-
-HandleType FrameBuffer::createEmulatedEglWindowSurface(int p_config, int p_width, int p_height) {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation unavailable.";
- }
-
- AutoLock mutex(m_lock);
- // Hold the ColorBuffer map lock so that the new handle won't collide with a ColorBuffer handle.
- AutoLock colorBufferMapLock(m_colorBufferMapLock);
-
- HandleType handle = genHandle_locked();
-
- auto window =
- m_emulationGl->createEmulatedEglWindowSurface(p_config, p_width, p_height, handle);
- if (!window) {
- ERR("Failed to create EmulatedEglWindowSurface.");
- return 0;
- }
-
- m_windows[handle] = {std::move(window), 0};
-
- RenderThreadInfo* info = RenderThreadInfo::get();
- if (!info->m_glInfo) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "RRenderThreadInfoGl not available.";
- }
-
- uint64_t puid = info->m_puid;
- if (puid) {
- m_procOwnedEmulatedEglWindowSurfaces[puid].insert(handle);
- } else { // legacy path to manage window surface lifetime by threads
- info->m_glInfo->m_windowSet.insert(handle);
- }
-
- return handle;
-}
-
-void FrameBuffer::destroyEmulatedEglWindowSurface(HandleType p_surface) {
- if (m_shuttingDown) {
- return;
- }
- AutoLock mutex(m_lock);
- destroyEmulatedEglWindowSurfaceLocked(p_surface);
-}
-
-std::vector<HandleType> FrameBuffer::destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface) {
- std::vector<HandleType> colorBuffersToCleanUp;
- const auto w = m_windows.find(p_surface);
- if (w != m_windows.end()) {
- RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
- if (!m_guestManagedColorBufferLifetime) {
- if (m_refCountPipeEnabled) {
- if (decColorBufferRefCountLocked(w->second.second)) {
- colorBuffersToCleanUp.push_back(w->second.second);
- }
- } else {
- if (closeColorBufferLocked(w->second.second)) {
- colorBuffersToCleanUp.push_back(w->second.second);
- }
- }
- }
- m_windows.erase(w);
- RenderThreadInfo* tinfo = RenderThreadInfo::get();
- uint64_t puid = tinfo->m_puid;
- if (puid) {
- auto ite = m_procOwnedEmulatedEglWindowSurfaces.find(puid);
- if (ite != m_procOwnedEmulatedEglWindowSurfaces.end()) {
- ite->second.erase(p_surface);
- }
- } else {
- if (!tinfo->m_glInfo) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
- << "Render thread GL not available.";
- }
- tinfo->m_glInfo->m_windowSet.erase(p_surface);
- }
- }
- return colorBuffersToCleanUp;
-}
-
-void FrameBuffer::createEmulatedEglFenceSync(EGLenum type, int destroyWhenSignaled,
- uint64_t* outSync, uint64_t* outSyncThread) {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not available.";
- }
-
- // TODO(b/233939967): move RenderThreadInfoGl usage to EmulationGl.
- RenderThreadInfoGl* const info = RenderThreadInfoGl::get();
- if (!info) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "RenderThreadInfoGl not available.";
- }
- if (!info->currContext) {
- auto fb = FrameBuffer::getFB();
- uint32_t syncContext;
- uint32_t syncSurface;
- createTrivialContext(0, // There is no context to share.
- &syncContext, &syncSurface);
- bindContext(syncContext, syncSurface, syncSurface);
- // This context is then cleaned up when the render thread exits.
- }
-
- auto sync = m_emulationGl->createEmulatedEglFenceSync(type, destroyWhenSignaled);
- if (!sync) {
- return;
- }
-
- if (outSync) {
- *outSync = (uint64_t)(uintptr_t)sync.release();
- }
- if (outSyncThread) {
- *outSyncThread = reinterpret_cast<uint64_t>(SyncThread::get());
- }
-}
-
-void FrameBuffer::drainGlRenderThreadResources() {
- // If we're already exiting then snapshot should not contain
- // this thread information at all.
- if (isShuttingDown()) {
- return;
- }
-
- // Release references to the current thread's context/surfaces if any
- bindContext(0, 0, 0);
-
- drainGlRenderThreadSurfaces();
- drainGlRenderThreadContexts();
-
- if (!s_egl.eglReleaseThread()) {
- ERR("Error: RenderThread @%p failed to eglReleaseThread()", this);
- }
-}
-
-void FrameBuffer::drainGlRenderThreadContexts() {
- if (isShuttingDown()) {
- return;
- }
-
- RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
- if (!tinfo) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
- }
-
- if (tinfo->m_contextSet.empty()) {
- return;
- }
-
- AutoLock mutex(m_lock);
- android::base::AutoWriteLock contextLock(m_contextStructureLock);
- for (const HandleType contextHandle : tinfo->m_contextSet) {
- m_contexts.erase(contextHandle);
- }
- tinfo->m_contextSet.clear();
-}
-
-void FrameBuffer::drainGlRenderThreadSurfaces() {
- if (isShuttingDown()) {
- return;
- }
-
- RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
- if (!tinfo) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
- }
-
- if (tinfo->m_windowSet.empty()) {
- return;
- }
-
- std::vector<HandleType> colorBuffersToCleanup;
-
- AutoLock mutex(m_lock);
- RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
- for (const HandleType winHandle : tinfo->m_windowSet) {
- const auto winIt = m_windows.find(winHandle);
- if (winIt != m_windows.end()) {
- if (const HandleType oldColorBufferHandle = winIt->second.second) {
- if (!m_guestManagedColorBufferLifetime) {
- if (m_refCountPipeEnabled) {
- if (decColorBufferRefCountLocked(oldColorBufferHandle)) {
- colorBuffersToCleanup.push_back(oldColorBufferHandle);
- }
- } else {
- if (closeColorBufferLocked(oldColorBufferHandle)) {
- colorBuffersToCleanup.push_back(oldColorBufferHandle);
- }
- }
- }
- m_windows.erase(winIt);
- }
- }
- }
- tinfo->m_windowSet.clear();
-}
-
-EmulationGl& FrameBuffer::getEmulationGl() {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
- }
- return *m_emulationGl;
-}
-
-EGLDisplay FrameBuffer::getDisplay() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
- return m_emulationGl->mEglDisplay;
-}
-
-EGLSurface FrameBuffer::getWindowSurface() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
-
- if (!m_emulationGl->mWindowSurface) {
- return EGL_NO_SURFACE;
- }
-
- const auto* displaySurfaceGl =
- reinterpret_cast<const DisplaySurfaceGl*>(m_emulationGl->mWindowSurface->getImpl());
-
- return displaySurfaceGl->getSurface();
-}
-
-EGLContext FrameBuffer::getContext() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
- return m_emulationGl->mEglContext;
-}
-
-EGLContext FrameBuffer::getConfig() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
- return m_emulationGl->mEglConfig;
-}
-
-EGLContext FrameBuffer::getGlobalEGLContext() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
-
- if (!m_emulationGl->mPbufferSurface) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
- << "FrameBuffer pbuffer surface not available.";
- }
-
- const auto* displaySurfaceGl =
- reinterpret_cast<const DisplaySurfaceGl*>(m_emulationGl->mPbufferSurface->getImpl());
-
- return displaySurfaceGl->getContextForShareContext();
-}
-
-EmulatedEglContextPtr FrameBuffer::getContext_locked(HandleType p_context) {
- return android::base::findOrDefault(m_contexts, p_context);
-}
-
-EmulatedEglWindowSurfacePtr FrameBuffer::getWindowSurface_locked(HandleType p_windowsurface) {
- return android::base::findOrDefault(m_windows, p_windowsurface).first;
-}
-
-TextureDraw* FrameBuffer::getTextureDraw() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
-
- return m_emulationGl->mTextureDraw.get();
-}
-
-bool FrameBuffer::isFastBlitSupported() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
-
- return m_emulationGl->isFastBlitSupported();
-}
-
-void FrameBuffer::disableFastBlitForTesting() {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
-
- m_emulationGl->disableFastBlitForTesting();
-}
-
-HandleType FrameBuffer::createEmulatedEglImage(HandleType contextHandle, EGLenum target,
- GLuint buffer) {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
- }
-
- AutoLock mutex(m_lock);
-
- EmulatedEglContext* context = nullptr;
- if (contextHandle) {
- android::base::AutoWriteLock contextLock(m_contextStructureLock);
-
- auto it = m_contexts.find(contextHandle);
- if (it == m_contexts.end()) {
- ERR("Failed to find EmulatedEglContext:%d", contextHandle);
- return false;
- }
-
- context = it->second.get();
- }
-
- auto image = m_emulationGl->createEmulatedEglImage(context, target,
- reinterpret_cast<EGLClientBuffer>(buffer));
- if (!image) {
- ERR("Failed to create EmulatedEglImage");
- return false;
- }
-
- HandleType imageHandle = image->getHandle();
-
- m_images[imageHandle] = std::move(image);
-
- RenderThreadInfo* tInfo = RenderThreadInfo::get();
- uint64_t puid = tInfo->m_puid;
- if (puid) {
- m_procOwnedEmulatedEglImages[puid].insert(imageHandle);
- }
- return imageHandle;
-}
-
-EGLBoolean FrameBuffer::destroyEmulatedEglImage(HandleType imageHandle) {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "GL/EGL emulation not enabled.";
- }
-
- AutoLock mutex(m_lock);
-
- auto imageIt = m_images.find(imageHandle);
- if (imageIt == m_images.end()) {
- ERR("Failed to find EmulatedEglImage:%d", imageHandle);
- return false;
- }
- auto& image = imageIt->second;
-
- EGLBoolean success = image->destroy();
- m_images.erase(imageIt);
-
- RenderThreadInfo* tInfo = RenderThreadInfo::get();
- uint64_t puid = tInfo->m_puid;
- if (puid) {
- m_procOwnedEmulatedEglImages[puid].erase(imageHandle);
- // We don't explicitly call m_procOwnedEmulatedEglImages.erase(puid) when the
- // size reaches 0, since it could go between zero and one many times in
- // the lifetime of a process. It will be cleaned up by
- // cleanupProcGLObjects(puid) when the process is dead.
- }
- return success;
-}
-
-bool FrameBuffer::flushEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface) {
- AutoLock mutex(m_lock);
-
- auto it = m_windows.find(p_surface);
- if (it == m_windows.end()) {
- ERR("FB::flushEmulatedEglWindowSurfaceColorBuffer: window handle %#x not found", p_surface);
- // bad surface handle
- return false;
- }
-
- EmulatedEglWindowSurface* surface = it->second.first.get();
- surface->flushColorBuffer();
-
- return true;
-}
-
-GLESDispatchMaxVersion FrameBuffer::getMaxGLESVersion() {
- if (!m_emulationGl) {
- return GLES_DISPATCH_MAX_VERSION_2;
- }
- return m_emulationGl->getGlesMaxDispatchVersion();
-}
-
-void FrameBuffer::fillGLESUsages(android_studio::EmulatorGLESUsages* usages) {
- if (s_egl.eglFillUsages) {
- s_egl.eglFillUsages(usages);
- }
-}
-
-void* FrameBuffer::platformCreateSharedEglContext(void) {
- AutoLock lock(m_lock);
-
- EGLContext context = 0;
- EGLSurface surface = 0;
- createSharedTrivialContext(&context, &surface);
-
- void* underlyingContext = s_egl.eglGetNativeContextANDROID(getDisplay(), context);
- if (!underlyingContext) {
- ERR("Error: Underlying egl backend could not produce a native EGL context.");
- return nullptr;
- }
-
- m_platformEglContexts[underlyingContext] = {context, surface};
-
-#if defined(__QNX__)
- EGLDisplay currDisplay = eglGetCurrentDisplay();
- EGLSurface currRead = eglGetCurrentSurface(EGL_READ);
- EGLSurface currDraw = eglGetCurrentSurface(EGL_DRAW);
- EGLSurface currContext = eglGetCurrentContext();
- // Make this context current to ensure thread-state is initialized
- s_egl.eglMakeCurrent(getDisplay(), surface, surface, context);
- // Revert back to original state
- s_egl.eglMakeCurrent(currDisplay, currRead, currDraw, currContext);
-#endif
-
- return underlyingContext;
-}
-
-bool FrameBuffer::platformDestroySharedEglContext(void* underlyingContext) {
- AutoLock lock(m_lock);
-
- auto it = m_platformEglContexts.find(underlyingContext);
- if (it == m_platformEglContexts.end()) {
- ERR("Error: Could not find underlying egl context %p (perhaps already destroyed?)",
- underlyingContext);
- return false;
- }
-
- destroySharedTrivialContext(it->second.context, it->second.surface);
-
- m_platformEglContexts.erase(it);
-
- return true;
-}
-
-bool FrameBuffer::flushColorBufferFromGl(HandleType colorBufferHandle) {
- auto colorBuffer = findColorBuffer(colorBufferHandle);
- if (!colorBuffer) {
- ERR("Failed to find ColorBuffer:%d", colorBufferHandle);
- return false;
- }
- return colorBuffer->flushFromGl();
-}
-
-bool FrameBuffer::invalidateColorBufferForGl(HandleType colorBufferHandle) {
- auto colorBuffer = findColorBuffer(colorBufferHandle);
- if (!colorBuffer) {
- ERR("Failed to find ColorBuffer:%d", colorBufferHandle);
- return false;
- }
- return colorBuffer->invalidateForGl();
-}
-
-ContextHelper* FrameBuffer::getPbufferSurfaceContextHelper() const {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
- if (!m_emulationGl->mPbufferSurface) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
- << "EGL emulation pbuffer surface not available.";
- }
- const auto* displaySurfaceGl =
- reinterpret_cast<const DisplaySurfaceGl*>(m_emulationGl->mPbufferSurface->getImpl());
-
- return displaySurfaceGl->getContextHelper();
-}
-
-bool FrameBuffer::bindColorBufferToTexture(HandleType p_colorbuffer) {
- AutoLock mutex(m_lock);
-
- ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
- if (!colorBuffer) {
- // bad colorbuffer handle
- return false;
- }
-
- return colorBuffer->glOpBindToTexture();
-}
-
-bool FrameBuffer::bindColorBufferToTexture2(HandleType p_colorbuffer) {
- // This is only called when using multi window display
- // It will deadlock when posting from main thread.
- std::unique_ptr<AutoLock> mutex;
- if (!postOnlyOnMainThread()) {
- mutex = std::make_unique<AutoLock>(m_lock);
- }
-
- ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
- if (!colorBuffer) {
- // bad colorbuffer handle
- return false;
- }
-
- return colorBuffer->glOpBindToTexture2();
-}
-
-bool FrameBuffer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) {
- AutoLock mutex(m_lock);
-
- ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
- if (!colorBuffer) {
- // bad colorbuffer handle
- return false;
- }
-
- return colorBuffer->glOpBindToRenderbuffer();
-}
-
-bool FrameBuffer::bindContext(HandleType p_context, HandleType p_drawSurface,
- HandleType p_readSurface) {
- if (m_shuttingDown) {
- return false;
- }
-
- AutoLock mutex(m_lock);
-
- EmulatedEglWindowSurfacePtr draw, read;
- EmulatedEglContextPtr ctx;
-
- //
- // if this is not an unbind operation - make sure all handles are good
- //
- if (p_context || p_drawSurface || p_readSurface) {
- ctx = getContext_locked(p_context);
- if (!ctx) return false;
- EmulatedEglWindowSurfaceMap::iterator w(m_windows.find(p_drawSurface));
- if (w == m_windows.end()) {
- // bad surface handle
- return false;
- }
- draw = (*w).second.first;
-
- if (p_readSurface != p_drawSurface) {
- EmulatedEglWindowSurfaceMap::iterator w(m_windows.find(p_readSurface));
- if (w == m_windows.end()) {
- // bad surface handle
- return false;
- }
- read = (*w).second.first;
- } else {
- read = draw;
- }
- } else {
- // if unbind operation, sweep color buffers
- sweepColorBuffersLocked();
- }
-
- if (!s_egl.eglMakeCurrent(getDisplay(), draw ? draw->getEGLSurface() : EGL_NO_SURFACE,
- read ? read->getEGLSurface() : EGL_NO_SURFACE,
- ctx ? ctx->getEGLContext() : EGL_NO_CONTEXT)) {
- ERR("eglMakeCurrent failed");
- return false;
- }
-
- //
- // Bind the surface(s) to the context
- //
- RenderThreadInfoGl* const tinfo = RenderThreadInfoGl::get();
- if (!tinfo) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "Render thread GL not available.";
- }
-
- EmulatedEglWindowSurfacePtr bindDraw, bindRead;
- if (draw.get() == NULL && read.get() == NULL) {
- // Unbind the current read and draw surfaces from the context
- bindDraw = tinfo->currDrawSurf;
- bindRead = tinfo->currReadSurf;
- } else {
- bindDraw = draw;
- bindRead = read;
- }
-
- if (bindDraw.get() != NULL && bindRead.get() != NULL) {
- if (bindDraw.get() != bindRead.get()) {
- bindDraw->bind(ctx, EmulatedEglWindowSurface::BIND_DRAW);
- bindRead->bind(ctx, EmulatedEglWindowSurface::BIND_READ);
- } else {
- bindDraw->bind(ctx, EmulatedEglWindowSurface::BIND_READDRAW);
- }
- }
-
- //
- // update thread info with current bound context
- //
- tinfo->currContext = ctx;
- tinfo->currDrawSurf = draw;
- tinfo->currReadSurf = read;
- if (ctx) {
- if (ctx->clientVersion() > GLESApi_CM)
- tinfo->m_gl2Dec.setContextData(&ctx->decoderContextData());
- else
- tinfo->m_glDec.setContextData(&ctx->decoderContextData());
- } else {
- tinfo->m_glDec.setContextData(NULL);
- tinfo->m_gl2Dec.setContextData(NULL);
- }
- return true;
-}
-
-void FrameBuffer::createYUVTextures(uint32_t type, uint32_t count, int width, int height,
- uint32_t* output) {
- FrameworkFormat format = static_cast<FrameworkFormat>(type);
- AutoLock mutex(m_lock);
- RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
- for (uint32_t i = 0; i < count; ++i) {
- if (format == FRAMEWORK_FORMAT_NV12) {
- YUVConverter::createYUVGLTex(GL_TEXTURE0, width, height, format, YUVPlane::Y,
- &output[2 * i]);
- YUVConverter::createYUVGLTex(GL_TEXTURE1, width / 2, height / 2, format, YUVPlane::UV,
- &output[2 * i + 1]);
- } else if (format == FRAMEWORK_FORMAT_YUV_420_888) {
- YUVConverter::createYUVGLTex(GL_TEXTURE0, width, height, format, YUVPlane::Y,
- &output[3 * i]);
- YUVConverter::createYUVGLTex(GL_TEXTURE1, width / 2, height / 2, format, YUVPlane::U,
- &output[3 * i + 1]);
- YUVConverter::createYUVGLTex(GL_TEXTURE2, width / 2, height / 2, format, YUVPlane::V,
- &output[3 * i + 2]);
- }
- }
-}
-
-void FrameBuffer::destroyYUVTextures(uint32_t type, uint32_t count, uint32_t* textures) {
- AutoLock mutex(m_lock);
- RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
- if (type == FRAMEWORK_FORMAT_NV12) {
- s_gles2.glDeleteTextures(2 * count, textures);
- } else if (type == FRAMEWORK_FORMAT_YUV_420_888) {
- s_gles2.glDeleteTextures(3 * count, textures);
- }
-}
-
-void FrameBuffer::updateYUVTextures(uint32_t type, uint32_t* textures, void* privData, void* func) {
- AutoLock mutex(m_lock);
- RecursiveScopedContextBind bind(getPbufferSurfaceContextHelper());
-
- yuv_updater_t updater = (yuv_updater_t)func;
- uint32_t gtextures[3] = {0, 0, 0};
-
- if (type == FRAMEWORK_FORMAT_NV12) {
- gtextures[0] = s_gles2.glGetGlobalTexName(textures[0]);
- gtextures[1] = s_gles2.glGetGlobalTexName(textures[1]);
- } else if (type == FRAMEWORK_FORMAT_YUV_420_888) {
- gtextures[0] = s_gles2.glGetGlobalTexName(textures[0]);
- gtextures[1] = s_gles2.glGetGlobalTexName(textures[1]);
- gtextures[2] = s_gles2.glGetGlobalTexName(textures[2]);
- }
-
-#ifdef __APPLE__
- EGLContext prevContext = s_egl.eglGetCurrentContext();
- auto mydisp = EglGlobalInfo::getInstance()->getDisplayFromDisplayType(EGL_DEFAULT_DISPLAY);
- void* nativecontext = mydisp->getLowLevelContext(prevContext);
- struct MediaNativeCallerData callerdata;
- callerdata.ctx = nativecontext;
- callerdata.converter = nsConvertVideoFrameToNV12Textures;
- void* pcallerdata = &callerdata;
-#else
- void* pcallerdata = nullptr;
-#endif
-
- updater(privData, type, gtextures, pcallerdata);
-}
-
-void FrameBuffer::swapTexturesAndUpdateColorBuffer(uint32_t p_colorbuffer, int x, int y, int width,
- int height, uint32_t format, uint32_t type,
- uint32_t texture_type, uint32_t* textures) {
- {
- AutoLock mutex(m_lock);
- ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
- if (!colorBuffer) {
- // bad colorbuffer handle
- return;
- }
- colorBuffer->glOpSwapYuvTexturesAndUpdate(
- format, type, static_cast<FrameworkFormat>(texture_type), textures);
- }
-}
-
-bool FrameBuffer::readColorBufferContents(HandleType p_colorbuffer, size_t* numBytes,
- void* pixels) {
- AutoLock mutex(m_lock);
-
- ColorBufferPtr colorBuffer = findColorBuffer(p_colorbuffer);
- if (!colorBuffer) {
- // bad colorbuffer handle
- return false;
- }
-
- return colorBuffer->glOpReadContents(numBytes, pixels);
-}
-
-void FrameBuffer::waitForGpu(uint64_t eglsync) {
- EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(eglsync);
-
- if (!fenceSync) {
- ERR("err: fence sync 0x%llx not found", (unsigned long long)eglsync);
- return;
- }
-
- SyncThread::get()->triggerBlockedWaitNoTimeline(fenceSync);
-}
-
-void FrameBuffer::asyncWaitForGpuWithCb(uint64_t eglsync, FenceCompletionCallback cb) {
- EmulatedEglFenceSync* fenceSync = EmulatedEglFenceSync::getFromHandle(eglsync);
-
- if (!fenceSync) {
- ERR("err: fence sync 0x%llx not found", (unsigned long long)eglsync);
- return;
- }
-
- SyncThread::get()->triggerWaitWithCompletionCallback(fenceSync, std::move(cb));
-}
-
-const gl::GLESv2Dispatch* FrameBuffer::getGles2Dispatch() {
- if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
- }
-
- return m_emulationGl->getGles2Dispatch();
-}
-
const gl::EGLDispatch* FrameBuffer::getEglDispatch() {
if (!m_emulationGl) {
- GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER)) << "EGL emulation not enabled.";
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
}
return m_emulationGl->getEglDispatch();
}
-#endif
+const gl::GLESv2Dispatch* FrameBuffer::getGles2Dispatch() {
+ if (!m_emulationGl) {
+ GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
+ << "EGL emulation not enabled.";
+ }
+
+ return m_emulationGl->getGles2Dispatch();
+}
} // namespace gfxstream
diff --git a/host/FrameBuffer.h b/host/FrameBuffer.h
index ecb28a9..60a6a35 100644
--- a/host/FrameBuffer.h
+++ b/host/FrameBuffer.h
@@ -16,6 +16,9 @@
#ifndef _LIBRENDER_FRAMEBUFFER_H
#define _LIBRENDER_FRAMEBUFFER_H
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
#include <stdint.h>
#include <array>
@@ -27,7 +30,6 @@
#include <unordered_set>
#include "Buffer.h"
-#include "ColorBuffer.h"
#include "Compositor.h"
#include "Display.h"
#include "DisplaySurface.h"
@@ -46,13 +48,6 @@
#include "aemu/base/synchronization/MessageChannel.h"
#include "aemu/base/threads/Thread.h"
#include "aemu/base/threads/WorkerThread.h"
-
-#if GFXSTREAM_ENABLE_HOST_GLES
-
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
#include "gl/BufferGl.h"
#include "gl/ColorBufferGl.h"
#include "gl/CompositorGl.h"
@@ -64,19 +59,6 @@
#include "gl/EmulationGl.h"
#include "gl/GLESVersionDetector.h"
#include "gl/TextureDraw.h"
-#else
-#include "GlesCompat.h"
-#endif
-
-// values for 'param' argument of rcGetFBParam
-#define FB_WIDTH 1
-#define FB_HEIGHT 2
-#define FB_XDPI 3
-#define FB_YDPI 4
-#define FB_FPS 5
-#define FB_MIN_SWAP_INTERVAL 6
-#define FB_MAX_SWAP_INTERVAL 7
-
#include "render-utils/Renderer.h"
#include "render-utils/virtio_gpu_ops.h"
#include "render-utils/render_api.h"
@@ -119,13 +101,10 @@
mutable std::atomic<uint32_t> mSequenceNumber;
};
-#if GFXSTREAM_ENABLE_HOST_GLES
typedef std::unordered_map<uint64_t, gl::EmulatedEglWindowSurfaceSet>
ProcOwnedEmulatedEglWindowSurfaces;
typedef std::unordered_map<uint64_t, gl::EmulatedEglContextSet> ProcOwnedEmulatedEglContexts;
-typedef std::unordered_map<uint64_t, gl::EmulatedEglImageSet> ProcOwnedEmulatedEGLImages;
-#endif
typedef std::unordered_map<uint64_t, ColorBufferSet> ProcOwnedColorBuffers;
@@ -133,6 +112,8 @@
typedef std::unordered_multiset<HandleType> BufferSet;
typedef std::unordered_map<uint64_t, BufferSet> ProcOwnedBuffers;
+typedef std::unordered_map<uint64_t, gl::EmulatedEglImageSet> ProcOwnedEmulatedEGLImages;
+
typedef std::unordered_map<void*, std::function<void()>> CallbackMap;
typedef std::unordered_map<uint64_t, CallbackMap> ProcOwnedCleanupCallbacks;
@@ -199,12 +180,55 @@
// Return the emulated GPU display height in pixels.
int getHeight() const { return m_framebufferHeight; }
+ // Return the list of configs available from this display.
+ const gl::EmulatedEglConfigList* getConfigs() const;
+
// Set a callback that will be called each time the emulated GPU content
// is updated. This can be relatively slow with host-based GPU emulation,
// so only do this when you need to.
void setPostCallback(Renderer::OnPostCallback onPost, void* onPostContext, uint32_t displayId,
bool useBgraReadback = false);
+ // Retrieve the GL strings of the underlying EGL/GLES implementation.
+ // On return, |*vendor|, |*renderer| and |*version| will point to strings
+ // that are owned by the instance (and must not be freed by the caller).
+ void getGLStrings(const char** vendor, const char** renderer,
+ const char** version) const {
+ *vendor = m_graphicsAdapterVendor.c_str();
+ *renderer = m_graphicsAdapterName.c_str();
+ *version = m_graphicsApiVersion.c_str();
+ }
+
+ // Create a new EmulatedEglContext instance for this display instance.
+ // |p_config| is the index of one of the configs returned by getConfigs().
+ // |p_share| is either EGL_NO_CONTEXT or the handle of a shared context.
+ // |version| specifies the GLES version as a GLESApi enum.
+ // Return a new handle value, which will be 0 in case of error.
+ HandleType createEmulatedEglContext(int p_config, HandleType p_share,
+ gl::GLESApi version = gl::GLESApi_CM);
+
+ // Destroy a given EmulatedEglContext instance. |p_context| is its handle
+ // value as returned by createEmulatedEglContext().
+ void destroyEmulatedEglContext(HandleType p_context);
+
+ // Create a new EmulatedEglWindowSurface instance from this display instance.
+ // |p_config| is the index of one of the configs returned by getConfigs().
+ // |p_width| and |p_height| are the window dimensions in pixels.
+ // Return a new handle value, or 0 in case of error.
+ HandleType createEmulatedEglWindowSurface(int p_config, int p_width, int p_height);
+
+ // Destroy a given EmulatedEglWindowSurface instance. |p_surcace| is its
+ // handle value as returned by createEmulatedEglWindowSurface().
+ void destroyEmulatedEglWindowSurface(HandleType p_surface);
+
+ // Returns the set of ColorBuffers destroyed (for further cleanup)
+ std::vector<HandleType> destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface);
+
+ void createEmulatedEglFenceSync(EGLenum type,
+ int destroyWhenSignaled,
+ uint64_t* outSync = nullptr,
+ uint64_t* outSyncThread = nullptr);
+
// Create a new ColorBuffer instance from this display instance.
// |p_width| and |p_height| are its dimensions in pixels.
// |p_internalFormat| is the OpenGL format of this color buffer.
@@ -236,6 +260,21 @@
// virtio-gpu's RESOURCE_CREATE ioctl for BLOB resources.
void createBufferWithHandle(uint64_t size, HandleType handle);
+ // Call this function when a render thread terminates to destroy all
+ // resources it created. Necessary to avoid leaking host resources
+ // when a guest application crashes, for example.
+ void drainGlRenderThreadResources();
+
+ // Call this function when a render thread terminates to destroy all
+ // the remaining contexts it created. Necessary to avoid leaking host
+ // contexts when a guest application crashes, for example.
+ void drainGlRenderThreadContexts();
+
+ // Call this function when a render thread terminates to destroy all
+ // remaining window surface it created. Necessary to avoid leaking
+ // host buffers when a guest application crashes, for example.
+ void drainGlRenderThreadSurfaces();
+
// Increment the reference count associated with a given ColorBuffer
// instance. |p_colorbuffer| is its handle value as returned by
// createColorBuffer().
@@ -259,6 +298,54 @@
// TODO(kaiyili): retire cleanupProcGLObjects in favor of removeGraphicsProcessResources.
void cleanupProcGLObjects(uint64_t puid);
+ // Equivalent for eglMakeCurrent() for the current display.
+ // |p_context|, |p_drawSurface| and |p_readSurface| are the handle values
+ // of the context, the draw surface and the read surface, respectively.
+ // Returns true on success, false on failure.
+ // Note: if all handle values are 0, this is an unbind operation.
+ bool bindContext(HandleType p_context, HandleType p_drawSurface,
+ HandleType p_readSurface);
+
+ // Return a render context pointer from its handle
+ gl::EmulatedEglContextPtr getContext_locked(HandleType p_context);
+
+ // Return a color buffer pointer from its handle
+ gl::EmulatedEglWindowSurfacePtr getWindowSurface_locked(HandleType p_windowsurface);
+
+ // Attach a ColorBuffer to a EmulatedEglWindowSurface instance.
+ // See the documentation for EmulatedEglWindowSurface::setColorBuffer().
+ // |p_surface| is the target EmulatedEglWindowSurface's handle value.
+ // |p_colorbuffer| is the ColorBuffer handle value.
+ // Returns true on success, false otherwise.
+ bool setEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface,
+ HandleType p_colorbuffer);
+
+ // Copy the content of a EmulatedEglWindowSurface's Pbuffer to its attached
+ // ColorBuffer. See the documentation for
+ // EmulatedEglWindowSurface::flushColorBuffer().
+ // |p_surface| is the target WindowSurface's handle value.
+ // Returns true on success, false on failure.
+ bool flushEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface);
+
+ // Retrieves the color buffer handle associated with |p_surface|.
+ // Returns 0 if there is no such handle.
+ HandleType getEmulatedEglWindowSurfaceColorBufferHandle(HandleType p_surface);
+
+ // Bind the current context's EGL_TEXTURE_2D texture to a ColorBuffer
+ // instance's EGLImage. This is intended to implement
+ // glEGLImageTargetTexture2DOES() for all GLES versions.
+ // |p_colorbuffer| is the ColorBuffer's handle value.
+ // Returns true on success, false on failure.
+ bool bindColorBufferToTexture(HandleType p_colorbuffer);
+ bool bindColorBufferToTexture2(HandleType p_colorbuffer);
+
+ // Bind the current context's EGL_RENDERBUFFER_OES render buffer to this
+ // ColorBuffer's EGLImage. This is intended to implement
+ // glEGLImageTargetRenderbufferStorageOES() for all GLES versions.
+ // |p_colorbuffer| is the ColorBuffer's handle value.
+ // Returns true on success, false on failure.
+ bool bindColorBufferToRenderbuffer(HandleType p_colorbuffer);
+
// Read the content of a given Buffer into client memory.
// |p_buffer| is the Buffer's handle value.
// |offset| and |size| are the position and size of a slice of the buffer
@@ -290,6 +377,17 @@
void readColorBufferYUV(HandleType p_colorbuffer, int x, int y, int width,
int height, void* pixels, uint32_t pixels_size);
+ // create a Y texture and a UV texture with width and height, the created
+ // texture ids are stored in textures respectively
+ void createYUVTextures(uint32_t type, uint32_t count, int width, int height,
+ uint32_t* output);
+ void destroyYUVTextures(uint32_t type, uint32_t count, uint32_t* textures);
+ void updateYUVTextures(uint32_t type, uint32_t* textures, void* privData,
+ void* func);
+ void swapTexturesAndUpdateColorBuffer(uint32_t colorbufferhandle, int x, int y, int width,
+ int height, uint32_t format, uint32_t type,
+ uint32_t texture_type, uint32_t* textures);
+
// Update the content of a given Buffer from client data.
// |p_buffer| is the Buffer's handle value.
// |offset| and |size| are the position and size of a slice of the buffer
@@ -317,6 +415,17 @@
int height, FrameworkFormat fwkFormat, GLenum format,
GLenum type, void* pixels, void* metadata = nullptr);
+ // Reads back the raw color buffer to |pixels|
+ // if |pixels| is not null.
+ // Always returns in |numBytes| how many bytes were
+ // planned to be transmitted.
+ // |numBytes| is not an input parameter;
+ // fewer or more bytes cannot be specified.
+ // If the framework format is YUV, it will read
+ // back as raw YUV data.
+ bool readColorBufferContents(HandleType p_colorbuffer, size_t* numBytes,
+ void* pixels);
+
bool getColorBufferInfo(HandleType p_colorbuffer, int* width, int* height,
GLint* internalformat,
FrameworkFormat* frameworkFormat = nullptr);
@@ -352,6 +461,16 @@
// be re-displayed for any reason.
bool repost(bool needLockAndBind = true);
+ gl::EmulationGl& getEmulationGl();
+ bool hasEmulationGl() const { return m_emulationGl != nullptr; }
+
+ // Return the host EGLDisplay used by this instance.
+ EGLDisplay getDisplay() const;
+ EGLSurface getWindowSurface() const;
+ EGLContext getContext() const;
+ EGLConfig getConfig() const;
+ ContextHelper* getPbufferSurfaceContextHelper() const;
+
// Change the rotation of the displayed GPU sub-window.
void setDisplayRotation(float zRot) {
if (zRot != m_zRot) {
@@ -377,6 +496,19 @@
}
}
+ // Return a TextureDraw instance that can be used with this surfaces
+ // and windows created by this instance.
+ gl::TextureDraw* getTextureDraw() const;
+
+ // Create an eglImage and return its handle. Reference:
+ // https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
+ HandleType createEmulatedEglImage(HandleType context, EGLenum target,
+ GLuint buffer);
+ // Call the implementation of eglDestroyImageKHR, return if succeeds or
+ // not. Reference:
+ // https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
+ EGLBoolean destroyEmulatedEglImage(HandleType image);
+
void lockContextStructureRead() { m_contextStructureLock.lockRead(); }
void unlockContextStructureRead() { m_contextStructureLock.unlockRead(); }
@@ -385,7 +517,12 @@
// GL state.
// It can be unsafe / leaky to change the structure of contexts
// outside the facilities the FrameBuffer class provides.
- void createTrivialContext(HandleType shared, HandleType* contextOut, HandleType* surfOut);
+ void createTrivialContext(HandleType shared, HandleType* contextOut,
+ HandleType* surfOut);
+ // createTrivialContext(), but with a m_pbufContext
+ // as shared, and not adding itself to the context map at all.
+ void createSharedTrivialContext(EGLContext* contextOut, EGLSurface* surfOut);
+ void destroySharedTrivialContext(EGLContext context, EGLSurface surf);
void setShuttingDown() { m_shuttingDown = true; }
bool isShuttingDown() const { return m_shuttingDown; }
@@ -406,6 +543,8 @@
void lock();
void unlock();
+ gl::GLESDispatchMaxVersion getMaxGLESVersion();
+
float getDpr() const { return m_dpr; }
int windowWidth() const { return m_windowWidth; }
int windowHeight() const { return m_windowHeight; }
@@ -413,9 +552,15 @@
float getPy() const { return m_py; }
int getZrot() const { return m_zRot; }
+ bool isFastBlitSupported() const;
+ void disableFastBlitForTesting();
+
bool isVulkanInteropSupported() const { return m_vulkanInteropSupported; }
bool isVulkanEnabled() const { return m_vulkanEnabled; }
+ // Fill GLES usage protobuf
+ void fillGLESUsages(android_studio::EmulatorGLESUsages*);
+
// Saves a screenshot of the previous frame.
// nChannels should be 3 (RGB) or 4 (RGBA).
// You must provide a pre-allocated buffer of sufficient
@@ -477,13 +622,18 @@
static const uint32_t s_invalidIdMultiDisplay = 0xFFFFFFAB;
static const uint32_t s_maxNumMultiDisplay = 11;
+ EGLContext getGlobalEGLContext() const;
HandleType getLastPostedColorBuffer() { return m_lastPostedColorBuffer; }
+ void waitForGpu(uint64_t eglsync);
void waitForGpuVulkan(uint64_t deviceHandle, uint64_t fenceHandle);
+ void asyncWaitForGpuWithCb(uint64_t eglsync, FenceCompletionCallback cb);
void asyncWaitForGpuVulkanWithCb(uint64_t deviceHandle, uint64_t fenceHandle, FenceCompletionCallback cb);
void asyncWaitForGpuVulkanQsriWithCb(uint64_t image, FenceCompletionCallback cb);
void waitForGpuVulkanQsri(uint64_t image);
bool platformImportResource(uint32_t handle, uint32_t info, void* resource);
+ void* platformCreateSharedEglContext(void);
+ bool platformDestroySharedEglContext(void* context);
void setGuestManagedColorBufferLifetime(bool guestManaged);
@@ -508,182 +658,14 @@
const int getDisplayConfigsParam(int configId, EGLint param);
const int getDisplayActiveConfig();
- bool flushColorBufferFromVk(HandleType colorBufferHandle);
- bool flushColorBufferFromVkBytes(HandleType colorBufferHandle, const void* bytes,
- size_t bytesSize);
- bool invalidateColorBufferForVk(HandleType colorBufferHandle);
-
-#if GFXSTREAM_ENABLE_HOST_GLES
- // Retrieves the color buffer handle associated with |p_surface|.
- // Returns 0 if there is no such handle.
- HandleType getEmulatedEglWindowSurfaceColorBufferHandle(HandleType p_surface);
-
- // createTrivialContext(), but with a m_pbufContext
- // as shared, and not adding itself to the context map at all.
- void createSharedTrivialContext(EGLContext* contextOut, EGLSurface* surfOut);
- void destroySharedTrivialContext(EGLContext context, EGLSurface surf);
-
- // Attach a ColorBuffer to a EmulatedEglWindowSurface instance.
- // See the documentation for EmulatedEglWindowSurface::setColorBuffer().
- // |p_surface| is the target EmulatedEglWindowSurface's handle value.
- // |p_colorbuffer| is the ColorBuffer handle value.
- // Returns true on success, false otherwise.
-
- bool setEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface, HandleType p_colorbuffer);
- // Return the list of configs available from this display.
- const gl::EmulatedEglConfigList* getConfigs() const;
-
- // Retrieve the GL strings of the underlying EGL/GLES implementation.
- // On return, |*vendor|, |*renderer| and |*version| will point to strings
- // that are owned by the instance (and must not be freed by the caller).
- void getGLStrings(const char** vendor, const char** renderer, const char** version) const {
- *vendor = m_graphicsAdapterVendor.c_str();
- *renderer = m_graphicsAdapterName.c_str();
- *version = m_graphicsApiVersion.c_str();
- }
-
- // Create a new EmulatedEglContext instance for this display instance.
- // |p_config| is the index of one of the configs returned by getConfigs().
- // |p_share| is either EGL_NO_CONTEXT or the handle of a shared context.
- // |version| specifies the GLES version as a GLESApi enum.
- // Return a new handle value, which will be 0 in case of error.
- HandleType createEmulatedEglContext(int p_config, HandleType p_share,
- gl::GLESApi version = gl::GLESApi_CM);
-
- // Destroy a given EmulatedEglContext instance. |p_context| is its handle
- // value as returned by createEmulatedEglContext().
- void destroyEmulatedEglContext(HandleType p_context);
-
- // Create a new EmulatedEglWindowSurface instance from this display instance.
- // |p_config| is the index of one of the configs returned by getConfigs().
- // |p_width| and |p_height| are the window dimensions in pixels.
- // Return a new handle value, or 0 in case of error.
- HandleType createEmulatedEglWindowSurface(int p_config, int p_width, int p_height);
-
- // Destroy a given EmulatedEglWindowSurface instance. |p_surcace| is its
- // handle value as returned by createEmulatedEglWindowSurface().
- void destroyEmulatedEglWindowSurface(HandleType p_surface);
-
- // Returns the set of ColorBuffers destroyed (for further cleanup)
- std::vector<HandleType> destroyEmulatedEglWindowSurfaceLocked(HandleType p_surface);
-
- void createEmulatedEglFenceSync(EGLenum type, int destroyWhenSignaled,
- uint64_t* outSync = nullptr, uint64_t* outSyncThread = nullptr);
-
- // Call this function when a render thread terminates to destroy all
- // resources it created. Necessary to avoid leaking host resources
- // when a guest application crashes, for example.
- void drainGlRenderThreadResources();
-
- // Call this function when a render thread terminates to destroy all
- // the remaining contexts it created. Necessary to avoid leaking host
- // contexts when a guest application crashes, for example.
- void drainGlRenderThreadContexts();
-
- // Call this function when a render thread terminates to destroy all
- // remaining window surface it created. Necessary to avoid leaking
- // host buffers when a guest application crashes, for example.
- void drainGlRenderThreadSurfaces();
-
- gl::EmulationGl& getEmulationGl();
- bool hasEmulationGl() const { return m_emulationGl != nullptr; }
-
- // Return the host EGLDisplay used by this instance.
- EGLDisplay getDisplay() const;
- EGLSurface getWindowSurface() const;
- EGLContext getContext() const;
- EGLConfig getConfig() const;
-
- EGLContext getGlobalEGLContext() const;
-
- // Return a render context pointer from its handle
- gl::EmulatedEglContextPtr getContext_locked(HandleType p_context);
-
- // Return a color buffer pointer from its handle
- gl::EmulatedEglWindowSurfacePtr getWindowSurface_locked(HandleType p_windowsurface);
-
- // Return a TextureDraw instance that can be used with this surfaces
- // and windows created by this instance.
- gl::TextureDraw* getTextureDraw() const;
-
- bool isFastBlitSupported() const;
- void disableFastBlitForTesting();
-
- // Create an eglImage and return its handle. Reference:
- // https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
- HandleType createEmulatedEglImage(HandleType context, EGLenum target, GLuint buffer);
- // Call the implementation of eglDestroyImageKHR, return if succeeds or
- // not. Reference:
- // https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
- EGLBoolean destroyEmulatedEglImage(HandleType image);
- // Copy the content of a EmulatedEglWindowSurface's Pbuffer to its attached
- // ColorBuffer. See the documentation for
- // EmulatedEglWindowSurface::flushColorBuffer().
- // |p_surface| is the target WindowSurface's handle value.
- // Returns true on success, false on failure.
- bool flushEmulatedEglWindowSurfaceColorBuffer(HandleType p_surface);
-
- gl::GLESDispatchMaxVersion getMaxGLESVersion();
-
- // Fill GLES usage protobuf
- void fillGLESUsages(android_studio::EmulatorGLESUsages*);
-
- void* platformCreateSharedEglContext(void);
- bool platformDestroySharedEglContext(void* context);
-
bool flushColorBufferFromGl(HandleType colorBufferHandle);
-
+ bool flushColorBufferFromVk(HandleType colorBufferHandle);
+ bool flushColorBufferFromVkBytes(HandleType colorBufferHandle, const void* bytes, size_t bytesSize);
bool invalidateColorBufferForGl(HandleType colorBufferHandle);
-
- ContextHelper* getPbufferSurfaceContextHelper() const;
-
- // Bind the current context's EGL_TEXTURE_2D texture to a ColorBuffer
- // instance's EGLImage. This is intended to implement
- // glEGLImageTargetTexture2DOES() for all GLES versions.
- // |p_colorbuffer| is the ColorBuffer's handle value.
- // Returns true on success, false on failure.
- bool bindColorBufferToTexture(HandleType p_colorbuffer);
- bool bindColorBufferToTexture2(HandleType p_colorbuffer);
-
- // Bind the current context's EGL_RENDERBUFFER_OES render buffer to this
- // ColorBuffer's EGLImage. This is intended to implement
- // glEGLImageTargetRenderbufferStorageOES() for all GLES versions.
- // |p_colorbuffer| is the ColorBuffer's handle value.
- // Returns true on success, false on failure.
- bool bindColorBufferToRenderbuffer(HandleType p_colorbuffer);
-
- // Equivalent for eglMakeCurrent() for the current display.
- // |p_context|, |p_drawSurface| and |p_readSurface| are the handle values
- // of the context, the draw surface and the read surface, respectively.
- // Returns true on success, false on failure.
- // Note: if all handle values are 0, this is an unbind operation.
- bool bindContext(HandleType p_context, HandleType p_drawSurface, HandleType p_readSurface);
-
- // create a Y texture and a UV texture with width and height, the created
- // texture ids are stored in textures respectively
- void createYUVTextures(uint32_t type, uint32_t count, int width, int height, uint32_t* output);
- void destroyYUVTextures(uint32_t type, uint32_t count, uint32_t* textures);
- void updateYUVTextures(uint32_t type, uint32_t* textures, void* privData, void* func);
- void swapTexturesAndUpdateColorBuffer(uint32_t colorbufferhandle, int x, int y, int width,
- int height, uint32_t format, uint32_t type,
- uint32_t texture_type, uint32_t* textures);
-
- // Reads back the raw color buffer to |pixels|
- // if |pixels| is not null.
- // Always returns in |numBytes| how many bytes were
- // planned to be transmitted.
- // |numBytes| is not an input parameter;
- // fewer or more bytes cannot be specified.
- // If the framework format is YUV, it will read
- // back as raw YUV data.
- bool readColorBufferContents(HandleType p_colorbuffer, size_t* numBytes, void* pixels);
-
- void waitForGpu(uint64_t eglsync);
- void asyncWaitForGpuWithCb(uint64_t eglsync, FenceCompletionCallback cb);
+ bool invalidateColorBufferForVk(HandleType colorBufferHandle);
const gl::EGLDispatch* getEglDispatch();
const gl::GLESv2Dispatch* getGles2Dispatch();
-#endif
private:
FrameBuffer(int p_width, int p_height, bool useSubWindow);
@@ -756,9 +738,12 @@
android::base::Lock m_colorBufferMapLock;
uint64_t mFrameNumber;
FBNativeWindowType m_nativeWindow = 0;
-
+ gl::EmulatedEglContextMap m_contexts;
+ gl::EmulatedEglImageMap m_images;
+ gl::EmulatedEglWindowSurfaceMap m_windows;
ColorBufferMap m_colorbuffers;
BufferMap m_buffers;
+ std::unordered_map<HandleType, HandleType> m_EmulatedEglWindowSurfaceToColorBuffer;
// A collection of color buffers that were closed without any usages
// (|opened| == false).
@@ -828,6 +813,15 @@
std::string m_graphicsApiVersion;
std::string m_graphicsApiExtensions;
std::string m_graphicsDeviceExtensions;
+
+ // The host associates color buffers with guest processes for memory
+ // cleanup. Guest processes are identified with a host generated unique ID.
+ // TODO(kaiyili): move all those resources to the ProcessResources struct.
+ ProcOwnedColorBuffers m_procOwnedColorBuffers;
+ ProcOwnedEmulatedEGLImages m_procOwnedEmulatedEglImages;
+ ProcOwnedEmulatedEglContexts m_procOwnedEmulatedEglContexts;
+ ProcOwnedEmulatedEglWindowSurfaces m_procOwnedEmulatedEglWindowSurfaces;
+ ProcOwnedCleanupCallbacks m_procOwnedCleanupCallbacks;
std::unordered_map<uint64_t, std::unique_ptr<ProcessResources>> m_procOwnedResources;
// Flag set when emulator is shutting down.
@@ -863,6 +857,9 @@
android::base::MessageChannel<HandleType, 1024>
mOutstandingColorBufferDestroys;
+ std::unique_ptr<gl::EmulationGl> m_emulationGl;
+ gl::DisplayGl* m_displayGl = nullptr;
+
Compositor* m_compositor = nullptr;
bool m_useVulkanComposition = false;
@@ -886,9 +883,15 @@
// cases, this determines whether we can support zero-copy interop.
using VkUuid = std::array<uint8_t, VK_UUID_SIZE>;
VkUuid m_vulkanUUID{};
+ static_assert(VK_UUID_SIZE == GL_UUID_SIZE_EXT);
// Tracks platform EGL contexts that have been handed out to other users,
// indexed by underlying native EGL context object.
+ struct PlatformEglContextInfo {
+ EGLContext context;
+ EGLSurface surface;
+ };
+ std::unordered_map<void*, PlatformEglContextInfo> m_platformEglContexts;
std::unique_ptr<MetricsLogger> m_logger;
std::unique_ptr<HealthMonitor<>> m_healthMonitor;
@@ -909,34 +912,6 @@
};
std::map<int, DisplayConfig> mDisplayConfigs;
int mDisplayActiveConfigId = -1;
-
- std::unique_ptr<gl::EmulationGl> m_emulationGl;
-
- // The host associates color buffers with guest processes for memory
- // cleanup. Guest processes are identified with a host generated unique ID.
- // TODO(kaiyili): move all those resources to the ProcessResources struct.
- ProcOwnedColorBuffers m_procOwnedColorBuffers;
- ProcOwnedCleanupCallbacks m_procOwnedCleanupCallbacks;
-
-#if GFXSTREAM_ENABLE_HOST_GLES
- gl::EmulatedEglContextMap m_contexts;
- gl::EmulatedEglImageMap m_images;
- gl::EmulatedEglWindowSurfaceMap m_windows;
-
- std::unordered_map<HandleType, HandleType> m_EmulatedEglWindowSurfaceToColorBuffer;
-
- ProcOwnedEmulatedEGLImages m_procOwnedEmulatedEglImages;
- ProcOwnedEmulatedEglContexts m_procOwnedEmulatedEglContexts;
- ProcOwnedEmulatedEglWindowSurfaces m_procOwnedEmulatedEglWindowSurfaces;
- gl::DisplayGl* m_displayGl = nullptr;
-
- struct PlatformEglContextInfo {
- EGLContext context;
- EGLSurface surface;
- };
-
- std::unordered_map<void*, PlatformEglContextInfo> m_platformEglContexts;
-#endif
};
} // namespace gfxstream
diff --git a/host/GlesCompat.h b/host/GlesCompat.h
deleted file mode 100644
index 3c57028..0000000
--- a/host/GlesCompat.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2024 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.
-
-#ifndef GLES_COMPAT_H
-#define GLES_COMPAT_H
-
-#include <cstdint>
-
-typedef unsigned int GLenum;
-typedef int32_t EGLint;
-// typedef void *EGLNativeDisplayType;
-typedef unsigned int EGLNativeWindowType;
-
-namespace gfxstream {
-namespace gl {
-class EmulationGl {
- public:
- EmulationGl() {}
- ~EmulationGl() {}
-
- private:
- uint32_t payload;
-};
-} // namespace gl
-} // namespace gfxstream
-
-#endif
diff --git a/host/NativeSubWindow.h b/host/NativeSubWindow.h
index aff117c..07dec0e 100644
--- a/host/NativeSubWindow.h
+++ b/host/NativeSubWindow.h
@@ -18,11 +18,7 @@
#include "render-utils/render_api_platform_types.h"
-#if GFXSTREAM_ENABLE_HOST_GLES
#include <EGL/egl.h>
-#else
-#include "GlesCompat.h"
-#endif
#ifdef __cplusplus
extern "C" {
diff --git a/host/NativeSubWindow_stub.cpp b/host/NativeSubWindow_stub.cpp
deleted file mode 100644
index 75a1ea8..0000000
--- a/host/NativeSubWindow_stub.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2024 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 "GlesCompat.h"
-#include "NativeSubWindow.h"
-
-EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, int x, int y, int width,
- int height, float dpr,
- SubWindowRepaintCallback repaint_callback,
- void* repaint_callback_param, int hideWindow) {
- return 0;
-}
-
-void destroySubWindow(EGLNativeWindowType win) { return; }
-
-int moveSubWindow(FBNativeWindowType p_parent_window, EGLNativeWindowType p_sub_window, int x,
- int y, int width, int height) {
- return 0;
-}
diff --git a/host/RenderControl.cpp b/host/RenderControl.cpp
index 698914c..2c84d45 100644
--- a/host/RenderControl.cpp
+++ b/host/RenderControl.cpp
@@ -1636,4 +1636,4 @@
dec->rcGetHostExtensionsString = rcGetHostExtensionsString;
}
-} // namespace gfxstream
+} // namespace gfxstream
\ No newline at end of file
diff --git a/host/RenderLibImpl.cpp b/host/RenderLibImpl.cpp
index 8f695e6..cd1dffe 100644
--- a/host/RenderLibImpl.cpp
+++ b/host/RenderLibImpl.cpp
@@ -14,6 +14,8 @@
#include "RenderLibImpl.h"
#include "FrameBuffer.h"
+#include "OpenGLESDispatch/EGLDispatch.h"
+#include "OpenGLESDispatch/DispatchTables.h"
#include "RendererImpl.h"
#include "aemu/base/files/Stream.h"
#include "host-common/address_space_device_control_ops.h"
@@ -25,11 +27,6 @@
#include "host-common/opengl/misc.h"
#include "host-common/sync_device.h"
-#if GFXSTREAM_ENABLE_HOST_GLES
-#include "OpenGLESDispatch/DispatchTables.h"
-#include "OpenGLESDispatch/EGLDispatch.h"
-#endif
-
namespace gfxstream {
void RenderLibImpl::setRenderer(SelectedRenderer renderer) {
@@ -114,11 +111,10 @@
return false;
}
-#if GFXSTREAM_ENABLE_HOST_GLES
opt->display = fb->getDisplay();
opt->surface = fb->getWindowSurface();
opt->config = fb->getConfig();
-#endif
+
return (opt->display && opt->surface && opt->config);
}
diff --git a/host/RenderThread.cpp b/host/RenderThread.cpp
index d1d34ea..abe4fcc 100644
--- a/host/RenderThread.cpp
+++ b/host/RenderThread.cpp
@@ -19,24 +19,21 @@
#include "FrameBuffer.h"
#include "ReadBuffer.h"
#include "RenderChannelImpl.h"
+#include "RenderControl.h"
#include "RenderThreadInfo.h"
#include "RingStream.h"
#include "VkDecoderContext.h"
+#include "apigen-codec-common/ChecksumCalculatorThreadInfo.h"
#include "aemu/base/HealthMonitor.h"
-#include "aemu/base/Metrics.h"
-#include "aemu/base/files/StreamSerializing.h"
#include "aemu/base/synchronization/Lock.h"
#include "aemu/base/synchronization/MessageChannel.h"
+#include "aemu/base/Metrics.h"
+#include "aemu/base/files/StreamSerializing.h"
#include "aemu/base/system/System.h"
-#include "apigen-codec-common/ChecksumCalculatorThreadInfo.h"
#include "host-common/feature_control.h"
#include "host-common/logging.h"
#include "vulkan/VkCommonOperations.h"
-#if GFXSTREAM_ENABLE_HOST_GLES
-#include "RenderControl.h"
-#endif
-
#define EMUGL_DEBUG_LEVEL 0
#include "host-common/debug.h"
@@ -273,13 +270,12 @@
//
// initialize decoders
-#if GFXSTREAM_ENABLE_HOST_GLES
+ //
if (!feature_is_enabled(kFeature_GuestUsesAngle)) {
tInfo.initGl();
}
initRenderControlContext(&tInfo.m_rcDec);
-#endif
if (!mChannel && !mRingStream) {
GL_LOG("Exited a loader RenderThread @%p", this);
@@ -527,7 +523,6 @@
FrameBuffer::getFB()->lockContextStructureRead();
}
-#if GFXSTREAM_ENABLE_HOST_GLES
if (tInfo.m_glInfo) {
{
last = tInfo.m_glInfo->m_glDec.decode(
@@ -552,14 +547,12 @@
}
}
}
-#endif
FrameBuffer::getFB()->unlockContextStructureRead();
//
// try to process some of the command buffer using the
// renderControl decoder
//
-#if GFXSTREAM_ENABLE_HOST_GLES
{
last = tInfo.m_rcDec.decode(readBuf.buf(), readBuf.validData(),
ioStream, &checksumCalc);
@@ -568,7 +561,6 @@
progress = true;
}
}
-#endif
//
// try to process some of the command buffer using the Magma
@@ -597,11 +589,9 @@
fclose(dumpFP);
}
-#if GFXSTREAM_ENABLE_HOST_GLES
if (tInfo.m_glInfo) {
FrameBuffer::getFB()->drainGlRenderThreadResources();
}
-#endif
setFinished();
diff --git a/host/RenderThreadInfo.cpp b/host/RenderThreadInfo.cpp
index b3cab71..fdbbfc8 100644
--- a/host/RenderThreadInfo.cpp
+++ b/host/RenderThreadInfo.cpp
@@ -61,21 +61,16 @@
}
}
-#if GFXSTREAM_ENABLE_HOST_GLES
void RenderThreadInfo::initGl() {
m_glInfo.emplace();
}
-#endif
void RenderThreadInfo::onSave(Stream* stream) {
// TODO(b/309858017): remove if when ready to bump snapshot version
if (feature_is_enabled(kFeature_VulkanSnapshots)) {
stream->putBe64(m_puid);
}
-
-#if GFXSTREAM_ENABLE_HOST_GLES
m_glInfo->onSave(stream);
-#endif
}
bool RenderThreadInfo::onLoad(Stream* stream) {
@@ -83,19 +78,11 @@
if (feature_is_enabled(kFeature_VulkanSnapshots)) {
m_puid = stream->getBe64();
}
-
-#if GFXSTREAM_ENABLE_HOST_GLES
return m_glInfo->onLoad(stream);
-#else
- // Functions only work with GLES for now.
- return false;
-#endif
}
void RenderThreadInfo::postLoadRefreshCurrentContextSurfacePtrs() {
-#if GFXSTREAM_ENABLE_HOST_GLES
return m_glInfo->postLoadRefreshCurrentContextSurfacePtrs();
-#endif
}
} // namespace gfxstream
diff --git a/host/RenderThreadInfo.h b/host/RenderThreadInfo.h
index 5e20d8a..636421e 100644
--- a/host/RenderThreadInfo.h
+++ b/host/RenderThreadInfo.h
@@ -21,12 +21,8 @@
#include <unordered_set>
#include "aemu/base/files/Stream.h"
-
-#if GFXSTREAM_ENABLE_HOST_GLES
#include "renderControl_dec/renderControl_dec.h"
#include "RenderThreadInfoGl.h"
-#endif
-
#include "RenderThreadInfoVk.h"
#if GFXSTREAM_ENABLE_HOST_MAGMA
@@ -51,19 +47,15 @@
// Loop over all active render thread infos
static void forAllRenderThreadInfos(std::function<void(RenderThreadInfo*)>);
-#if GFXSTREAM_ENABLE_HOST_GLES
void initGl();
-#endif
+
+ renderControl_decoder_context_t m_rcDec;
// The unique id of owner guest process of this render thread
uint64_t m_puid = 0;
std::optional<std::string> m_processName;
-#if GFXSTREAM_ENABLE_HOST_GLES
- renderControl_decoder_context_t m_rcDec;
std::optional<gl::RenderThreadInfoGl> m_glInfo;
-#endif
-
std::optional<vk::RenderThreadInfoVk> m_vkInfo;
#if GFXSTREAM_ENABLE_HOST_MAGMA
diff --git a/host/RenderWindow.cpp b/host/RenderWindow.cpp
index ace6114..58c374e 100644
--- a/host/RenderWindow.cpp
+++ b/host/RenderWindow.cpp
@@ -498,16 +498,11 @@
D("No framebuffer!\n");
return false;
}
-
-#if GFXSTREAM_ENABLE_HOST_GLES
fb->getGLStrings(vendor, renderer, version);
D("Exiting vendor=[%s] renderer=[%s] version=[%s]\n",
*vendor, *renderer, *version);
return true;
-#else
- return false;
-#endif
}
void RenderWindow::setPostCallback(Renderer::OnPostCallback onPost, void* onPostContext,
@@ -615,11 +610,11 @@
void RenderWindow::setScreenMask(int width, int height, const unsigned char* rgbaData) {
if (FrameBuffer* fb = FrameBuffer::getFB()) {
-#if GFXSTREAM_ENABLE_HOST_GLES
if (fb->hasEmulationGl()) {
fb->getTextureDraw()->setScreenMask(width, height, rgbaData);
+ } else {
+ ERR("RenderWindow::setScreenMask() not supported without GL emulation.");
}
-#endif
}
}
@@ -695,4 +690,4 @@
}
}
-} // namespace gfxstream
+} // namespace gfxstream
\ No newline at end of file
diff --git a/host/RendererImpl.cpp b/host/RendererImpl.cpp
index 33972b4..c1fb7dd 100644
--- a/host/RendererImpl.cpp
+++ b/host/RendererImpl.cpp
@@ -24,13 +24,10 @@
#include "RenderThread.h"
#include "aemu/base/system/System.h"
#include "aemu/base/threads/WorkerThread.h"
+#include "gl/EmulatedEglFenceSync.h"
#include "host-common/logging.h"
#include "snapshot/common.h"
-#if GFXSTREAM_ENABLE_HOST_GLES
-#include "gl/EmulatedEglFenceSync.h"
-#endif
-
namespace gfxstream {
// kUseSubwindowThread is used to determine whether the RenderWindow should use
@@ -392,18 +389,14 @@
bool res = true;
res = fb->onLoad(stream, textureLoader);
-#if GFXSTREAM_ENABLE_HOST_GLES
gl::EmulatedEglFenceSync::onLoad(stream);
-#endif
return res;
}
void RendererImpl::fillGLESUsages(android_studio::EmulatorGLESUsages* usages) {
auto fb = FrameBuffer::getFB();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (fb) fb->fillGLESUsages(usages);
-#endif
}
int RendererImpl::getScreenshot(unsigned int nChannels, unsigned int* width, unsigned int* height,
@@ -595,7 +588,6 @@
FrameBuffer::getFB()->postWithCallback(handle, cb);
},
.repost = []() { FrameBuffer::getFB()->repost(); },
-#if GFXSTREAM_ENABLE_HOST_GLES
.create_yuv_textures =
[](uint32_t type, uint32_t count, int width, int height, uint32_t* output) {
FrameBuffer::getFB()->createYUVTextures(type, count, width, height, output);
@@ -614,15 +606,12 @@
FrameBuffer::getFB()->swapTexturesAndUpdateColorBuffer(
colorbufferhandle, x, y, width, height, format, type, texture_type, textures);
},
-#endif
.get_last_posted_color_buffer =
[]() { return FrameBuffer::getFB()->getLastPostedColorBuffer(); },
-#if GFXSTREAM_ENABLE_HOST_GLES
.bind_color_buffer_to_texture =
[](uint32_t handle) { FrameBuffer::getFB()->bindColorBufferToTexture2(handle); },
.get_global_egl_context = []() { return FrameBuffer::getFB()->getGlobalEGLContext(); },
.wait_for_gpu = [](uint64_t eglsync) { FrameBuffer::getFB()->waitForGpu(eglsync); },
-#endif
.wait_for_gpu_vulkan =
[](uint64_t device, uint64_t fence) {
FrameBuffer::getFB()->waitForGpuVulkan(device, fence);
@@ -631,12 +620,10 @@
[](bool guestManaged) {
FrameBuffer::getFB()->setGuestManagedColorBufferLifetime(guestManaged);
},
-#if GFXSTREAM_ENABLE_HOST_GLES
.async_wait_for_gpu_with_cb =
[](uint64_t eglsync, FenceCompletionCallback cb) {
FrameBuffer::getFB()->asyncWaitForGpuWithCb(eglsync, cb);
},
-#endif
.async_wait_for_gpu_vulkan_with_cb =
[](uint64_t device, uint64_t fence, FenceCompletionCallback cb) {
FrameBuffer::getFB()->asyncWaitForGpuVulkanWithCb(device, fence, cb);
@@ -662,14 +649,12 @@
[](uint32_t handle, int32_t* width, int32_t* height, int32_t* internal_format) {
return FrameBuffer::getFB()->getColorBufferInfo(handle, width, height, internal_format);
},
-#if GFXSTREAM_ENABLE_HOST_GLES
.platform_create_shared_egl_context =
[]() { return FrameBuffer::getFB()->platformCreateSharedEglContext(); },
.platform_destroy_shared_egl_context =
[](void* context) {
return FrameBuffer::getFB()->platformDestroySharedEglContext(context);
},
-#endif
};
struct AndroidVirtioGpuOps* RendererImpl::getVirtioGpuOps() {
@@ -724,19 +709,11 @@
}
const void* RendererImpl::getEglDispatch() {
-#if GFXSTREAM_ENABLE_HOST_GLES
return FrameBuffer::getFB()->getEglDispatch();
-#else
- return nullptr;
-#endif
}
const void* RendererImpl::getGles2Dispatch() {
-#if GFXSTREAM_ENABLE_HOST_GLES
return FrameBuffer::getFB()->getGles2Dispatch();
-#else
- return nullptr;
-#endif
}
} // namespace gfxstream
diff --git a/host/SyncThread.cpp b/host/SyncThread.cpp
index 5b1d1c1..5835387 100644
--- a/host/SyncThread.cpp
+++ b/host/SyncThread.cpp
@@ -16,10 +16,7 @@
#include "SyncThread.h"
-#if GFXSTREAM_ENABLE_HOST_GLES
#include "OpenGLESDispatch/OpenGLDispatchLoader.h"
-#endif
-
#include "aemu/base/Metrics.h"
#include "aemu/base/system/System.h"
#include "aemu/base/threads/Thread.h"
@@ -38,11 +35,8 @@
using android::base::EventHangMetadata;
using emugl::ABORT_REASON_OTHER;
using emugl::FatalError;
-
-#if GFXSTREAM_ENABLE_HOST_GLES
using gl::EGLDispatch;
using gl::EmulatedEglFenceSync;
-#endif
#define DEBUG 0
@@ -118,18 +112,15 @@
mHealthMonitor(healthMonitor) {
this->start();
mWorkerThreadPool.start();
-#if GFXSTREAM_ENABLE_HOST_GLES
if (hasGl) {
initSyncEGLContext();
}
-#endif
}
SyncThread::~SyncThread() {
cleanup();
}
-#if GFXSTREAM_ENABLE_HOST_GLES
void SyncThread::triggerWait(EmulatedEglFenceSync* fenceSync,
uint64_t timeline) {
std::stringstream ss;
@@ -145,6 +136,20 @@
ss.str());
}
+void SyncThread::triggerWaitVk(VkFence vkFence, uint64_t timeline) {
+ std::stringstream ss;
+ ss << "triggerWaitVk vkFence=0x" << std::hex << reinterpret_cast<uintptr_t>(vkFence)
+ << " timeline=0x" << std::hex << timeline;
+ sendAsync(
+ [vkFence, timeline](WorkerId) {
+ doSyncWaitVk(vkFence, [timeline] {
+ DPRINT("vk wait done, use goldfish sync timeline inc");
+ emugl::emugl_sync_timeline_inc(timeline, kTimelineInterval);
+ });
+ },
+ ss.str());
+}
+
void SyncThread::triggerBlockedWaitNoTimeline(EmulatedEglFenceSync* fenceSync) {
std::stringstream ss;
ss << "triggerBlockedWaitNoTimeline fenceSyncInfo=0x" << std::hex
@@ -166,6 +171,137 @@
ss.str());
}
+
+void SyncThread::triggerWaitVkWithCompletionCallback(VkFence vkFence, FenceCompletionCallback cb) {
+ std::stringstream ss;
+ ss << "triggerWaitVkWithCompletionCallback vkFence=0x" << std::hex
+ << reinterpret_cast<uintptr_t>(vkFence);
+ sendAsync([vkFence, cb = std::move(cb)](WorkerId) { doSyncWaitVk(vkFence, std::move(cb)); },
+ ss.str());
+}
+
+void SyncThread::triggerWaitVkQsriWithCompletionCallback(VkImage vkImage, FenceCompletionCallback cb) {
+ std::stringstream ss;
+ ss << "triggerWaitVkQsriWithCompletionCallback vkImage=0x"
+ << reinterpret_cast<uintptr_t>(vkImage);
+ sendAsync(
+ [vkImage, cb = std::move(cb)](WorkerId) {
+ auto decoder = vk::VkDecoderGlobalState::get();
+ auto res = decoder->registerQsriCallback(vkImage, cb);
+ // If registerQsriCallback does not schedule the callback, we still need to complete
+ // the task, otherwise we may hit deadlocks on tasks on the same ring.
+ if (!res.CallbackScheduledOrFired()) {
+ cb();
+ }
+ },
+ ss.str());
+}
+
+void SyncThread::triggerWaitVkQsri(VkImage vkImage, uint64_t timeline) {
+ std::stringstream ss;
+ ss << "triggerWaitVkQsri vkImage=0x" << std::hex << vkImage
+ << " timeline=0x" << std::hex << timeline;
+ sendAsync(
+ [vkImage, timeline](WorkerId) {
+ auto decoder = vk::VkDecoderGlobalState::get();
+ auto res = decoder->registerQsriCallback(vkImage, [timeline](){
+ emugl::emugl_sync_timeline_inc(timeline, kTimelineInterval);
+ });
+ // If registerQsriCallback does not schedule the callback, we still need to complete
+ // the task, otherwise we may hit deadlocks on tasks on the same ring.
+ if (!res.CallbackScheduledOrFired()) {
+ emugl::emugl_sync_timeline_inc(timeline, kTimelineInterval);
+ }
+ },
+ ss.str());
+}
+
+void SyncThread::triggerGeneral(FenceCompletionCallback cb, std::string description) {
+ std::stringstream ss;
+ ss << "triggerGeneral: " << description;
+ sendAsync(std::bind(std::move(cb)), ss.str());
+}
+
+void SyncThread::cleanup() {
+ sendAndWaitForResult(
+ [this](WorkerId workerId) {
+ if (mHasGl) {
+ const EGLDispatch* egl = gl::LazyLoadedEGLDispatch::get();
+
+ egl->eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+ egl->eglDestroyContext(mDisplay, mContext[workerId]);
+ egl->eglDestroySurface(mDisplay, mSurface[workerId]);
+ mContext[workerId] = EGL_NO_CONTEXT;
+ mSurface[workerId] = EGL_NO_SURFACE;
+ }
+ return 0;
+ },
+ "cleanup");
+ DPRINT("signal");
+ mLock.lock();
+ mExiting = true;
+ mCv.signalAndUnlock(&mLock);
+ DPRINT("exit");
+ // Wait for the control thread to exit. We can't destroy the SyncThread
+ // before we wait the control thread.
+ if (!wait(nullptr)) {
+ ERR("Fail to wait the control thread of the SyncThread to exit.");
+ }
+}
+
+// Private methods below////////////////////////////////////////////////////////
+
+intptr_t SyncThread::main() {
+ DPRINT("in sync thread");
+ mLock.lock();
+ mCv.wait(&mLock, [this] { return mExiting; });
+
+ mWorkerThreadPool.done();
+ mWorkerThreadPool.join();
+ DPRINT("exited sync thread");
+ return 0;
+}
+
+int SyncThread::sendAndWaitForResult(std::function<int(WorkerId)> job, std::string description) {
+ DPRINT("sendAndWaitForResult task(%s)", description.c_str());
+ std::packaged_task<int(WorkerId)> task(std::move(job));
+ std::future<int> resFuture = task.get_future();
+ Command command = {
+ .mTask = std::move(task),
+ .mDescription = std::move(description),
+ };
+
+ mWorkerThreadPool.enqueue(std::move(command));
+ auto res = resFuture.get();
+ DPRINT("exit");
+ return res;
+}
+
+void SyncThread::sendAsync(std::function<void(WorkerId)> job, std::string description) {
+ DPRINT("send task(%s)", description.c_str());
+ mWorkerThreadPool.enqueue(Command{
+ .mTask =
+ std::packaged_task<int(WorkerId)>([job = std::move(job)](WorkerId workerId) mutable {
+ job(workerId);
+ return 0;
+ }),
+ .mDescription = std::move(description),
+ });
+ DPRINT("exit");
+}
+
+void SyncThread::doSyncThreadCmd(Command&& command, WorkerId workerId) {
+ std::unique_ptr<std::unordered_map<std::string, std::string>> syncThreadData =
+ std::make_unique<std::unordered_map<std::string, std::string>>();
+ syncThreadData->insert({{"syncthread_cmd_desc", command.mDescription}});
+ auto watchdog = WATCHDOG_BUILDER(mHealthMonitor, "SyncThread task execution")
+ .setHangType(EventHangMetadata::HangType::kSyncThread)
+ .setAnnotations(std::move(syncThreadData))
+ .build();
+ command.mTask(workerId);
+}
+
void SyncThread::initSyncEGLContext() {
mWorkerThreadPool.broadcast([this] {
return Command{
@@ -238,10 +374,9 @@
DPRINT("wait on sync obj: %p", fenceSync);
wait_result = fenceSync->wait(kDefaultTimeoutNsecs);
- DPRINT(
- "done waiting, with wait result=0x%x. "
- "increment timeline (and signal fence)",
- wait_result);
+ DPRINT("done waiting, with wait result=0x%x. "
+ "increment timeline (and signal fence)",
+ wait_result);
if (wait_result != EGL_CONDITION_SATISFIED_KHR) {
EGLint error = gl::s_egl.eglGetError();
@@ -286,154 +421,6 @@
DPRINT("exit");
}
-#endif
-
-void SyncThread::triggerWaitVk(VkFence vkFence, uint64_t timeline) {
- std::stringstream ss;
- ss << "triggerWaitVk vkFence=0x" << std::hex << reinterpret_cast<uintptr_t>(vkFence)
- << " timeline=0x" << std::hex << timeline;
- sendAsync(
- [vkFence, timeline](WorkerId) {
- doSyncWaitVk(vkFence, [timeline] {
- DPRINT("vk wait done, use goldfish sync timeline inc");
- emugl::emugl_sync_timeline_inc(timeline, kTimelineInterval);
- });
- },
- ss.str());
-}
-
-void SyncThread::triggerWaitVkWithCompletionCallback(VkFence vkFence, FenceCompletionCallback cb) {
- std::stringstream ss;
- ss << "triggerWaitVkWithCompletionCallback vkFence=0x" << std::hex
- << reinterpret_cast<uintptr_t>(vkFence);
- sendAsync([vkFence, cb = std::move(cb)](WorkerId) { doSyncWaitVk(vkFence, std::move(cb)); },
- ss.str());
-}
-
-void SyncThread::triggerWaitVkQsriWithCompletionCallback(VkImage vkImage, FenceCompletionCallback cb) {
- std::stringstream ss;
- ss << "triggerWaitVkQsriWithCompletionCallback vkImage=0x"
- << reinterpret_cast<uintptr_t>(vkImage);
- sendAsync(
- [vkImage, cb = std::move(cb)](WorkerId) {
- auto decoder = vk::VkDecoderGlobalState::get();
- auto res = decoder->registerQsriCallback(vkImage, cb);
- // If registerQsriCallback does not schedule the callback, we still need to complete
- // the task, otherwise we may hit deadlocks on tasks on the same ring.
- if (!res.CallbackScheduledOrFired()) {
- cb();
- }
- },
- ss.str());
-}
-
-void SyncThread::triggerWaitVkQsri(VkImage vkImage, uint64_t timeline) {
- std::stringstream ss;
- ss << "triggerWaitVkQsri vkImage=0x" << std::hex << vkImage
- << " timeline=0x" << std::hex << timeline;
- sendAsync(
- [vkImage, timeline](WorkerId) {
- auto decoder = vk::VkDecoderGlobalState::get();
- auto res = decoder->registerQsriCallback(vkImage, [timeline](){
- emugl::emugl_sync_timeline_inc(timeline, kTimelineInterval);
- });
- // If registerQsriCallback does not schedule the callback, we still need to complete
- // the task, otherwise we may hit deadlocks on tasks on the same ring.
- if (!res.CallbackScheduledOrFired()) {
- emugl::emugl_sync_timeline_inc(timeline, kTimelineInterval);
- }
- },
- ss.str());
-}
-
-void SyncThread::triggerGeneral(FenceCompletionCallback cb, std::string description) {
- std::stringstream ss;
- ss << "triggerGeneral: " << description;
- sendAsync(std::bind(std::move(cb)), ss.str());
-}
-
-void SyncThread::cleanup() {
- sendAndWaitForResult(
- [this](WorkerId workerId) {
-#if GFXSTREAM_ENABLE_HOST_GLES
- if (mHasGl) {
- const EGLDispatch* egl = gl::LazyLoadedEGLDispatch::get();
-
- egl->eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
- egl->eglDestroyContext(mDisplay, mContext[workerId]);
- egl->eglDestroySurface(mDisplay, mSurface[workerId]);
- mContext[workerId] = EGL_NO_CONTEXT;
- mSurface[workerId] = EGL_NO_SURFACE;
- }
-#endif
- return 0;
- },
- "cleanup");
- DPRINT("signal");
- mLock.lock();
- mExiting = true;
- mCv.signalAndUnlock(&mLock);
- DPRINT("exit");
- // Wait for the control thread to exit. We can't destroy the SyncThread
- // before we wait the control thread.
- if (!wait(nullptr)) {
- ERR("Fail to wait the control thread of the SyncThread to exit.");
- }
-}
-
-// Private methods below////////////////////////////////////////////////////////
-
-intptr_t SyncThread::main() {
- DPRINT("in sync thread");
- mLock.lock();
- mCv.wait(&mLock, [this] { return mExiting; });
-
- mWorkerThreadPool.done();
- mWorkerThreadPool.join();
- DPRINT("exited sync thread");
- return 0;
-}
-
-int SyncThread::sendAndWaitForResult(std::function<int(WorkerId)> job, std::string description) {
- DPRINT("sendAndWaitForResult task(%s)", description.c_str());
- std::packaged_task<int(WorkerId)> task(std::move(job));
- std::future<int> resFuture = task.get_future();
- Command command = {
- .mTask = std::move(task),
- .mDescription = std::move(description),
- };
-
- mWorkerThreadPool.enqueue(std::move(command));
- auto res = resFuture.get();
- DPRINT("exit");
- return res;
-}
-
-void SyncThread::sendAsync(std::function<void(WorkerId)> job, std::string description) {
- DPRINT("send task(%s)", description.c_str());
- mWorkerThreadPool.enqueue(Command{
- .mTask =
- std::packaged_task<int(WorkerId)>([job = std::move(job)](WorkerId workerId) mutable {
- job(workerId);
- return 0;
- }),
- .mDescription = std::move(description),
- });
- DPRINT("exit");
-}
-
-void SyncThread::doSyncThreadCmd(Command&& command, WorkerId workerId) {
- std::unique_ptr<std::unordered_map<std::string, std::string>> syncThreadData =
- std::make_unique<std::unordered_map<std::string, std::string>>();
- syncThreadData->insert({{"syncthread_cmd_desc", command.mDescription}});
- auto watchdog = WATCHDOG_BUILDER(mHealthMonitor, "SyncThread task execution")
- .setHangType(EventHangMetadata::HangType::kSyncThread)
- .setAnnotations(std::move(syncThreadData))
- .build();
- command.mTask(workerId);
-}
-
int SyncThread::doSyncWaitVk(VkFence vkFence, std::function<void()> onComplete) {
DPRINT("enter");
@@ -473,4 +460,4 @@
void SyncThread::destroy() { sGlobalSyncThread()->destroy(); }
-} // namespace gfxstream
+} // namespace gfxstream
\ No newline at end of file
diff --git a/host/SyncThread.h b/host/SyncThread.h
index 1c84301..2710222 100644
--- a/host/SyncThread.h
+++ b/host/SyncThread.h
@@ -16,26 +16,23 @@
#pragma once
-#if GFXSTREAM_ENABLE_HOST_GLES
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
-#include "gl/EmulatedEglFenceSync.h"
-#endif
-
#include <functional>
#include <future>
#include <string>
#include <type_traits>
-#include "aemu/base/HealthMonitor.h"
-#include "aemu/base/Optional.h"
#include "aemu/base/synchronization/ConditionVariable.h"
+#include "aemu/base/HealthMonitor.h"
#include "aemu/base/synchronization/Lock.h"
#include "aemu/base/synchronization/MessageChannel.h"
+#include "aemu/base/Optional.h"
#include "aemu/base/threads/Thread.h"
#include "aemu/base/threads/ThreadPool.h"
+#include "gl/EmulatedEglFenceSync.h"
#include "render-utils/virtio_gpu_ops.h"
#include "vulkan/VkDecoderGlobalState.h"
@@ -57,6 +54,14 @@
SyncThread(bool hasGl, HealthMonitor<>* healthMonitor);
~SyncThread();
+ // |triggerWait|: async wait with a given EmulatedEglFenceSync object.
+ // We use the wait() method to do a eglClientWaitSyncKHR.
+ // After wait is over, the timeline will be incremented,
+ // which should signal the guest-side fence FD.
+ // This method is how the goldfish sync virtual device
+ // knows when to increment timelines / signal native fence FD's.
+ void triggerWait(gl::EmulatedEglFenceSync* fenceSync, uint64_t timeline);
+
// |triggerWaitVk|: async wait with a given VkFence object.
// The |vkFence| argument is a *boxed* host Vulkan handle of the fence.
//
@@ -67,36 +72,17 @@
// knows when to increment timelines / signal native fence FD's.
void triggerWaitVk(VkFence vkFence, uint64_t timeline);
-#if GFXSTREAM_ENABLE_HOST_GLES
- // |triggerWait|: async wait with a given EmulatedEglFenceSync object.
- // We use the wait() method to do a eglClientWaitSyncKHR.
- // After wait is over, the timeline will be incremented,
- // which should signal the guest-side fence FD.
- // This method is how the goldfish sync virtual device
- // knows when to increment timelines / signal native fence FD's.
- void triggerWait(gl::EmulatedEglFenceSync* fenceSync, uint64_t timeline);
-
// for use with the virtio-gpu path; is meant to have a current context
// while waiting.
void triggerBlockedWaitNoTimeline(gl::EmulatedEglFenceSync* fenceSync);
+
+ // This increments the timeline after the QSRI completes.
+ void triggerWaitVkQsri(VkImage vkImage, uint64_t timeline);
// For use with virtio-gpu and async fence completion callback. This is async like triggerWait,
// but takes a fence completion callback instead of incrementing some timeline directly.
void triggerWaitWithCompletionCallback(gl::EmulatedEglFenceSync* fenceSync,
FenceCompletionCallback);
-
- // |initSyncContext| creates an EGL context expressly for calling
- // eglClientWaitSyncKHR in the processing caused by |triggerWait|.
- // This is used by the constructor only. It is non-blocking.
- // - Triggers a |SyncThreadCmd| with op code |SYNC_THREAD_EGL_INIT|
- void initSyncEGLContext();
-
- void doSyncWait(gl::EmulatedEglFenceSync* fenceSync, std::function<void()> onComplete);
-#endif
-
- // This increments the timeline after the QSRI completes.
- void triggerWaitVkQsri(VkImage vkImage, uint64_t timeline);
-
void triggerWaitVkWithCompletionCallback(VkFence fenceHandle, FenceCompletionCallback);
void triggerWaitVkQsriWithCompletionCallback(VkImage image, FenceCompletionCallback);
void triggerGeneral(FenceCompletionCallback, std::string description);
@@ -125,6 +111,12 @@
};
using ThreadPool = android::base::ThreadPool<Command>;
+ // |initSyncContext| creates an EGL context expressly for calling
+ // eglClientWaitSyncKHR in the processing caused by |triggerWait|.
+ // This is used by the constructor only. It is non-blocking.
+ // - Triggers a |SyncThreadCmd| with op code |SYNC_THREAD_EGL_INIT|
+ void initSyncEGLContext();
+
// Thread function.
// It keeps the workers runner until |mExiting| is set.
virtual intptr_t main() override final;
@@ -140,17 +132,16 @@
// |doSyncThreadCmd| execute the actual task. These run on the sync thread.
void doSyncThreadCmd(Command&& command, ThreadPool::WorkerId);
+ void doSyncWait(gl::EmulatedEglFenceSync* fenceSync, std::function<void()> onComplete);
static int doSyncWaitVk(VkFence, std::function<void()> onComplete);
// EGL objects / object handles specific to
// a sync thread.
static const uint32_t kNumWorkerThreads = 4u;
-#if GFXSTREAM_ENABLE_HOST_GLES
EGLDisplay mDisplay = EGL_NO_DISPLAY;
EGLSurface mSurface[kNumWorkerThreads];
EGLContext mContext[kNumWorkerThreads];
-#endif
bool mExiting = false;
android::base::Lock mLock;
diff --git a/host/meson.build b/host/meson.build
index 9a35912..1d9b4c8 100644
--- a/host/meson.build
+++ b/host/meson.build
@@ -94,14 +94,6 @@
use_magma = host_machine.system() == 'linux'
endif
-gfxstream_host_args += '-DGFXSTREAM_ENABLE_HOST_GLES=@0@'.format(use_gles ? '1' : '0')
-if use_magma
- gfxstream_host_args += '-DUSE_MAGMA=1'
- drm_dep = dependency('libdrm')
-else
- gfxstream_host_args += '-DUSE_MAGMA=0'
-endif
-
if use_magma
gfxstream_host_args += '-DGFXSTREAM_ENABLE_HOST_GLES=1'
drm_dep = dependency('libdrm')
@@ -155,7 +147,7 @@
inc_gfxstream_backend = [inc_root, inc_include, inc_apigen_codec, inc_utils,
inc_gl_host_common, inc_host_include]
-link_gfxstream_backend = [lib_gl_host_common, lib_apigen_codec]
+link_gfxstream_backend = [lib_gl_host_common]
files_lib_gfxstream_backend = files(
'Buffer.cpp',
@@ -173,6 +165,7 @@
'RenderThreadInfo.cpp',
'RingStream.cpp',
'SyncThread.cpp',
+ 'RenderControl.cpp',
'RenderWindow.cpp',
'RenderLibImpl.cpp',
'RendererImpl.cpp',
@@ -192,7 +185,6 @@
files_lib_gfxstream_backend += files('PostWorkerGl.cpp')
files_lib_gfxstream_backend += files('RenderThreadInfoGl.cpp')
- files_lib_gfxstream_backend += files('RenderControl.cpp')
inc_gfxstream_backend += [inc_gl_server, inc_gl_snapshot, inc_gles_translator]
link_gfxstream_backend += lib_gl_server
@@ -217,13 +209,11 @@
link_gfxstream_backend += lib_magma_server
endif
-if not use_gles
- files_lib_gfxstream_backend += files('NativeSubWindow_stub.cpp')
-elif host_machine.system() == 'darwin'
+if host_machine.system() == 'darwin'
files_lib_gfxstream_backend += files('NativeSubWindow_cocoa.m')
elif host_machine.system() == 'windows'
files_lib_gfxstream_backend += files('NativeSubWindow_win32.cpp')
-elif host_machine.system() == 'linux' and use_gles
+elif host_machine.system() == 'linux'
files_lib_gfxstream_backend += files('NativeSubWindow_x11.cpp')
elif host_machine.system() == 'qnx'
files_lib_gfxstream_backend += files(
diff --git a/host/renderControl_dec/renderControl_types.h b/host/renderControl_dec/renderControl_types.h
index f265e06..fb5ced9 100644
--- a/host/renderControl_dec/renderControl_types.h
+++ b/host/renderControl_dec/renderControl_types.h
@@ -18,4 +18,13 @@
#include <EGL/egl.h>
#include "glUtils.h"
+// values for 'param' argument of rcGetFBParam
+#define FB_WIDTH 1
+#define FB_HEIGHT 2
+#define FB_XDPI 3
+#define FB_YDPI 4
+#define FB_FPS 5
+#define FB_MIN_SWAP_INTERVAL 6
+#define FB_MAX_SWAP_INTERVAL 7
+
using RenderControlByte = char;
diff --git a/host/vulkan/emulated_textures/meson.build b/host/vulkan/emulated_textures/meson.build
index d3e6f45..06f8181 100644
--- a/host/vulkan/emulated_textures/meson.build
+++ b/host/vulkan/emulated_textures/meson.build
@@ -17,6 +17,5 @@
cpp_args: emulated_texture_args + gfxstream_host_args,
include_directories: [inc_utils, inc_root, inc_vulkan_headers, inc_vulkan_server,
inc_include, inc_cereal_common, inc_stream_servers],
- link_with: [lib_compressed_textures],
dependencies: [aemu_base_dep, aemu_common_dep]
)