mirror of
https://github.com/libsdl-org/SDL.git
synced 2024-11-27 05:43:29 +08:00
Closes #10318 - implement Android prerotation in the Vulkan renderer
This commit is contained in:
parent
93471cf78d
commit
4f160d69a6
@ -361,6 +361,7 @@ typedef struct
|
||||
uint32_t swapchainDesiredImageCount;
|
||||
VkSurfaceFormatKHR surfaceFormat;
|
||||
VkExtent2D swapchainSize;
|
||||
VkSurfaceTransformFlagBitsKHR swapChainPreTransform;
|
||||
uint32_t swapchainImageCount;
|
||||
VkImage *swapchainImages;
|
||||
VkImageView *swapchainImageViews;
|
||||
@ -477,6 +478,8 @@ static bool VULKAN_FindMemoryTypeIndex(VULKAN_RenderData *rendererData, uint32_t
|
||||
static VkResult VULKAN_CreateWindowSizeDependentResources(SDL_Renderer *renderer);
|
||||
static VkDescriptorPool VULKAN_AllocateDescriptorPool(VULKAN_RenderData *rendererData);
|
||||
static VkResult VULKAN_CreateDescriptorSetAndPipelineLayout(VULKAN_RenderData *rendererData, VkSampler samplerYcbcr, VkDescriptorSetLayout *descriptorSetLayoutOut, VkPipelineLayout *pipelineLayoutOut);
|
||||
static VkSurfaceTransformFlagBitsKHR VULKAN_GetRotationForCurrentRenderTarget(VULKAN_RenderData *rendererData);
|
||||
static bool VULKAN_IsDisplayRotated90Degrees(VkSurfaceTransformFlagBitsKHR rotation);
|
||||
|
||||
static void VULKAN_DestroyAll(SDL_Renderer *renderer)
|
||||
{
|
||||
@ -923,6 +926,7 @@ static void VULKAN_BeginRenderPass(VULKAN_RenderData *rendererData, VkAttachment
|
||||
width = rendererData->textureRenderTarget->width;
|
||||
height = rendererData->textureRenderTarget->height;
|
||||
}
|
||||
|
||||
switch (loadOp) {
|
||||
case VK_ATTACHMENT_LOAD_OP_CLEAR:
|
||||
rendererData->currentRenderPass = rendererData->textureRenderTarget ?
|
||||
@ -2212,6 +2216,15 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
rendererData->surfaceCapabilities.minImageExtent.height,
|
||||
rendererData->surfaceCapabilities.maxImageExtent.height);
|
||||
|
||||
// Handle rotation
|
||||
rendererData->swapChainPreTransform = rendererData->surfaceCapabilities.currentTransform;
|
||||
if (rendererData->swapChainPreTransform == VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||
|
||||
rendererData->swapChainPreTransform == VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
|
||||
uint32_t tempWidth = rendererData->swapchainSize.width;
|
||||
rendererData->swapchainSize.width = rendererData->swapchainSize.height;
|
||||
rendererData->swapchainSize.height = tempWidth;
|
||||
}
|
||||
|
||||
if (rendererData->swapchainSize.width == 0 && rendererData->swapchainSize.height == 0) {
|
||||
// Don't recreate the swapchain if size is (0,0), just fail and continue attempting creation
|
||||
return VK_ERROR_OUT_OF_DATE_KHR;
|
||||
@ -2275,7 +2288,7 @@ static VkResult VULKAN_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
swapchainCreateInfo.imageArrayLayers = 1;
|
||||
swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
swapchainCreateInfo.preTransform = rendererData->surfaceCapabilities.currentTransform;
|
||||
swapchainCreateInfo.preTransform = rendererData->swapChainPreTransform;
|
||||
swapchainCreateInfo.compositeAlpha = (renderer->window->flags & SDL_WINDOW_TRANSPARENT) ? (VkCompositeAlphaFlagBitsKHR)0 : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||
swapchainCreateInfo.presentMode = presentMode;
|
||||
swapchainCreateInfo.clipped = VK_TRUE;
|
||||
@ -3249,12 +3262,34 @@ static bool VULKAN_UpdateVertexBuffer(SDL_Renderer *renderer,
|
||||
return true;
|
||||
}
|
||||
|
||||
static VkSurfaceTransformFlagBitsKHR VULKAN_GetRotationForCurrentRenderTarget(VULKAN_RenderData *rendererData)
|
||||
{
|
||||
if (rendererData->textureRenderTarget) {
|
||||
return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
} else {
|
||||
return rendererData->swapChainPreTransform;
|
||||
}
|
||||
}
|
||||
|
||||
static bool VULKAN_IsDisplayRotated90Degrees(VkSurfaceTransformFlagBitsKHR rotation)
|
||||
{
|
||||
switch (rotation) {
|
||||
case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
|
||||
case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool VULKAN_UpdateViewport(SDL_Renderer *renderer)
|
||||
{
|
||||
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
|
||||
const SDL_Rect *viewport = &rendererData->currentViewport;
|
||||
Float4X4 projection;
|
||||
Float4X4 view;
|
||||
VkSurfaceTransformFlagBitsKHR rotation = VULKAN_GetRotationForCurrentRenderTarget(rendererData);
|
||||
bool swapDimensions;
|
||||
|
||||
if (viewport->w == 0 || viewport->h == 0) {
|
||||
/* If the viewport is empty, assume that it is because
|
||||
@ -3265,7 +3300,22 @@ static bool VULKAN_UpdateViewport(SDL_Renderer *renderer)
|
||||
return false;
|
||||
}
|
||||
|
||||
projection = MatrixIdentity();
|
||||
switch (rotation) {
|
||||
case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
|
||||
projection = MatrixRotationZ(SDL_PI_F * 0.5f);
|
||||
break;
|
||||
case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
|
||||
projection = MatrixRotationZ(SDL_PI_F);
|
||||
break;
|
||||
case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
|
||||
projection = MatrixRotationZ(-SDL_PI_F * 0.5f);
|
||||
break;
|
||||
case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
|
||||
default:
|
||||
projection = MatrixIdentity();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Update the view matrix
|
||||
SDL_zero(view);
|
||||
@ -3281,10 +3331,20 @@ static bool VULKAN_UpdateViewport(SDL_Renderer *renderer)
|
||||
projection);
|
||||
|
||||
VkViewport vkViewport;
|
||||
vkViewport.x = viewport->x;
|
||||
vkViewport.y = viewport->y;
|
||||
vkViewport.width = viewport->w;
|
||||
vkViewport.height = viewport->h;
|
||||
|
||||
swapDimensions = VULKAN_IsDisplayRotated90Degrees(rotation);
|
||||
if (swapDimensions) {
|
||||
vkViewport.x = viewport->y;
|
||||
vkViewport.y = viewport->x;
|
||||
vkViewport.width = viewport->h;
|
||||
vkViewport.height = viewport->w;
|
||||
}
|
||||
else {
|
||||
vkViewport.x = viewport->x;
|
||||
vkViewport.y = viewport->y;
|
||||
vkViewport.width = viewport->w;
|
||||
vkViewport.height = viewport->h;
|
||||
}
|
||||
vkViewport.minDepth = 0.0f;
|
||||
vkViewport.maxDepth = 1.0f;
|
||||
vkCmdSetViewport(rendererData->currentCommandBuffer, 0, 1, &vkViewport);
|
||||
@ -3297,6 +3357,8 @@ static bool VULKAN_UpdateClipRect(SDL_Renderer *renderer)
|
||||
{
|
||||
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
|
||||
const SDL_Rect *viewport = &rendererData->currentViewport;
|
||||
VkSurfaceTransformFlagBitsKHR rotation = VULKAN_GetRotationForCurrentRenderTarget(rendererData);
|
||||
bool swapDimensions = VULKAN_IsDisplayRotated90Degrees(rotation);
|
||||
|
||||
VkRect2D scissor;
|
||||
if (rendererData->currentCliprectEnabled) {
|
||||
@ -3310,6 +3372,13 @@ static bool VULKAN_UpdateClipRect(SDL_Renderer *renderer)
|
||||
scissor.extent.width = viewport->w;
|
||||
scissor.extent.height = viewport->h;
|
||||
}
|
||||
if (swapDimensions) {
|
||||
VkRect2D scissorTemp = scissor;
|
||||
scissor.offset.x = scissorTemp.offset.y;
|
||||
scissor.offset.y = scissorTemp.offset.x;
|
||||
scissor.extent.width = scissorTemp.extent.height;
|
||||
scissor.extent.height = scissorTemp.extent.width;
|
||||
}
|
||||
vkCmdSetScissor(rendererData->currentCommandBuffer, 0, 1, &scissor);
|
||||
|
||||
rendererData->cliprectDirty = false;
|
||||
@ -3769,6 +3838,7 @@ static void VULKAN_InvalidateCachedState(SDL_Renderer *renderer)
|
||||
static bool VULKAN_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
|
||||
{
|
||||
VULKAN_RenderData *rendererData = (VULKAN_RenderData *)renderer->internal;
|
||||
VkSurfaceTransformFlagBitsKHR currentRotation = VULKAN_GetRotationForCurrentRenderTarget(rendererData);
|
||||
VULKAN_DrawStateCache stateCache;
|
||||
SDL_memset(&stateCache, 0, sizeof(stateCache));
|
||||
|
||||
@ -3776,6 +3846,12 @@ static bool VULKAN_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cm
|
||||
return SDL_SetError("Device lost and couldn't be recovered");
|
||||
}
|
||||
|
||||
if(rendererData->currentViewportRotation != currentRotation) {
|
||||
rendererData->currentViewportRotation = currentRotation;
|
||||
rendererData->viewportDirty = true;
|
||||
rendererData->cliprectDirty = true;
|
||||
}
|
||||
|
||||
if (rendererData->recreateSwapchain) {
|
||||
if (VULKAN_UpdateForWindowSizeChange(renderer) != VK_SUCCESS) {
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user