diff --git a/CMakeLists.txt b/CMakeLists.txt index f504f933f8347..8f3bd5e27192d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2010,6 +2010,7 @@ elseif(WINDOWS) set(HAVE_VULKAN TRUE) if(SDL_RENDER_VULKAN) set(SDL_VIDEO_RENDER_VULKAN 1) + set(HAVE_RENDER_VULKAN TRUE) endif() endif() endif() @@ -2254,6 +2255,7 @@ elseif(APPLE) set(HAVE_VULKAN TRUE) if(SDL_RENDER_VULKAN) set(SDL_VIDEO_RENDER_VULKAN 1) + set(HAVE_RENDER_VULKAN TRUE) endif() endif() if(SDL_METAL) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index 4cf36f3e8a30e..7fae2524b4e17 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -725,7 +725,10 @@ macro(CheckVulkan) if(SDL_VULKAN) set(SDL_VIDEO_VULKAN 1) set(HAVE_VULKAN TRUE) - set(SDL_VIDEO_RENDER_VULKAN 1) + if(SDL_RENDER_VULKAN) + set(SDL_VIDEO_RENDER_VULKAN 1) + set(HAVE_RENDER_VULKAN TRUE) + endif() endif() endmacro() diff --git a/src/render/vulkan/SDL_render_vulkan.c b/src/render/vulkan/SDL_render_vulkan.c index bce68ca9401f8..d5564cfd33ca1 100644 --- a/src/render/vulkan/SDL_render_vulkan.c +++ b/src/render/vulkan/SDL_render_vulkan.c @@ -404,6 +404,8 @@ static VkFormat SDLPixelFormatToVkTextureFormat(Uint32 format, Uint32 colorspace case SDL_PIXELFORMAT_NV12: /* Y plane */ case SDL_PIXELFORMAT_NV21: /* Y plane */ return VK_FORMAT_R8_UNORM; + case SDL_PIXELFORMAT_P010: + return VK_FORMAT_R16_UNORM; default: return VK_FORMAT_UNDEFINED; } @@ -2408,7 +2410,7 @@ static int VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD texture->format == SDL_PIXELFORMAT_P010) { int bits_per_pixel; VkFormat uvFormat = VK_FORMAT_R8G8_UNORM; - if (texture->format == SDL_PIXELFORMAT_P010 || texture->format == SDL_PIXELFORMAT_P016) { + if (texture->format == SDL_PIXELFORMAT_P010) { uvFormat = VK_FORMAT_R16G16_UNORM; } textureData->nv12 = SDL_TRUE; @@ -2534,7 +2536,7 @@ static VkResult VULKAN_UpdateTextureInternal(VULKAN_RenderData *rendererData, Vk for (VkDeviceSize row = h; row--; ) { SDL_memcpy(dst, src, length); src += pitch; - dst += pitch; + dst += length; } } @@ -3220,7 +3222,7 @@ static VkDescriptorSet VULKAN_AllocateDescriptorSet(SDL_Renderer *renderer, VULK } uint32_t startImageViews = descriptorCount; - for (uint32_t i = 0; i < 3 && imageViewCount > 0; i++) { + for (int i = 0; i < 3 && imageViewCount > 0; i++) { descriptorCount++; imageDescriptors[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; /* There are up to 3 images in the shader, if we haven't specified that many, duplicate the first @@ -3363,12 +3365,12 @@ static SDL_bool VULKAN_SetDrawState(SDL_Renderer *renderer, const SDL_RenderComm constantBuffer = rendererData->constantBuffers[rendererData->currentCommandBufferIndex][rendererData->currentConstantBufferIndex].buffer; } + SDL_memcpy(&rendererData->currentPipelineState->shader_constants, shader_constants, sizeof(*shader_constants)); + /* Upload constants to persistently mapped buffer */ uint8_t *dst = rendererData->constantBuffers[rendererData->currentCommandBufferIndex][rendererData->currentConstantBufferIndex].mappedBufferPtr; dst += constantBufferOffset; SDL_memcpy(dst, &rendererData->currentPipelineState->shader_constants, sizeof(PixelShaderConstants)); - - SDL_memcpy(&rendererData->currentPipelineState->shader_constants, shader_constants, sizeof(*shader_constants)); } /* Allocate/update descriptor set with the bindings */ diff --git a/src/video/SDL_blit_slow.c b/src/video/SDL_blit_slow.c index d16be66e118b9..9bd59a752af36 100644 --- a/src/video/SDL_blit_slow.c +++ b/src/video/SDL_blit_slow.c @@ -699,6 +699,17 @@ static void TonemapLinear(float *r, float *g, float *b, float scale) *b *= scale; } +/* This uses the same tonemapping algorithm developed by Google for Chrome: + * https://colab.research.google.com/drive/1hI10nq6L6ru_UFvz7-f7xQaQp0qarz_K + * + * Essentially, you use the source headroom and the destination headroom + * to calculate scaling factors: + * tonemap_a = (dst_headroom / (src_headroom * src_headroom)); + * tonemap_b = (1.0f / dst_headroom); + * + * Then you normalize your source color by the HDR whitepoint, + * and calculate a final scaling factor in BT.2020 colorspace. + */ static void TonemapChrome(float *r, float *g, float *b, float tonemap_a, float tonemap_b) { float v1 = *r; diff --git a/test/testffmpeg.c b/test/testffmpeg.c index d151ff05b0193..1770dca4506fb 100644 --- a/test/testffmpeg.c +++ b/test/testffmpeg.c @@ -259,6 +259,10 @@ static Uint32 GetTextureFormat(enum AVPixelFormat format) return SDL_PIXELFORMAT_YUY2; case AV_PIX_FMT_UYVY422: return SDL_PIXELFORMAT_UYVY; + case AV_PIX_FMT_NV12: + return SDL_PIXELFORMAT_NV12; + case AV_PIX_FMT_NV21: + return SDL_PIXELFORMAT_NV21; default: return SDL_PIXELFORMAT_UNKNOWN; } @@ -428,6 +432,33 @@ static SDL_Colorspace GetFrameColorspace(AVFrame *frame) return colorspace; } +static SDL_PropertiesID CreateVideoTextureProperties(AVFrame *frame, Uint32 format, int access, int w, int h) +{ + AVFrameSideData *pSideData; + SDL_PropertiesID props; + + props = SDL_CreateProperties(); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame)); + pSideData = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); + if (pSideData) { + /* ITU-R BT.2408-6 recommends using an SDR white point of 203 nits, which is more likely for game content */ + static const float k_flSDRWhitePoint = 203.0f; + + AVMasteringDisplayMetadata *pMasteringDisplayMetadata = (AVMasteringDisplayMetadata *)pSideData->data; + float flMaxLuminance = (float)pMasteringDisplayMetadata->max_luminance.num / pMasteringDisplayMetadata->max_luminance.den; + if (flMaxLuminance > k_flSDRWhitePoint) { + SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT, k_flSDRWhitePoint); + SDL_SetFloatProperty(props, SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT, flMaxLuminance / k_flSDRWhitePoint); + } + } + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, access); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, w); + SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, h); + + return props; +} + static void SDLCALL FreeSwsContextContainer(void *userdata, void *value) { struct SwsContextContainer *sws_container = (struct SwsContextContainer *)value; @@ -453,16 +484,12 @@ static SDL_bool GetTextureForMemoryFrame(AVFrame *frame, SDL_Texture **texture) SDL_DestroyTexture(*texture); } - SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame)); + SDL_PropertiesID props; if (frame_format == SDL_PIXELFORMAT_UNKNOWN) { - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_ARGB8888); + props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); } else { - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, frame_format); + props = CreateVideoTextureProperties(frame, frame_format, SDL_TEXTUREACCESS_STREAMING, frame->width, frame->height); } - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STREAMING); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, frame->width); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, frame->height); *texture = SDL_CreateTextureWithProperties(renderer, props); SDL_DestroyProperties(props); if (!*texture) { @@ -552,12 +579,7 @@ static SDL_bool GetTextureForDRMFrame(AVFrame *frame, SDL_Texture **texture) SDL_SetHint("SDL_RENDER_OPENGL_NV12_RG_SHADER", "1"); } - props = SDL_CreateProperties(); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame)); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, SDL_PIXELFORMAT_NV12); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, frame->width); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, frame->height); + props = CreateVideoTextureProperties(frame, SDL_PIXELFORMAT_NV12, SDL_TEXTUREACCESS_STATIC, frame->width, frame->height); *texture = SDL_CreateTextureWithProperties(renderer, props); SDL_DestroyProperties(props); if (!*texture) { @@ -657,11 +679,7 @@ static SDL_bool GetTextureForD3D11Frame(AVFrame *frame, SDL_Texture **texture) SDL_DestroyTexture(*texture); } - SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame)); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, desc.Width); + SDL_PropertiesID props = CreateVideoTextureProperties(frame, format, SDL_TEXTUREACCESS_STATIC, desc.Width, desc.Height); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, desc.Height); *texture = SDL_CreateTextureWithProperties(renderer, props); SDL_DestroyProperties(props); @@ -717,12 +735,7 @@ static SDL_bool GetTextureForVideoToolboxFrame(AVFrame *frame, SDL_Texture **tex SDL_DestroyTexture(*texture); } - props = SDL_CreateProperties(); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, GetFrameColorspace(frame)); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER, format); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, nPixelBufferWidth); - SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, nPixelBufferHeight); + props = CreateVideoTextureProperties(frame, format, SDL_TEXTUREACCESS_STATIC, nPixelBufferWidth, nPixelBufferHeight); SDL_SetProperty(props, SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER, pPixelBuffer); *texture = SDL_CreateTextureWithProperties(renderer, props); SDL_DestroyProperties(props); @@ -754,20 +767,6 @@ static SDL_bool GetTextureForFrame(AVFrame *frame, SDL_Texture **texture) static void DisplayVideoTexture(AVFrame *frame) { -#if 0 /* This data doesn't seem to be valid in any of the videos I've tried */ - AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); - if (sd) { - AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data; - mdm = mdm; - } - - sd = av_frame_get_side_data(frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); - if (sd) { - AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data; - clm = clm; - } -#endif /* 0 */ - /* Update the video texture */ if (!GetTextureForFrame(frame, &video_texture)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't get texture for frame: %s\n", SDL_GetError()); @@ -1008,6 +1007,9 @@ int main(int argc, char *argv[]) #elif !defined(SDL_PLATFORM_WIN32) window_flags |= SDL_WINDOW_OPENGL; #endif + if (SDL_GetHint(SDL_HINT_RENDER_DRIVER) != NULL) { + CreateWindowAndRenderer(window_flags, SDL_GetHint(SDL_HINT_RENDER_DRIVER)); + } #ifdef HAVE_EGL /* Try to create an EGL compatible window for DRM hardware frame support */ if (!window) { @@ -1133,7 +1135,8 @@ int main(int argc, char *argv[]) /* Check for events */ while (SDL_PollEvent(&event)) { - if (event.type == SDL_EVENT_QUIT || event.type == SDL_EVENT_KEY_DOWN) { + if (event.type == SDL_EVENT_QUIT || + (event.type == SDL_EVENT_KEY_DOWN && event.key.keysym.sym == SDLK_ESCAPE)) { done = 1; } }