diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2021-05-07 00:29:35 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2021-05-07 00:29:35 +0000 |
commit | 7da7662377165edbf9ec59f722a3ef208ff3d9e6 (patch) | |
tree | 95ac76eff2fc387ee5ebac0a3bf8d18ee0df2459 | |
parent | ed03f529fb0d847ee0e838af2c0017e3098b83b0 (diff) | |
parent | 85532f3dc56bdb461e1c5b7da20d514aa67ff66d (diff) | |
download | vulkan-cereal-7da7662377165edbf9ec59f722a3ef208ff3d9e6.tar.gz |
Snap for 7343852 from 85532f3dc56bdb461e1c5b7da20d514aa67ff66d to sc-mainline-release
Change-Id: I841b294e6da150bb3b1d1ce501e5ec40386b0b32
29 files changed, 796 insertions, 274 deletions
@@ -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 ¤tComposition = *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 ¤tComposition = *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); |