summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-05-07 00:29:35 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-05-07 00:29:35 +0000
commit7da7662377165edbf9ec59f722a3ef208ff3d9e6 (patch)
tree95ac76eff2fc387ee5ebac0a3bf8d18ee0df2459
parented03f529fb0d847ee0e838af2c0017e3098b83b0 (diff)
parent85532f3dc56bdb461e1c5b7da20d514aa67ff66d (diff)
downloadvulkan-cereal-7da7662377165edbf9ec59f722a3ef208ff3d9e6.tar.gz
Snap for 7343852 from 85532f3dc56bdb461e1c5b7da20d514aa67ff66d to sc-mainline-release
Change-Id: I841b294e6da150bb3b1d1ce501e5ec40386b0b32
-rw-r--r--README.md4
-rw-r--r--base/MruCache.h1
-rw-r--r--base/ThreadPool.h1
-rw-r--r--protocols/renderControl/renderControl.in3
-rw-r--r--stream-servers/ColorBuffer.cpp2
-rw-r--r--stream-servers/CompositorVk.cpp259
-rw-r--r--stream-servers/CompositorVk.h37
-rw-r--r--stream-servers/DisplayVk.cpp179
-rw-r--r--stream-servers/DisplayVk.h24
-rw-r--r--stream-servers/FrameBuffer.cpp69
-rw-r--r--stream-servers/FrameBuffer.h39
-rw-r--r--stream-servers/GfxStreamAgents.cpp162
-rw-r--r--stream-servers/PostCommands.h40
-rw-r--r--stream-servers/PostWorker.cpp22
-rw-r--r--stream-servers/PostWorker.h2
-rw-r--r--stream-servers/RenderControl.cpp25
-rw-r--r--stream-servers/SyncThread.cpp17
-rw-r--r--stream-servers/YUVConverter.cpp3
-rw-r--r--stream-servers/glestranslator/EGL/EglOsApi_egl.cpp4
-rw-r--r--stream-servers/glestranslator/EGL/ShaderCache.cpp1
-rw-r--r--stream-servers/renderControl_dec/renderControl_dec.cpp43
-rw-r--r--stream-servers/renderControl_dec/renderControl_opcodes.h4
-rw-r--r--stream-servers/renderControl_dec/renderControl_server_context.cpp2
-rw-r--r--stream-servers/renderControl_dec/renderControl_server_context.h2
-rw-r--r--stream-servers/renderControl_dec/renderControl_server_proc.h2
-rw-r--r--stream-servers/virtio-gpu-gfxstream-renderer.cpp8
-rw-r--r--stream-servers/vulkan/Compositor.vert9
-rw-r--r--stream-servers/vulkan/CompositorVertexShader.h101
-rw-r--r--stream-servers/vulkan/VkAndroidNativeBuffer.cpp5
29 files changed, 796 insertions, 274 deletions
diff --git a/README.md b/README.md
index ef1f4451..d00d326b 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,9 @@ and forward graphics API calls from one place to another:
# Build: Linux
Make sure the latest CMake is installed.
-Make sure you are using Clang as your `CC` and `CXX`. Then
+Make sure the opengl lib is installed. Otherwise, sudo apt-get install
+libglu1-mesa-dev freeglut3-dev mesa-common-dev
+Make sure you are using Clang as your `CC` and clang++ as your`CXX`. Then
mkdir build
cd build
diff --git a/base/MruCache.h b/base/MruCache.h
index 36a09ad3..0649e8e5 100644
--- a/base/MruCache.h
+++ b/base/MruCache.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_BASE_MRUCACHE_
#define ANDROID_BASE_MRUCACHE_
+#include <algorithm>
#include <list>
#include <map>
diff --git a/base/ThreadPool.h b/base/ThreadPool.h
index ceacd10e..f21a628d 100644
--- a/base/ThreadPool.h
+++ b/base/ThreadPool.h
@@ -121,6 +121,7 @@ public:
void enqueue(Item&& item) {
// Iterate over the worker threads until we find a one that's running.
+ // TODO(b/187082169, warty): We rely on this round-robin strategy in SyncThread
for (;;) {
int currentIndex =
mNextWorkerIndex.fetch_add(1, std::memory_order_relaxed);
diff --git a/protocols/renderControl/renderControl.in b/protocols/renderControl/renderControl.in
index 47c41c66..5be924e7 100644
--- a/protocols/renderControl/renderControl.in
+++ b/protocols/renderControl/renderControl.in
@@ -60,4 +60,5 @@ GL_ENTRY(void, rcComposeAsync, uint32_t bufferSize, void *buffer);
GL_ENTRY(void, rcDestroySyncKHRAsync, uint64_t sync);
GL_ENTRY(GLint, rcComposeWithoutPost, uint32_t bufferSize, void *buffer);
GL_ENTRY(void, rcComposeAsyncWithoutPost, uint32_t bufferSize, void *buffer);
-
+GL_ENTRY(int, rcCreateDisplayById, uint32_t displayId);
+GL_ENTRY(int, rcSetDisplayPoseDpi, uint32_t displayId, GLint x, GLint y, uint32_t w, uint32_t h, uint32_t dpi);
diff --git a/stream-servers/ColorBuffer.cpp b/stream-servers/ColorBuffer.cpp
index b36c8710..a01002f6 100644
--- a/stream-servers/ColorBuffer.cpp
+++ b/stream-servers/ColorBuffer.cpp
@@ -21,6 +21,8 @@
#include "TextureDraw.h"
#include "TextureResize.h"
#include "YUVConverter.h"
+#include "vulkan/VulkanDispatch.h"
+#include "vulkan/VkCommonOperations.h"
#include "OpenGLESDispatch/DispatchTables.h"
#include "OpenGLESDispatch/EGLDispatch.h"
diff --git a/stream-servers/CompositorVk.cpp b/stream-servers/CompositorVk.cpp
index 7be39256..5e17d26b 100644
--- a/stream-servers/CompositorVk.cpp
+++ b/stream-servers/CompositorVk.cpp
@@ -2,9 +2,11 @@
#include <string.h>
-#include <glm/gtx/matrix_transform_2d.hpp>
+#include <cinttypes>
+#include <glm/gtc/matrix_transform.hpp>
#include <optional>
+#include "ErrorLog.h"
#include "vulkan/vk_util.h"
namespace CompositorVkShader {
@@ -24,13 +26,99 @@ static VkShaderModule createShaderModule(const goldfish_vk::VulkanDispatch &vk,
return res;
}
-Composition::Composition(VkImageView vkImageView, VkSampler vkSampler,
- uint32_t width, uint32_t height)
- : m_vkImageView(vkImageView),
- m_vkSampler(vkSampler),
- m_width(width),
- m_height(height),
- m_transform(1.0f) {}
+ComposeLayerVk::ComposeLayerVk(VkSampler vkSampler, VkImageView vkImageView,
+ const LayerTransform &layerTransform)
+ : m_vkSampler(vkSampler),
+ m_vkImageView(vkImageView),
+ m_layerTransform(
+ {.pos = layerTransform.pos, .texcoord = layerTransform.texcoord}) {}
+
+std::unique_ptr<ComposeLayerVk> ComposeLayerVk::createFromHwc2ComposeLayer(
+ VkSampler vkSampler, VkImageView vkImageView,
+ const ComposeLayer &composeLayer, uint32_t cbWidth, uint32_t cbHeight,
+ uint32_t dstWidth, uint32_t dstHeight) {
+ // Calculate the posTransform and the texcoordTransform needed in the
+ // uniform of the Compositor.vert shader. The posTransform should transform
+ // the square(top = -1, bottom = 1, left = -1, right = 1) to the position
+ // where the layer should be drawn in NDC space given the composeLayer.
+ // texcoordTransform should transform the unit square(top = 0, bottom = 1,
+ // left = 0, right = 1) to where we should sample the layer in the
+ // normalized uv space given the composeLayer.
+ const hwc_rect_t &posRect = composeLayer.displayFrame;
+ const hwc_frect_t &texcoordRect = composeLayer.crop;
+
+ int posWidth = posRect.right - posRect.left;
+ int posHeight = posRect.bottom - posRect.top;
+
+ float posScaleX = float(posWidth) / dstWidth;
+ float posScaleY = float(posHeight) / dstHeight;
+
+ float posTranslateX =
+ -1.0f + posScaleX + 2.0f * float(posRect.left) / dstWidth;
+ float posTranslateY =
+ -1.0f + posScaleY + 2.0f * float(posRect.top) / dstHeight;
+
+ float texcoordScalX =
+ (texcoordRect.right - texcoordRect.left) / float(cbWidth);
+ float texCoordScaleY =
+ (texcoordRect.bottom - texcoordRect.top) / float(cbHeight);
+
+ float texCoordTranslateX = texcoordRect.left / float(cbWidth);
+ float texCoordTranslateY = texcoordRect.top / float(cbHeight);
+
+ float texcoordRotation = 0.0f;
+
+ const float pi = glm::pi<float>();
+
+ switch (composeLayer.transform) {
+ case HWC_TRANSFORM_ROT_90:
+ texcoordRotation = pi * 0.5f;
+ break;
+ case HWC_TRANSFORM_ROT_180:
+ texcoordRotation = pi;
+ break;
+ case HWC_TRANSFORM_ROT_270:
+ texcoordRotation = pi * 1.5f;
+ break;
+ case HWC_TRANSFORM_FLIP_H:
+ texcoordScalX *= -1.0f;
+ break;
+ case HWC_TRANSFORM_FLIP_V:
+ texCoordScaleY *= -1.0f;
+ break;
+ case HWC_TRANSFORM_FLIP_H_ROT_90:
+ texcoordRotation = pi * 0.5f;
+ texcoordScalX *= -1.0f;
+ break;
+ case HWC_TRANSFORM_FLIP_V_ROT_90:
+ texcoordRotation = pi * 0.5f;
+ texCoordScaleY *= -1.0f;
+ break;
+ default:
+ break;
+ }
+
+ ComposeLayerVk::LayerTransform layerTransform = {
+ .pos =
+ glm::translate(glm::mat4(1.0f),
+ glm::vec3(posTranslateX, posTranslateY, 0.0f)) *
+ glm::scale(glm::mat4(1.0f), glm::vec3(posScaleX, posScaleY, 1.0f)),
+ .texcoord = glm::translate(glm::mat4(1.0f),
+ glm::vec3(texCoordTranslateX,
+ texCoordTranslateY, 0.0f)) *
+ glm::scale(glm::mat4(1.0f),
+ glm::vec3(texcoordScalX, texCoordScaleY, 1.0f)) *
+ glm::rotate(glm::mat4(1.0f), texcoordRotation,
+ glm::vec3(0.0f, 0.0f, 1.0f)),
+ };
+
+ return std::unique_ptr<ComposeLayerVk>(
+ new ComposeLayerVk(vkSampler, vkImageView, layerTransform));
+}
+
+Composition::Composition(
+ std::vector<std::unique_ptr<ComposeLayerVk>> composeLayers)
+ : m_composeLayers(std::move(composeLayers)) {}
const std::vector<CompositorVk::Vertex> CompositorVk::k_vertices = {
{{-1.0f, -1.0f}, {0.0f, 0.0f}},
@@ -61,11 +149,9 @@ std::unique_ptr<CompositorVk> CompositorVk::create(
res->setUpEmptyComposition(format);
res->m_currentCompositions.resize(renderTargets.size());
for (auto i = 0; i < renderTargets.size(); i++) {
- res->setComposition(
- i, std::make_unique<Composition>(res->m_emptyCompositionVkImageView,
- res->m_emptyCompositionVkSampler,
- k_emptyCompositionExtent.width,
- k_emptyCompositionExtent.height));
+ std::vector<std::unique_ptr<ComposeLayerVk>> emptyCompositionLayers;
+ res->setComposition(i, std::make_unique<Composition>(
+ std::move(emptyCompositionLayers)));
}
return res;
}
@@ -84,6 +170,9 @@ CompositorVk::CompositorVk(const goldfish_vk::VulkanDispatch &vk,
m_emptyCompositionVkSampler(VK_NULL_HANDLE),
m_currentCompositions(0),
m_uniformStorage({VK_NULL_HANDLE, VK_NULL_HANDLE, nullptr, 0}) {
+ (void)m_renderTargetWidth;
+ (void)m_renderTargetHeight;
+
VkPhysicalDeviceProperties physicalDeviceProperties;
m_vk.vkGetPhysicalDeviceProperties(m_vkPhysicalDevice,
&physicalDeviceProperties);
@@ -203,12 +292,12 @@ void CompositorVk::setUpGraphicsPipeline(uint32_t width, uint32_t height,
VkPipelineColorBlendAttachmentState colorBlendAttachment = {
.blendEnable = VK_TRUE,
- .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
+ .srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
.colorBlendOp = VK_BLEND_OP_ADD,
- .srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
- .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
- .alphaBlendOp = VK_BLEND_OP_MAX,
+ .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
+ .dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+ .alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
@@ -433,35 +522,42 @@ void CompositorVk::setUpFramebuffers(
}
}
+// We don't see composition requests with more than 10 layers from the guest for
+// now. If we see rendering error or significant time spent on updating
+// descriptors in setComposition, we should tune this number.
+static const uint32_t kMaxLayersPerFrame = 10;
+
void CompositorVk::setUpDescriptorSets() {
uint32_t numOfFrames =
static_cast<uint32_t>(m_renderTargetVkFrameBuffers.size());
+ uint32_t setsPerDescriptorType = numOfFrames * kMaxLayersPerFrame;
+
VkDescriptorPoolSize descriptorPoolSizes[2] = {
{.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .descriptorCount = numOfFrames},
+ .descriptorCount = setsPerDescriptorType},
{.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
- .descriptorCount = numOfFrames}};
+ .descriptorCount = setsPerDescriptorType}};
VkDescriptorPoolCreateInfo descriptorPoolCi = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT,
- .maxSets = static_cast<uint32_t>(numOfFrames),
+ .maxSets = static_cast<uint32_t>(setsPerDescriptorType),
.poolSizeCount = static_cast<uint32_t>(std::size(descriptorPoolSizes)),
.pPoolSizes = descriptorPoolSizes};
VK_CHECK(m_vk.vkCreateDescriptorPool(m_vkDevice, &descriptorPoolCi, nullptr,
&m_vkDescriptorPool));
- std::vector<VkDescriptorSetLayout> layouts(numOfFrames,
+ std::vector<VkDescriptorSetLayout> layouts(setsPerDescriptorType,
m_vkDescriptorSetLayout);
VkDescriptorSetAllocateInfo descriptorSetAllocInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = m_vkDescriptorPool,
- .descriptorSetCount = numOfFrames,
+ .descriptorSetCount = setsPerDescriptorType,
.pSetLayouts = layouts.data()};
- m_vkDescriptorSets.resize(numOfFrames);
+ m_vkDescriptorSets.resize(setsPerDescriptorType);
VK_CHECK(m_vk.vkAllocateDescriptorSets(m_vkDevice, &descriptorSetAllocInfo,
m_vkDescriptorSets.data()));
- for (size_t i = 0; i < numOfFrames; i++) {
+ for (size_t i = 0; i < setsPerDescriptorType; i++) {
VkDescriptorBufferInfo bufferInfo = {
.buffer = m_uniformStorage.m_vkBuffer,
.offset = i * m_uniformStorage.m_stride,
@@ -514,11 +610,14 @@ void CompositorVk::setUpCommandBuffers(uint32_t width, uint32_t height) {
offsets);
m_vk.vkCmdBindIndexBuffer(cmdBuffer, m_indexVkBuffer, 0,
VK_INDEX_TYPE_UINT16);
- m_vk.vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- m_vkPipelineLayout, 0, 1,
- &m_vkDescriptorSets[i], 0, nullptr);
- m_vk.vkCmdDrawIndexed(
- cmdBuffer, static_cast<uint32_t>(k_indices.size()), 1, 0, 0, 0);
+ for (uint32_t j = 0; j < kMaxLayersPerFrame; ++j) {
+ m_vk.vkCmdBindDescriptorSets(
+ cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_vkPipelineLayout,
+ 0, 1, &m_vkDescriptorSets[i * kMaxLayersPerFrame + j], 0,
+ nullptr);
+ m_vk.vkCmdDrawIndexed(
+ cmdBuffer, static_cast<uint32_t>(k_indices.size()), 1, 0, 0, 0);
+ }
m_vk.vkCmdEndRenderPass(cmdBuffer);
VK_CHECK(m_vk.vkEndCommandBuffer(cmdBuffer));
@@ -617,7 +716,8 @@ void CompositorVk::setUpEmptyComposition(VkFormat format) {
void CompositorVk::setUpUniformBuffers() {
auto numOfFrames = m_renderTargetVkFrameBuffers.size();
- VkDeviceSize size = m_uniformStorage.m_stride * numOfFrames;
+ VkDeviceSize size =
+ m_uniformStorage.m_stride * numOfFrames * kMaxLayersPerFrame;
auto maybeBuffer = createBuffer(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
@@ -677,46 +777,65 @@ VkCommandBuffer CompositorVk::getCommandBuffer(uint32_t i) const {
return m_vkCommandBuffers[i];
}
-void CompositorVk::setComposition(uint32_t i,
+void CompositorVk::setComposition(uint32_t rtIndex,
std::unique_ptr<Composition> &&composition) {
- m_currentCompositions[i] = std::move(composition);
- const auto &currentComposition = *m_currentCompositions[i];
- VkDescriptorImageInfo imageInfo = {
- .sampler = currentComposition.m_vkSampler,
- .imageView = currentComposition.m_vkImageView,
- .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
- VkWriteDescriptorSet descriptorSetWrite = {
- .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
- .dstSet = m_vkDescriptorSets[i],
- .dstBinding = 0,
- .dstArrayElement = 0,
- .descriptorCount = 1,
- .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
- .pImageInfo = &imageInfo};
- m_vk.vkUpdateDescriptorSets(m_vkDevice, 1, &descriptorSetWrite, 0, nullptr);
-
- auto local2screen = glm::translate(glm::mat3(1.0f), glm::vec2(1.0f, 1.0f));
- local2screen =
- glm::scale(
- glm::mat3(1.0f),
- glm::vec2(static_cast<float>(currentComposition.m_width) / 2.0f,
- static_cast<float>(currentComposition.m_height) / 2.0f)) *
- local2screen;
- auto screen2ndc =
- glm::scale(glm::mat3(1.0f),
- glm::vec2(2.0f / static_cast<float>(m_renderTargetWidth),
- 2.0f / static_cast<float>(m_renderTargetHeight)));
- screen2ndc =
- glm::translate(glm::mat3(1.0f), glm::vec2(-1.0f, -1.0f)) * screen2ndc;
- auto t = screen2ndc * currentComposition.m_transform * local2screen;
- UniformBufferObject ubo{};
- ubo.transform = glm::mat4(glm::vec4(t[0][0], t[0][1], 0.0f, t[0][2]),
- glm::vec4(t[1][0], t[1][1], 0.0f, t[1][2]),
- glm::vec4(0.0f, 0.0f, 0.0f, 0.0f),
- glm::vec4(t[2][0], t[2][1], 0.0f, t[2][2]));
- memcpy(reinterpret_cast<uint8_t *>(m_uniformStorage.m_data) +
- i * m_uniformStorage.m_stride,
- &ubo, sizeof(ubo));
+ m_currentCompositions[rtIndex] = std::move(composition);
+ const auto &currentComposition = *m_currentCompositions[rtIndex];
+ if (currentComposition.m_composeLayers.size() > kMaxLayersPerFrame) {
+ ERR("%s(%s:%d): CompositorVk can't compose more than %" PRIu32
+ " layers, %" PRIu32 " layers asked.\n",
+ __FUNCTION__, __FILE__, static_cast<int>(__LINE__),
+ kMaxLayersPerFrame,
+ static_cast<uint32_t>(currentComposition.m_composeLayers.size()));
+ }
+
+ memset(reinterpret_cast<uint8_t *>(m_uniformStorage.m_data) +
+ (rtIndex * kMaxLayersPerFrame + 0) * m_uniformStorage.m_stride,
+ 0, sizeof(ComposeLayerVk::LayerTransform) * kMaxLayersPerFrame);
+
+ std::vector<VkDescriptorImageInfo> imageInfos(
+ currentComposition.m_composeLayers.size());
+ std::vector<VkWriteDescriptorSet> descriptorWrites;
+ for (size_t i = 0; i < currentComposition.m_composeLayers.size(); ++i) {
+ const auto &layer = currentComposition.m_composeLayers[i];
+ imageInfos[i] = VkDescriptorImageInfo(
+ {.sampler = layer->m_vkSampler,
+ .imageView = layer->m_vkImageView,
+ .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL});
+ const VkDescriptorImageInfo &imageInfo = imageInfos[i];
+ descriptorWrites.emplace_back(VkWriteDescriptorSet(
+ {.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = m_vkDescriptorSets[rtIndex * kMaxLayersPerFrame + i],
+ .dstBinding = 0,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .pImageInfo = &imageInfo}));
+ memcpy(
+ reinterpret_cast<uint8_t *>(m_uniformStorage.m_data) +
+ (rtIndex * kMaxLayersPerFrame + i) * m_uniformStorage.m_stride,
+ &layer->m_layerTransform, sizeof(ComposeLayerVk::LayerTransform));
+ }
+ m_vk.vkUpdateDescriptorSets(m_vkDevice, descriptorWrites.size(),
+ descriptorWrites.data(), 0, nullptr);
+
+ for (size_t i = currentComposition.m_composeLayers.size();
+ i < kMaxLayersPerFrame; ++i) {
+ VkDescriptorImageInfo imageInfo = {
+ .sampler = m_emptyCompositionVkSampler,
+ .imageView = m_emptyCompositionVkImageView,
+ .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
+ VkWriteDescriptorSet descriptorSetWrite = {
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ .dstSet = m_vkDescriptorSets[rtIndex * kMaxLayersPerFrame + i],
+ .dstBinding = 0,
+ .dstArrayElement = 0,
+ .descriptorCount = 1,
+ .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ .pImageInfo = &imageInfo};
+ m_vk.vkUpdateDescriptorSets(m_vkDevice, 1, &descriptorSetWrite, 0,
+ nullptr);
+ }
}
VkVertexInputBindingDescription CompositorVk::Vertex::getBindingDescription() {
@@ -737,4 +856,4 @@ CompositorVk::Vertex::getAttributeDescription() {
.binding = 0,
.format = VK_FORMAT_R32G32_SFLOAT,
.offset = offsetof(struct Vertex, texPos)}};
-} \ No newline at end of file
+}
diff --git a/stream-servers/CompositorVk.h b/stream-servers/CompositorVk.h
index 91551574..97a21a2d 100644
--- a/stream-servers/CompositorVk.h
+++ b/stream-servers/CompositorVk.h
@@ -12,19 +12,35 @@
#include "vulkan/cereal/common/goldfish_vk_dispatch.h"
#include "vulkan/vk_util.h"
-class Composition {
+#include "Hwc2.h"
+
+class ComposeLayerVk {
public:
- VkImageView m_vkImageView;
VkSampler m_vkSampler;
- uint32_t m_width;
- uint32_t m_height;
+ VkImageView m_vkImageView;
+ struct LayerTransform {
+ glm::mat4 pos;
+ glm::mat4 texcoord;
+ } m_layerTransform;
+
+ static std::unique_ptr<ComposeLayerVk> createFromHwc2ComposeLayer(
+ VkSampler, VkImageView, const ComposeLayer &, uint32_t cbWidth,
+ uint32_t cbHeight, uint32_t dstWidth, uint32_t dstHeight);
- // transform matrix in screen coordinates
- glm::mat3 m_transform;
+ private:
+ ComposeLayerVk() = delete;
+ explicit ComposeLayerVk(VkSampler, VkImageView, const LayerTransform &);
+};
+
+// If we want to apply transform to all layers to rotate/clip/position the
+// virtual display, we should add that functionality here.
+class Composition {
+ public:
+ std::vector<std::unique_ptr<ComposeLayerVk>> m_composeLayers;
Composition() = delete;
- explicit Composition(VkImageView, VkSampler, uint32_t width,
- uint32_t height);
+ explicit Composition(
+ std::vector<std::unique_ptr<ComposeLayerVk>> composeLayers);
};
struct CompositorVkBase
@@ -117,7 +133,8 @@ class CompositorVk : protected CompositorVkBase {
void copyBuffer(VkBuffer src, VkBuffer dst, VkDeviceSize) const;
struct UniformBufferObject {
- alignas(16) glm::mat4 transform;
+ alignas(16) glm::mat4 pos_transform;
+ alignas(16) glm::mat4 texcoord_transform;
};
struct Vertex {
@@ -149,4 +166,4 @@ class CompositorVk : protected CompositorVkBase {
} m_uniformStorage;
};
-#endif /* COMPOSITOR_VK_H */ \ No newline at end of file
+#endif /* COMPOSITOR_VK_H */
diff --git a/stream-servers/DisplayVk.cpp b/stream-servers/DisplayVk.cpp
index 62fc66c7..c1552876 100644
--- a/stream-servers/DisplayVk.cpp
+++ b/stream-servers/DisplayVk.cpp
@@ -116,13 +116,65 @@ std::shared_ptr<DisplayVk::DisplayBufferInfo> DisplayVk::createDisplayBuffer(
void DisplayVk::post(
const std::shared_ptr<DisplayBufferInfo> &displayBufferPtr) {
- if (m_swapChainStateVk == nullptr || m_compositorVk == nullptr) {
- ERR("%s(%s:%d): Haven't bound to a surface, can't post color buffer.\n",
+ if (!displayBufferPtr) {
+ fprintf(stderr, "%s: warning: null ptr passed to post buffer\n",
+ __func__);
+ return;
+ }
+ ComposeLayer composeLayer = {
+ 0,
+ HWC2_COMPOSITION_DEVICE,
+ {0, 0, static_cast<int>(displayBufferPtr->m_width),
+ static_cast<int>(displayBufferPtr->m_height)},
+ {0.0f, 0.0f, static_cast<float>(displayBufferPtr->m_width),
+ static_cast<float>(displayBufferPtr->m_height)},
+ HWC2_BLEND_MODE_PREMULTIPLIED,
+ 1.0f,
+ {0, 0, 0, 0},
+ static_cast<hwc_transform_t>(0) /* transform */
+ };
+ compose(1, &composeLayer, {std::move(displayBufferPtr)});
+}
+
+void DisplayVk::compose(
+ uint32_t numLayers, const ComposeLayer layers[],
+ const std::vector<std::shared_ptr<DisplayBufferInfo>> &composeBuffers) {
+ if (!m_swapChainStateVk || !m_compositorVk || !m_surfaceState) {
+ ERR("%s(%s:%d): Haven't bound to a surface, can't compose color "
+ "buffer.\n",
__FUNCTION__, __FILE__, static_cast<int>(__LINE__));
return;
}
+
auto &surfaceState = *m_surfaceState;
- const auto &db = *displayBufferPtr;
+ std::vector<std::unique_ptr<ComposeLayerVk>> composeLayers;
+ for (int i = 0; i < numLayers; ++i) {
+ if (!composeBuffers[i]) {
+ fprintf(
+ stderr,
+ "%s: warning: null ptr passed to compose buffer for layer %d\n",
+ __func__, i);
+ continue;
+ }
+ const auto &db = *composeBuffers[i];
+ if (!canComposite(db.m_vkFormat)) {
+ ERR("%s(%s:%d): Can't composite the DisplayBuffer(0x%" PRIxPTR
+ "). The image(VkFormat = %" PRIu64 ") can't be sampled from.\n",
+ __FUNCTION__, __FILE__, static_cast<int>(__LINE__),
+ reinterpret_cast<uintptr_t>(&db),
+ static_cast<uint64_t>(db.m_vkFormat));
+ continue;
+ }
+ auto layer = ComposeLayerVk::createFromHwc2ComposeLayer(
+ m_compositionVkSampler, composeBuffers[i]->m_vkImageView, layers[i],
+ composeBuffers[i]->m_width, composeBuffers[i]->m_height,
+ surfaceState.m_width, surfaceState.m_height);
+ composeLayers.emplace_back(std::move(layer));
+ }
+
+ if (composeLayers.empty()) {
+ return;
+ }
VK_CHECK(m_vk.vkWaitForFences(m_vkDevice, 1, &m_frameDrawCompleteFence,
VK_TRUE, UINT64_MAX));
@@ -130,26 +182,12 @@ void DisplayVk::post(
VK_CHECK(m_vk.vkAcquireNextImageKHR(
m_vkDevice, m_swapChainStateVk->getSwapChain(), UINT64_MAX,
m_imageReadySem, VK_NULL_HANDLE, &imageIndex));
- auto maybePrevDisplayBuffer = surfaceState.m_prevDisplayBuffer.lock();
- if (!maybePrevDisplayBuffer || maybePrevDisplayBuffer != displayBufferPtr) {
- if (!canComposite(db.m_vkFormat)) {
- ERR("%s(%s:%d): Can't composite the DisplayBuffer(0x%" PRIxPTR
- "). The image(VkFormat = %" PRIu64 ") can be sampled from.\n",
- __FUNCTION__, __FILE__, static_cast<int>(__LINE__),
- reinterpret_cast<uintptr_t>(displayBufferPtr.get()),
- static_cast<uint64_t>(db.m_vkFormat));
- return;
- }
- auto composition = std::make_unique<Composition>(
- db.m_vkImageView, m_compositionVkSampler, db.m_width, db.m_height);
- composition->m_transform =
- glm::scale(glm::mat3(1.0),
- glm::vec2(static_cast<float>(surfaceState.m_width) /
- static_cast<float>(db.m_width),
- static_cast<float>(surfaceState.m_height) /
- static_cast<float>(db.m_height)));
+
+ if (compareAndSaveComposition(imageIndex, numLayers, layers,
+ composeBuffers)) {
+ auto composition =
+ std::make_unique<Composition>(std::move(composeLayers));
m_compositorVk->setComposition(imageIndex, std::move(composition));
- surfaceState.m_prevDisplayBuffer = displayBufferPtr;
}
auto cmdBuff = m_compositorVk->getCommandBuffer(imageIndex);
@@ -194,6 +232,101 @@ bool DisplayVk::canComposite(VkFormat format) {
return res;
}
+bool DisplayVk::compareAndSaveComposition(
+ uint32_t renderTargetIndex, uint32_t numLayers, const ComposeLayer layers[],
+ const std::vector<std::shared_ptr<DisplayBufferInfo>> &composeBuffers) {
+ if (!m_surfaceState) {
+ ERR("%s(%s:%d): Haven't bound to a surface, can't compare and save "
+ "composition\n",
+ __FUNCTION__, __FILE__, static_cast<int>(__LINE__));
+ ::abort();
+ }
+ auto [iPrevComposition, compositionNotFound] =
+ m_surfaceState->m_prevCompositions.emplace(renderTargetIndex, 0);
+ auto &prevComposition = iPrevComposition->second;
+ bool compositionChanged = false;
+ if (numLayers == prevComposition.size()) {
+ for (int i = 0; i < numLayers; i++) {
+ if (composeBuffers[i] == nullptr) {
+ // If the display buffer of the current layer doesn't exist, we
+ // check if the layer at the same index in the previous
+ // composition doesn't exist either.
+ if (prevComposition[i] == nullptr) {
+ continue;
+ } else {
+ compositionChanged = true;
+ break;
+ }
+ }
+ if (prevComposition[i] == nullptr) {
+ // If the display buffer of the current layer exists but the
+ // layer at the same index in the previous composition doesn't
+ // exist, the composition is changed.
+ compositionChanged = true;
+ break;
+ }
+ const auto &prevLayer = *prevComposition[i];
+ const auto prevDisplayBufferPtr = prevLayer.m_displayBuffer.lock();
+ // prevLayer.m_displayBuffer is a weak pointer, so if
+ // prevDisplayBufferPtr is null, the color buffer
+ // prevDisplayBufferPtr pointed to should have been released or
+ // re-allocated, and we should consider the composition is changed.
+ // If prevDisplayBufferPtr exists and it points to the same display
+ // buffer as the input composeBuffers[i] we consider the composition
+ // not changed.
+ if (!prevDisplayBufferPtr ||
+ prevDisplayBufferPtr != composeBuffers[i]) {
+ compositionChanged = true;
+ break;
+ }
+ const auto &prevHwc2Layer = prevLayer.m_hwc2Layer;
+ const auto hwc2Layer = layers[i];
+ compositionChanged =
+ (prevHwc2Layer.cbHandle != hwc2Layer.cbHandle) ||
+ (prevHwc2Layer.composeMode != hwc2Layer.composeMode) ||
+ (prevHwc2Layer.displayFrame.left !=
+ hwc2Layer.displayFrame.left) ||
+ (prevHwc2Layer.displayFrame.top !=
+ hwc2Layer.displayFrame.top) ||
+ (prevHwc2Layer.displayFrame.right !=
+ hwc2Layer.displayFrame.right) ||
+ (prevHwc2Layer.displayFrame.bottom !=
+ hwc2Layer.displayFrame.bottom) ||
+ (prevHwc2Layer.crop.left != hwc2Layer.crop.left) ||
+ (prevHwc2Layer.crop.top != hwc2Layer.crop.top) ||
+ (prevHwc2Layer.crop.right != hwc2Layer.crop.right) ||
+ (prevHwc2Layer.crop.bottom != hwc2Layer.crop.bottom) ||
+ (prevHwc2Layer.blendMode != hwc2Layer.blendMode) ||
+ (prevHwc2Layer.alpha != hwc2Layer.alpha) ||
+ (prevHwc2Layer.color.r != hwc2Layer.color.r) ||
+ (prevHwc2Layer.color.g != hwc2Layer.color.g) ||
+ (prevHwc2Layer.color.b != hwc2Layer.color.b) ||
+ (prevHwc2Layer.color.a != hwc2Layer.color.a) ||
+ (prevHwc2Layer.transform != hwc2Layer.transform);
+ if (compositionChanged) {
+ break;
+ }
+ }
+ } else {
+ compositionChanged = true;
+ }
+ bool needsSave = compositionNotFound || compositionChanged;
+ if (needsSave) {
+ prevComposition.clear();
+ for (int i = 0; i < numLayers; i++) {
+ if (composeBuffers[i] == nullptr) {
+ prevComposition.emplace_back(nullptr);
+ continue;
+ }
+ auto layer = std::make_unique<SurfaceState::Layer>();
+ layer->m_hwc2Layer = layers[i];
+ layer->m_displayBuffer = composeBuffers[i];
+ prevComposition.emplace_back(std::move(layer));
+ }
+ }
+ return needsSave;
+}
+
DisplayVk::DisplayBufferInfo::DisplayBufferInfo(
const goldfish_vk::VulkanDispatch &vk, VkDevice vkDevice, uint32_t width,
uint32_t height, VkFormat format, VkImage image)
@@ -223,4 +356,4 @@ DisplayVk::DisplayBufferInfo::DisplayBufferInfo(
DisplayVk::DisplayBufferInfo::~DisplayBufferInfo() {
m_vk.vkDestroyImageView(m_vkDevice, m_vkImageView, nullptr);
-} \ No newline at end of file
+}
diff --git a/stream-servers/DisplayVk.h b/stream-servers/DisplayVk.h
index 88e86c20..952c28d1 100644
--- a/stream-servers/DisplayVk.h
+++ b/stream-servers/DisplayVk.h
@@ -6,6 +6,7 @@
#include <unordered_map>
#include "CompositorVk.h"
+#include "Hwc2.h"
#include "RenderContext.h"
#include "SwapChainStateVk.h"
#include "vulkan/cereal/common/goldfish_vk_dispatch.h"
@@ -49,8 +50,20 @@ class DisplayVk {
uint32_t height);
void post(const std::shared_ptr<DisplayBufferInfo> &);
+ void compose(
+ uint32_t numLayers, const ComposeLayer layers[],
+ const std::vector<std::shared_ptr<DisplayBufferInfo>> &composeBuffers);
+
private:
bool canComposite(VkFormat);
+ // Returns if the composition specified by the parameter is different from
+ // the previous composition. If the composition is different, update the
+ // previous composition stored in m_surfaceState. Must be called after
+ // bindToSurface() is called.
+ bool compareAndSaveComposition(
+ uint32_t renderTargetIndex, uint32_t numLayers,
+ const ComposeLayer layers[],
+ const std::vector<std::shared_ptr<DisplayBufferInfo>> &composeBuffers);
const goldfish_vk::VulkanDispatch &m_vk;
VkPhysicalDevice m_vkPhysicalDevice;
@@ -68,13 +81,18 @@ class DisplayVk {
std::unique_ptr<SwapChainStateVk> m_swapChainStateVk;
std::unique_ptr<CompositorVk> m_compositorVk;
struct SurfaceState {
+ struct Layer {
+ ComposeLayer m_hwc2Layer;
+ std::weak_ptr<DisplayBufferInfo> m_displayBuffer;
+ };
+
uint32_t m_width = 0;
uint32_t m_height = 0;
- std::weak_ptr<DisplayBufferInfo> m_prevDisplayBuffer =
- std::weak_ptr<DisplayBufferInfo>();
+ std::unordered_map<uint32_t, std::vector<std::unique_ptr<Layer>>>
+ m_prevCompositions;
};
std::unique_ptr<SurfaceState> m_surfaceState;
std::unordered_map<VkFormat, bool> m_canComposite;
};
-#endif \ No newline at end of file
+#endif
diff --git a/stream-servers/FrameBuffer.cpp b/stream-servers/FrameBuffer.cpp
index efee4542..bc8327b0 100644
--- a/stream-servers/FrameBuffer.cpp
+++ b/stream-servers/FrameBuffer.cpp
@@ -757,7 +757,7 @@ FrameBuffer::FrameBuffer(int p_width, int p_height, bool useSubWindow)
kFeature_RefCountPipe)),
m_noDelayCloseColorBufferEnabled(feature_is_enabled(
kFeature_NoDelayCloseColorBuffer)),
- m_postThread([this](FrameBuffer::Post&& post) {
+ m_postThread([this](Post&& post) {
return postWorkerFunc(post);
}) {
uint32_t displayId = 0;
@@ -857,7 +857,7 @@ FrameBuffer::postWorkerFunc(const Post& post) {
return WorkerProcessingResult::Continue;
}
-void FrameBuffer::sendPostWorkerCmd(FrameBuffer::Post post) {
+void FrameBuffer::sendPostWorkerCmd(Post post) {
#ifdef __APPLE__
bool postOnlyOnMainThread = m_subWin && (emugl::getRenderer() == SELECTED_RENDERER_HOST);
#else
@@ -2480,7 +2480,12 @@ bool FrameBuffer::postImpl(HandleType p_colorbuffer,
// TODO(kaiyili, b/179481815): make DisplayVk::post asynchronous.
if (m_displayVk != nullptr) {
+ if (m_justVkComposed) {
+ m_justVkComposed = false;
+ goto EXIT;
+ }
m_displayVk->post(c->second.cb->getDisplayBufferVk());
+ m_lastPostedColorBuffer = p_colorbuffer;
goto EXIT;
}
@@ -2775,18 +2780,50 @@ bool FrameBuffer::compose(uint32_t bufferSize, void* buffer, bool needPost) {
// support for multi-display
ComposeDevice_v2* p2 = (ComposeDevice_v2*)buffer;
if (p2->displayId != 0) {
- mutex.unlock();
- setDisplayColorBuffer(p2->displayId, p2->targetHandle);
- mutex.lock();
+ 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.cmd = PostCmd::Compose;
- sendPostWorkerCmd(composeCmd);
- if (p2->displayId == 0 && needPost) {
- post(p2->targetHandle, false);
+ if (m_displayVk) {
+ // We don't copy the render result to the targetHandle color buffer
+ // when using the Vulkan native host swapchain, because we directly
+ // render to the swapchain image instead of rendering onto a
+ // ColorBuffer, and we don't readback from the ColorBuffer so far.
+ ColorBufferMap::iterator c;
+
+ std::vector<ColorBufferPtr> cbs; // Keep ColorBuffers alive
+ std::vector<std::shared_ptr<DisplayVk::DisplayBufferInfo>> composeBuffers;
+ ComposeDevice_v2* const composeDevice = p2;
+ const ComposeLayer* const l = (ComposeLayer*)composeDevice->layer;
+ for (int i = 0; i < composeDevice->numLayers; ++i) {
+ c = m_colorbuffers.find(l[i].cbHandle);
+ if (c == m_colorbuffers.end()) {
+ composeBuffers.push_back(nullptr);
+ continue;
+ }
+ cbs.push_back(c->second.cb);
+ auto db = c->second.cb->getDisplayBufferVk();
+ if (!db) {
+ mutex.unlock();
+ goldfish_vk::setupVkColorBuffer(l[i].cbHandle);
+ mutex.lock();
+ db = c->second.cb->getDisplayBufferVk();
+ }
+ composeBuffers.push_back(db);
+ }
+
+ m_displayVk->compose(composeDevice->numLayers, l, composeBuffers);
+ m_justVkComposed = true;
+ } else {
+ Post composeCmd;
+ composeCmd.composeVersion = 2;
+ composeCmd.composeBuffer.resize(bufferSize);
+ memcpy(composeCmd.composeBuffer.data(), buffer, bufferSize);
+ composeCmd.cmd = PostCmd::Compose;
+ sendPostWorkerCmd(composeCmd);
+ if (p2->displayId == 0 && needPost) {
+ post(p2->targetHandle, false);
+ }
}
return true;
}
@@ -3141,6 +3178,10 @@ int FrameBuffer::createDisplay(uint32_t *displayId) {
return emugl::get_emugl_multi_display_operations().createDisplay(displayId);
}
+int FrameBuffer::createDisplay(uint32_t displayId) {
+ return emugl::get_emugl_multi_display_operations().createDisplay(&displayId);
+}
+
int FrameBuffer::destroyDisplay(uint32_t displayId) {
return emugl::get_emugl_multi_display_operations().destroyDisplay(displayId);
}
@@ -3222,4 +3263,4 @@ VkImageLayout FrameBuffer::getVkImageLayoutForPresent() const {
return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
return VK_IMAGE_LAYOUT_GENERAL;
-} \ No newline at end of file
+}
diff --git a/stream-servers/FrameBuffer.h b/stream-servers/FrameBuffer.h
index 71ce1ec0..88a7bcf1 100644
--- a/stream-servers/FrameBuffer.h
+++ b/stream-servers/FrameBuffer.h
@@ -30,6 +30,7 @@
#include "FbConfig.h"
#include "GLESVersionDetector.h"
#include "Hwc2.h"
+#include "PostCommands.h"
#include "PostWorker.h"
#include "ReadbackWorker.h"
#include "RenderContext.h"
@@ -541,7 +542,8 @@ class FrameBuffer {
void registerProcessSequenceNumberForPuid(uint64_t puid);
uint32_t* getProcessSequenceNumberPtr(uint64_t puid);
- int createDisplay(uint32_t* displayId);
+ int createDisplay(uint32_t *displayId);
+ int createDisplay(uint32_t displayId);
int destroyDisplay(uint32_t displayId);
int setDisplayColorBuffer(uint32_t displayId, uint32_t colorBuffer);
int getDisplayColorBuffer(uint32_t displayId, uint32_t* colorBuffer);
@@ -680,6 +682,9 @@ class FrameBuffer {
TextureDraw* m_textureDraw = nullptr;
EGLConfig m_eglConfig = nullptr;
HandleType m_lastPostedColorBuffer = 0;
+ // With Vulkan swapchain, compose also means to post to the WSI surface.
+ // In this case, don't do anything in the subsequent resource flush.
+ bool m_justVkComposed = false;
float m_zRot = 0;
float m_px = 0;
float m_py = 0;
@@ -755,38 +760,6 @@ class FrameBuffer {
// buffer is already tied to a file descriptor in the guest kernel.
bool m_noDelayCloseColorBufferEnabled = false;
- // Posting
- enum class PostCmd {
- Post = 0,
- Viewport = 1,
- Compose = 2,
- Clear = 3,
- Screenshot = 4,
- Exit = 5,
- };
-
- struct Post {
- PostCmd cmd;
- int composeVersion;
- std::vector<char> composeBuffer;
- union {
- ColorBuffer* cb;
- struct {
- int width;
- int height;
- } viewport;
- struct {
- ColorBuffer* cb;
- int screenwidth;
- int screenheight;
- GLenum format;
- GLenum type;
- int rotation;
- void* pixels;
- } screenshot;
- };
- };
-
std::unique_ptr<PostWorker> m_postWorker = {};
android::base::WorkerThread<Post> m_postThread;
android::base::WorkerProcessingResult postWorkerFunc(const Post& post);
diff --git a/stream-servers/GfxStreamAgents.cpp b/stream-servers/GfxStreamAgents.cpp
index b8fef7cd..716f9f04 100644
--- a/stream-servers/GfxStreamAgents.cpp
+++ b/stream-servers/GfxStreamAgents.cpp
@@ -24,10 +24,18 @@
#include "host-common/multi_display_agent.h" // for QAndroidM...
#include "host-common/vm_operations.h" // for SnapshotC...
#include "host-common/window_agent.h" // for WindowMes...
-#include "host-common/misc.h"
+#include "host-common/misc.h"
+
+#ifdef _DEBUG
+#define DEBUG_LOG(fd, fmt, ...) fprintf(fd, fmt, __VA_ARGS__);
+#else
+#define DEBUG_LOG(fd, fmt, ...)
+#endif
std::map<uint32_t, android::MultiDisplayInfo> mMultiDisplay;
+using namespace android;
+
static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
.setMultiDisplay = [](uint32_t id,
int32_t x,
@@ -37,12 +45,10 @@ static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
uint32_t dpi,
uint32_t flag,
bool add) -> int {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"setMultiDisplay (mock): %d, x: %d, y: %d, w: %d, h: %d, "
"dpi: %d, flag: %d\n",
id, x, y, w, h, dpi, flag);
- mMultiDisplay[id] =
- android::MultiDisplayInfo(x, y, w, h, dpi, flag, add);
return 0;
},
.getMultiDisplay = [](uint32_t id,
@@ -52,19 +58,35 @@ static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
uint32_t* h,
uint32_t* dpi,
uint32_t* flag,
- bool* enable) -> bool {
- fprintf(stderr, "getMultiDisplay (mock) id %u\n", id);
- if (x)
+ bool* enabled) -> bool {
+ DEBUG_LOG(stderr, "getMultiDisplay (mock) id %u\n", id);
+ if (mMultiDisplay.find(id) == mMultiDisplay.end()) {
+ if (enabled) {
+ *enabled = false;
+ }
+ return false;
+ }
+ if (x) {
*x = mMultiDisplay[id].pos_x;
- if (y)
+ }
+ if (y) {
*y = mMultiDisplay[id].pos_y;
- if (w)
+ }
+ if (w) {
*w = mMultiDisplay[id].width;
- if (h)
+ }
+ if (h) {
*h = mMultiDisplay[id].height;
- if (dpi)
+ }
+ if (dpi) {
*dpi = mMultiDisplay[id].dpi;
-
+ }
+ if (flag) {
+ *flag = mMultiDisplay[id].flag;
+ }
+ if (enabled) {
+ *enabled = mMultiDisplay[id].enabled;
+ }
return true;
},
.getNextMultiDisplay = [](int32_t start_id,
@@ -76,7 +98,7 @@ static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
uint32_t* dpi,
uint32_t* flag,
uint32_t* cb) -> bool {
- fprintf(stderr, "getNextMultiDisplay (mock) start_id %u\n",
+ DEBUG_LOG(stderr, "getNextMultiDisplay (mock) start_id %u\n",
start_id);
uint32_t key;
std::map<uint32_t, android::MultiDisplayInfo>::iterator i;
@@ -131,11 +153,37 @@ static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
},
.setGpuMode = [](bool isGuestMode, uint32_t w, uint32_t h) {},
.createDisplay = [](uint32_t* displayId) -> int {
+ if (displayId == nullptr) {
+ fprintf(stderr, "null displayId pointer\n");
+ return -1;
+ }
+ if (mMultiDisplay.size() >= MultiDisplay::s_maxNumMultiDisplay) {
+ fprintf(stderr, "cannot create more displays, exceeding limits %d\n",
+ MultiDisplay::s_maxNumMultiDisplay);
+ return -1;
+ }
+ if (mMultiDisplay.find(*displayId) != mMultiDisplay.end()) {
+ return 0;
+ }
+ // displays created by internal rcCommands
+ if (*displayId == MultiDisplay::s_invalidIdMultiDisplay) {
+ for (int i = MultiDisplay::s_displayIdInternalBegin; i < MultiDisplay::s_maxNumMultiDisplay; i++) {
+ if (mMultiDisplay.find(i) == mMultiDisplay.end()) {
+ *displayId = i;
+ break;
+ }
+ }
+ }
+ if (*displayId == MultiDisplay::s_invalidIdMultiDisplay) {
+ fprintf(stderr, "cannot create more internaldisplays, exceeding limits %d\n",
+ MultiDisplay::s_maxNumMultiDisplay - MultiDisplay::s_displayIdInternalBegin);
+ return -1;
+ }
+
mMultiDisplay.emplace(*displayId, android::MultiDisplayInfo());
return 0;
},
.destroyDisplay = [](uint32_t displayId) -> int {
- fprintf(stderr, "destroyDisplay (mock): %d\n", displayId);
mMultiDisplay.erase(displayId);
return 0;
},
@@ -145,6 +193,10 @@ static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
uint32_t w,
uint32_t h,
uint32_t dpi) -> int {
+ if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
+ fprintf(stderr, "cannot find display %d\n", displayId);
+ return -1;
+ }
mMultiDisplay[displayId].pos_x = x;
mMultiDisplay[displayId].pos_y = y;
mMultiDisplay[displayId].width = w;
@@ -157,6 +209,10 @@ static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
int32_t* y,
uint32_t* w,
uint32_t* h) -> int {
+ if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
+ fprintf(stderr, "cannot find display %d\n", displayId);
+ return -1;
+ }
if (x)
*x = mMultiDisplay[displayId].pos_x;
if (y)
@@ -169,6 +225,10 @@ static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
},
.getDisplayColorBuffer = [](uint32_t displayId,
uint32_t* colorBuffer) -> int {
+ if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
+ fprintf(stderr, "cannot find display %d\n", displayId);
+ return -1;
+ }
*colorBuffer = mMultiDisplay[displayId].cb;
return 0;
},
@@ -184,6 +244,10 @@ static const QAndroidMultiDisplayAgent sMultiDisplayAgent = {
},
.setDisplayColorBuffer = [](uint32_t displayId,
uint32_t colorBuffer) -> int {
+ if (mMultiDisplay.find(displayId) == mMultiDisplay.end()) {
+ fprintf(stderr, "cannot find display %d\n", displayId);
+ return -1;
+ }
mMultiDisplay[displayId].cb = colorBuffer;
return 0;
}};
@@ -193,34 +257,34 @@ static bool sIsFolded = false;
static const QAndroidEmulatorWindowAgent sQAndroidEmulatorWindowAgent = {
.getEmulatorWindow =
[](void) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"window-agent-GfxStream-impl: "
".getEmulatorWindow\n");
return (EmulatorWindow*)nullptr;
},
.rotate90Clockwise =
[](void) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"window-agent-GfxStream-impl: "
".rotate90Clockwise\n");
return true;
},
.rotate =
[](int rotation) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"window-agent-GfxStream-impl: "
".rotate90Clockwise\n");
return true;
},
.getRotation =
[](void) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"window-agent-GfxStream-impl: .getRotation\n");
return (int)SKIN_ROTATION_0;
},
.showMessage =
[](const char* message, WindowMessageType type, int timeoutMs) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"window-agent-GfxStream-impl: .showMessage %s\n",
message);
},
@@ -231,29 +295,29 @@ static const QAndroidEmulatorWindowAgent sQAndroidEmulatorWindowAgent = {
void* context,
void (*func)(void*),
int timeoutMs) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"window-agent-GfxStream-impl: "
".showMessageWithDismissCallback %s\n",
message);
},
.fold =
[](bool is_fold) -> bool {
- fprintf(stderr, "window-agent-GfxStream-impl: .fold %d\n",
+ DEBUG_LOG(stderr, "window-agent-GfxStream-impl: .fold %d\n",
is_fold);
sIsFolded = is_fold;
return true;
},
.isFolded = [](void) -> bool { return sIsFolded; },
.getFoldedArea = [](int* x, int* y, int* w, int* h) -> bool {
- fprintf(stderr, "window-agent-GfxStream-impl: .getFoldedArea\n");
+ DEBUG_LOG(stderr, "window-agent-GfxStream-impl: .getFoldedArea\n");
return true;
},
.updateFoldablePostureIndicator = [](bool) {
- fprintf(stderr, "window-agent-GfxStream-impl: updateFoldablePostureIndicator\n");
+ DEBUG_LOG(stderr, "window-agent-GfxStream-impl: updateFoldablePostureIndicator\n");
},
.setUIDisplayRegion =
[](int x_offset, int y_offset, int w, int h) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"window-agent-GfxStream-impl: .setUIDisplayRegion "
"%d %d %dx%d\n",
x_offset, y_offset, w, h);
@@ -263,7 +327,7 @@ static const QAndroidEmulatorWindowAgent sQAndroidEmulatorWindowAgent = {
.restoreSkin = [](void) {},
.updateUIMultiDisplayPage =
[](uint32_t id) {
- fprintf(stderr, "updateMultiDisplayPage\n");
+ DEBUG_LOG(stderr, "updateMultiDisplayPage\n");
},
.getMonitorRect =
[](uint32_t* w, uint32_t* h) -> bool {
@@ -277,116 +341,116 @@ static const QAndroidEmulatorWindowAgent sQAndroidEmulatorWindowAgent = {
static const QAndroidVmOperations sQAndroidVmOperations = {
.vmStop = []() -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: vm stop\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm stop\n");
return true;
},
.vmStart = []() -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: vm start\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm start\n");
return true;
},
.vmReset =
- []() { fprintf(stderr, "goldfish-opengl vm ops: vm reset\n"); },
+ []() { DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm reset\n"); },
.vmShutdown =
- []() { fprintf(stderr, "goldfish-opengl vm ops: vm reset\n"); },
+ []() { DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm reset\n"); },
.vmPause = []() -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: vm pause\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm pause\n");
return true;
},
.vmResume = []() -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: vm resume\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm resume\n");
return true;
},
.vmIsRunning = []() -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: vm is running\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: vm is running\n");
return true;
},
.snapshotList =
[](void*, LineConsumerCallback, LineConsumerCallback) -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: snapshot list\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot list\n");
return true;
},
.snapshotSave = [](const char* name,
void* opaque,
LineConsumerCallback) -> bool {
- fprintf(stderr, "gfxstream vm ops: snapshot save\n");
+ DEBUG_LOG(stderr, "gfxstream vm ops: snapshot save\n");
return true;
},
.snapshotLoad = [](const char* name,
void* opaque,
LineConsumerCallback) -> bool {
- fprintf(stderr, "gfxstream vm ops: snapshot load\n");
+ DEBUG_LOG(stderr, "gfxstream vm ops: snapshot load\n");
return true;
},
.snapshotDelete = [](const char* name,
void* opaque,
LineConsumerCallback errConsumer) -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: snapshot delete\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot delete\n");
return true;
},
.snapshotRemap = [](bool shared,
void* opaque,
LineConsumerCallback errConsumer) -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: snapshot remap\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot remap\n");
return true;
},
.snapshotExport = [](const char* snapshot,
const char* dest,
void* opaque,
LineConsumerCallback errConsumer) -> bool {
- fprintf(stderr, "goldfish-opengl vm ops: snapshot export image\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: snapshot export image\n");
return true;
},
.setSnapshotCallbacks =
[](void* opaque, const SnapshotCallbacks* callbacks) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"goldfish-opengl vm ops: set snapshot callbacks\n");
},
.mapUserBackedRam =
[](uint64_t gpa, void* hva, uint64_t size) {
- fprintf(stderr, "%s: map user backed ram\n", __func__);
+ DEBUG_LOG(stderr, "%s: map user backed ram\n", __func__);
},
.unmapUserBackedRam =
[](uint64_t gpa, uint64_t size) {
- fprintf(stderr, "%s: unmap user backed ram\n", __func__);
+ DEBUG_LOG(stderr, "%s: unmap user backed ram\n", __func__);
},
.getVmConfiguration =
[](VmConfiguration* out) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"goldfish-opengl vm ops: get vm configuration\n");
},
.setFailureReason =
[](const char* name, int failureReason) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"goldfish-opengl vm ops: set failure reason\n");
},
.setExiting =
[]() {
- fprintf(stderr, "goldfish-opengl vm ops: set exiting\n");
+ DEBUG_LOG(stderr, "goldfish-opengl vm ops: set exiting\n");
},
.allowRealAudio =
[](bool allow) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"goldfish-opengl vm ops: allow real audio\n");
},
.physicalMemoryGetAddr =
[](uint64_t gpa) {
- fprintf(stderr, "%s: physmemGetAddr\n", __func__);
+ DEBUG_LOG(stderr, "%s: physmemGetAddr\n", __func__);
return (void*)nullptr;
},
.isRealAudioAllowed =
[](void) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"goldfish-opengl vm ops: is real audiop allowed\n");
return true;
},
.setSkipSnapshotSave =
[](bool used) {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"goldfish-opengl vm ops: set skip snapshot save\n");
},
.isSnapshotSaveSkipped =
[]() {
- fprintf(stderr,
+ DEBUG_LOG(stderr,
"goldfish-opengl vm ops: is snapshot save "
"skipped\n");
return false;
diff --git a/stream-servers/PostCommands.h b/stream-servers/PostCommands.h
new file mode 100644
index 00000000..bcc2c759
--- /dev/null
+++ b/stream-servers/PostCommands.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <vector>
+
+#include <GLES2/gl2.h>
+
+class ColorBuffer;
+
+// Posting
+enum class PostCmd {
+ Post = 0,
+ Viewport = 1,
+ Compose = 2,
+ Clear = 3,
+ Screenshot = 4,
+ Exit = 5,
+};
+
+struct Post {
+ PostCmd cmd;
+ int composeVersion;
+ std::vector<char> composeBuffer;
+ union {
+ ColorBuffer* cb;
+ struct {
+ int width;
+ int height;
+ } viewport;
+ struct {
+ ColorBuffer* cb;
+ int screenwidth;
+ int screenheight;
+ GLenum format;
+ GLenum type;
+ int rotation;
+ void* pixels;
+ } screenshot;
+ };
+};
+
diff --git a/stream-servers/PostWorker.cpp b/stream-servers/PostWorker.cpp
index 8f3f374f..9fffb57a 100644
--- a/stream-servers/PostWorker.cpp
+++ b/stream-servers/PostWorker.cpp
@@ -231,7 +231,7 @@ void PostWorker::composeImpl(ComposeDevice* p) {
l->displayFrame.right, l->displayFrame.bottom,
l->crop.left, l->crop.top, l->crop.right,
l->crop.bottom);
- composeLayer(l);
+ composeLayer(l, mFb->getWidth(), mFb->getHeight());
}
cbPtr->setSync();
@@ -249,7 +249,16 @@ void PostWorker::composev2Impl(ComposeDevice_v2* p) {
ComposeLayer* l = (ComposeLayer*)p->layer;
GLint vport[4] = { 0, };
s_gles2.glGetIntegerv(GL_VIEWPORT, vport);
- s_gles2.glViewport(0, 0, mFb->getWidth(),mFb->getHeight());
+ uint32_t w, h;
+ emugl::get_emugl_multi_display_operations().getMultiDisplay(p->displayId,
+ nullptr,
+ nullptr,
+ &w,
+ &h,
+ nullptr,
+ nullptr,
+ nullptr);
+ s_gles2.glViewport(0, 0, w, h);
if (!m_composeFbo) {
s_gles2.glGenFramebuffers(1, &m_composeFbo);
}
@@ -281,7 +290,7 @@ void PostWorker::composev2Impl(ComposeDevice_v2* p) {
l->displayFrame.right, l->displayFrame.bottom,
l->crop.left, l->crop.top, l->crop.right,
l->crop.bottom);
- composeLayer(l);
+ composeLayer(l, w, h);
}
cbPtr->setSync();
@@ -310,7 +319,7 @@ void PostWorker::unbind() {
}
}
-void PostWorker::composeLayer(ComposeLayer* l) {
+void PostWorker::composeLayer(ComposeLayer* l, uint32_t w, uint32_t h) {
if (l->composeMode == HWC2_COMPOSITION_DEVICE) {
ColorBufferPtr cb = mFb->findColorBuffer(l->cbHandle);
if (!cb) {
@@ -318,12 +327,11 @@ void PostWorker::composeLayer(ComposeLayer* l) {
// ERR("%s: fail to find colorbuffer %d\n", __FUNCTION__, l->cbHandle);
return;
}
- cb->postLayer(l, mFb->getWidth(), mFb->getHeight());
+ cb->postLayer(l, w, h);
}
else {
// no Colorbuffer associated with SOLID_COLOR mode
- mFb->getTextureDraw()->drawLayer(l, mFb->getWidth(), mFb->getHeight(),
- 1, 1, 0);
+ mFb->getTextureDraw()->drawLayer(l, w, h, 1, 1, 0);
}
}
diff --git a/stream-servers/PostWorker.h b/stream-servers/PostWorker.h
index 9e7ccd51..31820853 100644
--- a/stream-servers/PostWorker.h
+++ b/stream-servers/PostWorker.h
@@ -84,7 +84,7 @@ private:
void bind();
void unbind();
- void composeLayer(ComposeLayer* l);
+ void composeLayer(ComposeLayer* l, uint32_t w, uint32_t h);
void fillMultiDisplayPostStruct(ComposeLayer* l,
hwc_rect_t displayArea,
hwc_frect_t cropArea,
diff --git a/stream-servers/RenderControl.cpp b/stream-servers/RenderControl.cpp
index 8c6e2af2..7f62811f 100644
--- a/stream-servers/RenderControl.cpp
+++ b/stream-servers/RenderControl.cpp
@@ -1274,6 +1274,15 @@ static int rcCreateDisplay(uint32_t* displayId) {
return fb->createDisplay(displayId);
}
+static int rcCreateDisplayById(uint32_t displayId) {
+ FrameBuffer *fb = FrameBuffer::getFB();
+ if (!fb) {
+ return -1;
+ }
+
+ return fb->createDisplay(displayId);
+}
+
static int rcDestroyDisplay(uint32_t displayId) {
FrameBuffer *fb = FrameBuffer::getFB();
if (!fb) {
@@ -1336,6 +1345,20 @@ static int rcSetDisplayPose(uint32_t displayId,
return fb->setDisplayPose(displayId, x, y, w, h);
}
+static int rcSetDisplayPoseDpi(uint32_t displayId,
+ int32_t x,
+ int32_t y,
+ uint32_t w,
+ uint32_t h,
+ uint32_t dpi) {
+ FrameBuffer *fb = FrameBuffer::getFB();
+ if (!fb) {
+ return -1;
+ }
+
+ return fb->setDisplayPose(displayId, x, y, w, h, dpi);
+}
+
static void rcReadColorBufferYUV(uint32_t colorBuffer,
GLint x, GLint y,
GLint width, GLint height,
@@ -1557,4 +1580,6 @@ void initRenderControlContext(renderControl_decoder_context_t *dec)
dec->rcDestroySyncKHRAsync = rcDestroySyncKHRAsync;
dec->rcComposeWithoutPost = rcComposeWithoutPost;
dec->rcComposeAsyncWithoutPost = rcComposeAsyncWithoutPost;
+ dec->rcCreateDisplayById = rcCreateDisplayById;
+ dec->rcSetDisplayPoseDpi = rcSetDisplayPoseDpi;
}
diff --git a/stream-servers/SyncThread.cpp b/stream-servers/SyncThread.cpp
index 1b3e0e74..f0744294 100644
--- a/stream-servers/SyncThread.cpp
+++ b/stream-servers/SyncThread.cpp
@@ -66,7 +66,7 @@ static GlobalSyncThread* sGlobalSyncThread() {
static const uint32_t kTimelineInterval = 1;
static const uint64_t kDefaultTimeoutNsecs = 5ULL * 1000ULL * 1000ULL * 1000ULL;
-static const uint64_t kNumWorkerThreads = 1u;
+static const uint64_t kNumWorkerThreads = 4u;
SyncThread::SyncThread()
: android::base::Thread(android::base::ThreadFlags::MaskSignals, 512 * 1024),
@@ -132,9 +132,13 @@ void SyncThread::cleanup() {
void SyncThread::initSyncContext() {
DPRINT("enter");
- SyncThreadCmd to_send;
- to_send.opCode = SYNC_THREAD_INIT;
- sendAndWaitForResult(to_send);
+ // TODO(b/187082169, warty): The thread pool's command-assignment strategy
+ // is round-robin, so as a hack, create one command for each worker.
+ for (int i = 0; i < mWorkerThreadPool.numWorkers(); i++) {
+ SyncThreadCmd to_send;
+ to_send.opCode = SYNC_THREAD_INIT;
+ sendAndWaitForResult(to_send);
+ }
DPRINT("exit");
}
@@ -313,8 +317,9 @@ void SyncThread::doSyncBlockedWaitNoTimeline(SyncThreadCmd* cmd) {
wait_result);
if (wait_result != EGL_CONDITION_SATISFIED_KHR) {
- fprintf(stderr, "error: eglClientWaitSync abnormal exit 0x%x %p\n",
- wait_result, cmd->fenceSync);
+ EGLint error = s_egl.eglGetError();
+ fprintf(stderr, "error: eglClientWaitSync abnormal exit 0x%x %p %#x\n",
+ wait_result, cmd->fenceSync, error);
}
}
diff --git a/stream-servers/YUVConverter.cpp b/stream-servers/YUVConverter.cpp
index 6e1b0a2f..22858e46 100644
--- a/stream-servers/YUVConverter.cpp
+++ b/stream-servers/YUVConverter.cpp
@@ -58,8 +58,11 @@ static void getYUVOffsets(int width, int height, FrameworkFormat format,
uint32_t yStride, cStride, cHeight, cSize, align;
switch (format) {
case FRAMEWORK_FORMAT_YV12:
+ // Luma stride is 32 bytes aligned.
align = 32;
yStride = (width + (align - 1)) & ~(align - 1);
+ // Chroma stride is 16 bytes aligned.
+ align = 16;
cStride = (yStride / 2 + (align - 1)) & ~(align - 1);
cHeight = height / 2;
cSize = cStride * cHeight;
diff --git a/stream-servers/glestranslator/EGL/EglOsApi_egl.cpp b/stream-servers/glestranslator/EGL/EglOsApi_egl.cpp
index 3d3037df..c14d3161 100644
--- a/stream-servers/glestranslator/EGL/EglOsApi_egl.cpp
+++ b/stream-servers/glestranslator/EGL/EglOsApi_egl.cpp
@@ -471,7 +471,9 @@ EglOsEglDisplay::createContext(EGLint profileMask,
// Always GLES3
std::vector<EGLint> attributes = { EGL_CONTEXT_CLIENT_VERSION, 3 };
auto exts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
- if (exts != nullptr && emugl::hasExtension(exts, "EGL_KHR_create_context_no_error")) {
+
+ bool disableValidation = android::base::getEnvironmentVariable("ANDROID_EMUGL_EGL_VALIDATION") == "0";
+ if (exts != nullptr && emugl::hasExtension(exts, "EGL_KHR_create_context_no_error") && disableValidation) {
attributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
attributes.push_back(EGL_TRUE);
}
diff --git a/stream-servers/glestranslator/EGL/ShaderCache.cpp b/stream-servers/glestranslator/EGL/ShaderCache.cpp
index 0a2b031f..ae70137c 100644
--- a/stream-servers/glestranslator/EGL/ShaderCache.cpp
+++ b/stream-servers/glestranslator/EGL/ShaderCache.cpp
@@ -15,6 +15,7 @@
#include "ShaderCache.h"
#include "base/MruCache.h"
+#include <string.h>
#include <cstdio>
#include <map>
diff --git a/stream-servers/renderControl_dec/renderControl_dec.cpp b/stream-servers/renderControl_dec/renderControl_dec.cpp
index 9f859ce3..8b275620 100644
--- a/stream-servers/renderControl_dec/renderControl_dec.cpp
+++ b/stream-servers/renderControl_dec/renderControl_dec.cpp
@@ -1222,6 +1222,49 @@ size_t renderControl_decoder_context_t::decode(void *buf, size_t len, IOStream *
android::base::endTrace();
break;
}
+ case OP_rcCreateDisplayById: {
+ android::base::beginTrace("rcCreateDisplayById decode");
+ uint32_t var_displayId = Unpack<uint32_t,uint32_t>(ptr + 8);
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::validOrDie(checksumCalc, ptr, 8 + 4, ptr + 8 + 4, checksumSize,
+ "renderControl_decoder_context_t::decode, OP_rcCreateDisplayById: GL checksumCalculator failure\n");
+ }
+ size_t totalTmpSize = sizeof(int);
+ totalTmpSize += checksumSize;
+ unsigned char *tmpBuf = stream->alloc(totalTmpSize);
+ *(int *)(&tmpBuf[0]) = this->rcCreateDisplayById(var_displayId);
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::writeChecksum(checksumCalc, &tmpBuf[0], totalTmpSize - checksumSize, &tmpBuf[totalTmpSize - checksumSize], checksumSize);
+ }
+ stream->flush();
+ SET_LASTCALL("rcCreateDisplayById");
+ android::base::endTrace();
+ break;
+ }
+ case OP_rcSetDisplayPoseDpi: {
+ android::base::beginTrace("rcSetDisplayPoseDpi decode");
+ uint32_t var_displayId = Unpack<uint32_t,uint32_t>(ptr + 8);
+ GLint var_x = Unpack<GLint,uint32_t>(ptr + 8 + 4);
+ GLint var_y = Unpack<GLint,uint32_t>(ptr + 8 + 4 + 4);
+ uint32_t var_w = Unpack<uint32_t,uint32_t>(ptr + 8 + 4 + 4 + 4);
+ uint32_t var_h = Unpack<uint32_t,uint32_t>(ptr + 8 + 4 + 4 + 4 + 4);
+ uint32_t var_dpi = Unpack<uint32_t,uint32_t>(ptr + 8 + 4 + 4 + 4 + 4 + 4);
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::validOrDie(checksumCalc, ptr, 8 + 4 + 4 + 4 + 4 + 4 + 4, ptr + 8 + 4 + 4 + 4 + 4 + 4 + 4, checksumSize,
+ "renderControl_decoder_context_t::decode, OP_rcSetDisplayPoseDpi: GL checksumCalculator failure\n");
+ }
+ size_t totalTmpSize = sizeof(int);
+ totalTmpSize += checksumSize;
+ unsigned char *tmpBuf = stream->alloc(totalTmpSize);
+ *(int *)(&tmpBuf[0]) = this->rcSetDisplayPoseDpi(var_displayId, var_x, var_y, var_w, var_h, var_dpi);
+ if (useChecksum) {
+ ChecksumCalculatorThreadInfo::writeChecksum(checksumCalc, &tmpBuf[0], totalTmpSize - checksumSize, &tmpBuf[totalTmpSize - checksumSize], checksumSize);
+ }
+ stream->flush();
+ SET_LASTCALL("rcSetDisplayPoseDpi");
+ android::base::endTrace();
+ break;
+ }
default:
return ptr - (unsigned char*)buf;
} //switch
diff --git a/stream-servers/renderControl_dec/renderControl_opcodes.h b/stream-servers/renderControl_dec/renderControl_opcodes.h
index a3a6e27c..732d3e03 100644
--- a/stream-servers/renderControl_dec/renderControl_opcodes.h
+++ b/stream-servers/renderControl_dec/renderControl_opcodes.h
@@ -65,7 +65,9 @@
#define OP_rcDestroySyncKHRAsync 10059
#define OP_rcComposeWithoutPost 10060
#define OP_rcComposeAsyncWithoutPost 10061
-#define OP_last 10062
+#define OP_rcCreateDisplayById 10062
+#define OP_rcSetDisplayPoseDpi 10063
+#define OP_last 10064
#endif
diff --git a/stream-servers/renderControl_dec/renderControl_server_context.cpp b/stream-servers/renderControl_dec/renderControl_server_context.cpp
index 60ca587a..c6cbf234 100644
--- a/stream-servers/renderControl_dec/renderControl_server_context.cpp
+++ b/stream-servers/renderControl_dec/renderControl_server_context.cpp
@@ -72,6 +72,8 @@ int renderControl_server_context_t::initDispatchByName(void *(*getProc)(const ch
rcDestroySyncKHRAsync = (rcDestroySyncKHRAsync_server_proc_t) getProc("rcDestroySyncKHRAsync", userData);
rcComposeWithoutPost = (rcComposeWithoutPost_server_proc_t) getProc("rcComposeWithoutPost", userData);
rcComposeAsyncWithoutPost = (rcComposeAsyncWithoutPost_server_proc_t) getProc("rcComposeAsyncWithoutPost", userData);
+ rcCreateDisplayById = (rcCreateDisplayById_server_proc_t) getProc("rcCreateDisplayById", userData);
+ rcSetDisplayPoseDpi = (rcSetDisplayPoseDpi_server_proc_t) getProc("rcSetDisplayPoseDpi", userData);
return 0;
}
diff --git a/stream-servers/renderControl_dec/renderControl_server_context.h b/stream-servers/renderControl_dec/renderControl_server_context.h
index fdd46d03..f151288b 100644
--- a/stream-servers/renderControl_dec/renderControl_server_context.h
+++ b/stream-servers/renderControl_dec/renderControl_server_context.h
@@ -72,6 +72,8 @@ struct renderControl_server_context_t {
rcDestroySyncKHRAsync_server_proc_t rcDestroySyncKHRAsync;
rcComposeWithoutPost_server_proc_t rcComposeWithoutPost;
rcComposeAsyncWithoutPost_server_proc_t rcComposeAsyncWithoutPost;
+ rcCreateDisplayById_server_proc_t rcCreateDisplayById;
+ rcSetDisplayPoseDpi_server_proc_t rcSetDisplayPoseDpi;
virtual ~renderControl_server_context_t() {}
int initDispatchByName( void *(*getProc)(const char *name, void *userData), void *userData);
};
diff --git a/stream-servers/renderControl_dec/renderControl_server_proc.h b/stream-servers/renderControl_dec/renderControl_server_proc.h
index 50f25aeb..84d192a8 100644
--- a/stream-servers/renderControl_dec/renderControl_server_proc.h
+++ b/stream-servers/renderControl_dec/renderControl_server_proc.h
@@ -74,6 +74,8 @@ typedef void (renderControl_APIENTRY *rcComposeAsync_server_proc_t) (uint32_t, v
typedef void (renderControl_APIENTRY *rcDestroySyncKHRAsync_server_proc_t) (uint64_t);
typedef GLint (renderControl_APIENTRY *rcComposeWithoutPost_server_proc_t) (uint32_t, void*);
typedef void (renderControl_APIENTRY *rcComposeAsyncWithoutPost_server_proc_t) (uint32_t, void*);
+typedef int (renderControl_APIENTRY *rcCreateDisplayById_server_proc_t) (uint32_t);
+typedef int (renderControl_APIENTRY *rcSetDisplayPoseDpi_server_proc_t) (uint32_t, GLint, GLint, uint32_t, uint32_t, uint32_t);
#endif
diff --git a/stream-servers/virtio-gpu-gfxstream-renderer.cpp b/stream-servers/virtio-gpu-gfxstream-renderer.cpp
index 19c7d82f..63b486d3 100644
--- a/stream-servers/virtio-gpu-gfxstream-renderer.cpp
+++ b/stream-servers/virtio-gpu-gfxstream-renderer.cpp
@@ -337,13 +337,13 @@ static inline size_t virgl_format_to_total_xfer_len(
uint32_t totalWidth, uint32_t totalHeight,
uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
if (virgl_format_is_yuv(format)) {
- uint32_t align = (format == VIRGL_FORMAT_YV12) ? 32 : 16;
-
+ uint32_t yAlign = (format == VIRGL_FORMAT_YV12) ? 32 : 16;
uint32_t yWidth = totalWidth;
uint32_t yHeight = totalHeight;
- uint32_t yStride = align_up_power_of_2(yWidth, align);
+ uint32_t yStride = align_up_power_of_2(yWidth, yAlign);
uint32_t ySize = yStride * yHeight;
+ uint32_t uvAlign = 16;
uint32_t uvWidth;
uint32_t uvPlaneCount;
if (format == VIRGL_FORMAT_NV12) {
@@ -356,7 +356,7 @@ static inline size_t virgl_format_to_total_xfer_len(
VGP_FATAL("Unknown yuv virgl format: 0x%x", format);
}
uint32_t uvHeight = totalHeight / 2;
- uint32_t uvStride = align_up_power_of_2(uvWidth, align);
+ uint32_t uvStride = align_up_power_of_2(uvWidth, uvAlign);
uint32_t uvSize = uvStride * uvHeight * uvPlaneCount;
uint32_t dataSize = ySize + uvSize;
diff --git a/stream-servers/vulkan/Compositor.vert b/stream-servers/vulkan/Compositor.vert
index 5dbefbd4..40702633 100644
--- a/stream-servers/vulkan/Compositor.vert
+++ b/stream-servers/vulkan/Compositor.vert
@@ -2,7 +2,8 @@
#extension GL_ARB_separate_shader_objects : enable
layout(binding = 1) uniform UniformBufferObject {
- mat4 transform;
+ mat4 posTransform;
+ mat4 texcoordTransform;
} ubo;
layout(location = 0) in vec2 inPosition;
@@ -11,6 +12,6 @@ layout(location = 1) in vec2 texCoord;
layout(location = 0) out vec2 fragTexCoord;
void main() {
- gl_Position = vec4((ubo.transform * vec4(inPosition, 0.0, 1.0)).xy, 0.0, 1.0);
- fragTexCoord = texCoord;
-} \ No newline at end of file
+ gl_Position = vec4((ubo.posTransform * vec4(inPosition, 0.0, 1.0)).xy, 0.0, 1.0);
+ fragTexCoord = (ubo.texcoordTransform * vec4(texCoord, 0.0, 1.0)).xy;
+}
diff --git a/stream-servers/vulkan/CompositorVertexShader.h b/stream-servers/vulkan/CompositorVertexShader.h
index b1bbcfe2..d98b6daf 100644
--- a/stream-servers/vulkan/CompositorVertexShader.h
+++ b/stream-servers/vulkan/CompositorVertexShader.h
@@ -20,13 +20,13 @@
#include <stdint.h>
const uint32_t compositorVertexShader[] = {
-0x07230203, 0x00010000, 0x000d000a, 0x0000002b,
+0x07230203, 0x00010000, 0x000d000a, 0x00000033,
0x00000000, 0x00020011, 0x00000001, 0x0006000b,
0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
0x00000000, 0x0003000e, 0x00000000, 0x00000001,
0x0009000f, 0x00000000, 0x00000004, 0x6e69616d,
0x00000000, 0x0000000d, 0x00000019, 0x00000028,
-0x00000029, 0x00030003, 0x00000002, 0x000001c2,
+0x0000002c, 0x00030003, 0x00000002, 0x000001c2,
0x00090004, 0x415f4c47, 0x735f4252, 0x72617065,
0x5f657461, 0x64616873, 0x6f5f7265, 0x63656a62,
0x00007374, 0x000a0004, 0x475f4c47, 0x4c474f4f,
@@ -45,41 +45,47 @@ const uint32_t compositorVertexShader[] = {
0x435f6c67, 0x446c6c75, 0x61747369, 0x0065636e,
0x00030005, 0x0000000d, 0x00000000, 0x00070005,
0x00000011, 0x66696e55, 0x426d726f, 0x65666675,
-0x6a624f72, 0x00746365, 0x00060006, 0x00000011,
-0x00000000, 0x6e617274, 0x726f6673, 0x0000006d,
-0x00030005, 0x00000013, 0x006f6275, 0x00050005,
-0x00000019, 0x6f506e69, 0x69746973, 0x00006e6f,
-0x00060005, 0x00000028, 0x67617266, 0x43786554,
-0x64726f6f, 0x00000000, 0x00050005, 0x00000029,
-0x43786574, 0x64726f6f, 0x00000000, 0x00050048,
-0x0000000b, 0x00000000, 0x0000000b, 0x00000000,
-0x00050048, 0x0000000b, 0x00000001, 0x0000000b,
-0x00000001, 0x00050048, 0x0000000b, 0x00000002,
-0x0000000b, 0x00000003, 0x00050048, 0x0000000b,
-0x00000003, 0x0000000b, 0x00000004, 0x00030047,
-0x0000000b, 0x00000002, 0x00040048, 0x00000011,
-0x00000000, 0x00000005, 0x00050048, 0x00000011,
-0x00000000, 0x00000023, 0x00000000, 0x00050048,
-0x00000011, 0x00000000, 0x00000007, 0x00000010,
-0x00030047, 0x00000011, 0x00000002, 0x00040047,
-0x00000013, 0x00000022, 0x00000000, 0x00040047,
-0x00000013, 0x00000021, 0x00000001, 0x00040047,
-0x00000019, 0x0000001e, 0x00000000, 0x00040047,
-0x00000028, 0x0000001e, 0x00000000, 0x00040047,
-0x00000029, 0x0000001e, 0x00000001, 0x00020013,
-0x00000002, 0x00030021, 0x00000003, 0x00000002,
-0x00030016, 0x00000006, 0x00000020, 0x00040017,
-0x00000007, 0x00000006, 0x00000004, 0x00040015,
-0x00000008, 0x00000020, 0x00000000, 0x0004002b,
-0x00000008, 0x00000009, 0x00000001, 0x0004001c,
-0x0000000a, 0x00000006, 0x00000009, 0x0006001e,
-0x0000000b, 0x00000007, 0x00000006, 0x0000000a,
-0x0000000a, 0x00040020, 0x0000000c, 0x00000003,
-0x0000000b, 0x0004003b, 0x0000000c, 0x0000000d,
-0x00000003, 0x00040015, 0x0000000e, 0x00000020,
-0x00000001, 0x0004002b, 0x0000000e, 0x0000000f,
-0x00000000, 0x00040018, 0x00000010, 0x00000007,
-0x00000004, 0x0003001e, 0x00000011, 0x00000010,
+0x6a624f72, 0x00746365, 0x00070006, 0x00000011,
+0x00000000, 0x54736f70, 0x736e6172, 0x6d726f66,
+0x00000000, 0x00080006, 0x00000011, 0x00000001,
+0x63786574, 0x64726f6f, 0x6e617254, 0x726f6673,
+0x0000006d, 0x00030005, 0x00000013, 0x006f6275,
+0x00050005, 0x00000019, 0x6f506e69, 0x69746973,
+0x00006e6f, 0x00060005, 0x00000028, 0x67617266,
+0x43786554, 0x64726f6f, 0x00000000, 0x00050005,
+0x0000002c, 0x43786574, 0x64726f6f, 0x00000000,
+0x00050048, 0x0000000b, 0x00000000, 0x0000000b,
+0x00000000, 0x00050048, 0x0000000b, 0x00000001,
+0x0000000b, 0x00000001, 0x00050048, 0x0000000b,
+0x00000002, 0x0000000b, 0x00000003, 0x00050048,
+0x0000000b, 0x00000003, 0x0000000b, 0x00000004,
+0x00030047, 0x0000000b, 0x00000002, 0x00040048,
+0x00000011, 0x00000000, 0x00000005, 0x00050048,
+0x00000011, 0x00000000, 0x00000023, 0x00000000,
+0x00050048, 0x00000011, 0x00000000, 0x00000007,
+0x00000010, 0x00040048, 0x00000011, 0x00000001,
+0x00000005, 0x00050048, 0x00000011, 0x00000001,
+0x00000023, 0x00000040, 0x00050048, 0x00000011,
+0x00000001, 0x00000007, 0x00000010, 0x00030047,
+0x00000011, 0x00000002, 0x00040047, 0x00000013,
+0x00000022, 0x00000000, 0x00040047, 0x00000013,
+0x00000021, 0x00000001, 0x00040047, 0x00000019,
+0x0000001e, 0x00000000, 0x00040047, 0x00000028,
+0x0000001e, 0x00000000, 0x00040047, 0x0000002c,
+0x0000001e, 0x00000001, 0x00020013, 0x00000002,
+0x00030021, 0x00000003, 0x00000002, 0x00030016,
+0x00000006, 0x00000020, 0x00040017, 0x00000007,
+0x00000006, 0x00000004, 0x00040015, 0x00000008,
+0x00000020, 0x00000000, 0x0004002b, 0x00000008,
+0x00000009, 0x00000001, 0x0004001c, 0x0000000a,
+0x00000006, 0x00000009, 0x0006001e, 0x0000000b,
+0x00000007, 0x00000006, 0x0000000a, 0x0000000a,
+0x00040020, 0x0000000c, 0x00000003, 0x0000000b,
+0x0004003b, 0x0000000c, 0x0000000d, 0x00000003,
+0x00040015, 0x0000000e, 0x00000020, 0x00000001,
+0x0004002b, 0x0000000e, 0x0000000f, 0x00000000,
+0x00040018, 0x00000010, 0x00000007, 0x00000004,
+0x0004001e, 0x00000011, 0x00000010, 0x00000010,
0x00040020, 0x00000012, 0x00000002, 0x00000011,
0x0004003b, 0x00000012, 0x00000013, 0x00000002,
0x00040020, 0x00000014, 0x00000002, 0x00000010,
@@ -91,7 +97,8 @@ const uint32_t compositorVertexShader[] = {
0x00040020, 0x00000025, 0x00000003, 0x00000007,
0x00040020, 0x00000027, 0x00000003, 0x00000017,
0x0004003b, 0x00000027, 0x00000028, 0x00000003,
-0x0004003b, 0x00000018, 0x00000029, 0x00000001,
+0x0004002b, 0x0000000e, 0x00000029, 0x00000001,
+0x0004003b, 0x00000018, 0x0000002c, 0x00000001,
0x00050036, 0x00000002, 0x00000004, 0x00000000,
0x00000003, 0x000200f8, 0x00000005, 0x00050041,
0x00000014, 0x00000015, 0x00000013, 0x0000000f,
@@ -110,7 +117,17 @@ const uint32_t compositorVertexShader[] = {
0x00000007, 0x00000024, 0x00000022, 0x00000023,
0x0000001b, 0x0000001c, 0x00050041, 0x00000025,
0x00000026, 0x0000000d, 0x0000000f, 0x0003003e,
-0x00000026, 0x00000024, 0x0004003d, 0x00000017,
-0x0000002a, 0x00000029, 0x0003003e, 0x00000028,
-0x0000002a, 0x000100fd, 0x00010038
-}; \ No newline at end of file
+0x00000026, 0x00000024, 0x00050041, 0x00000014,
+0x0000002a, 0x00000013, 0x00000029, 0x0004003d,
+0x00000010, 0x0000002b, 0x0000002a, 0x0004003d,
+0x00000017, 0x0000002d, 0x0000002c, 0x00050051,
+0x00000006, 0x0000002e, 0x0000002d, 0x00000000,
+0x00050051, 0x00000006, 0x0000002f, 0x0000002d,
+0x00000001, 0x00070050, 0x00000007, 0x00000030,
+0x0000002e, 0x0000002f, 0x0000001b, 0x0000001c,
+0x00050091, 0x00000007, 0x00000031, 0x0000002b,
+0x00000030, 0x0007004f, 0x00000017, 0x00000032,
+0x00000031, 0x00000031, 0x00000000, 0x00000001,
+0x0003003e, 0x00000028, 0x00000032, 0x000100fd,
+0x00010038
+};
diff --git a/stream-servers/vulkan/VkAndroidNativeBuffer.cpp b/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
index 5bc4f24e..42ea6183 100644
--- a/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
+++ b/stream-servers/vulkan/VkAndroidNativeBuffer.cpp
@@ -277,10 +277,6 @@ void teardownAndroidNativeBufferImage(
anbInfo->acquireQueueState.teardown(vk, device);
- if (anbInfo->externallyBacked) {
- teardownVkColorBuffer(anbInfo->colorBufferHandle);
- }
-
*anbInfo = {};
}
@@ -399,6 +395,7 @@ void AndroidNativeBufferInfo::QueueState::setup(
void AndroidNativeBufferInfo::QueueState::teardown(
VulkanDispatch* vk, VkDevice device) {
+ if (queue) vk->vkQueueWaitIdle(queue);
if (cb) vk->vkFreeCommandBuffers(device, pool, 1, &cb);
if (pool) vk->vkDestroyCommandPool(device, pool, nullptr);
if (fence) vk->vkDestroyFence(device, fence, nullptr);