Added support for the scRGB colorspace on D3D11 and D3D12
This commit is contained in:
@@ -965,6 +965,10 @@ SDL3_0.0.0 {
|
||||
SDL_GetTextureAlphaModFloat;
|
||||
SDL_SetRenderDrawColorFloat;
|
||||
SDL_GetRenderDrawColorFloat;
|
||||
SDL_ConvertPixelsAndColorspace;
|
||||
SDL_SetSurfaceColorspace;
|
||||
SDL_GetSurfaceColorspace;
|
||||
SDL_ConvertSurfaceFormatAndColorspace;
|
||||
# extra symbols go here (don't modify this line)
|
||||
local: *;
|
||||
};
|
||||
|
||||
@@ -990,3 +990,7 @@
|
||||
#define SDL_GetTextureAlphaModFloat SDL_GetTextureAlphaModFloat_REAL
|
||||
#define SDL_SetRenderDrawColorFloat SDL_SetRenderDrawColorFloat_REAL
|
||||
#define SDL_GetRenderDrawColorFloat SDL_GetRenderDrawColorFloat_REAL
|
||||
#define SDL_ConvertPixelsAndColorspace SDL_ConvertPixelsAndColorspace_REAL
|
||||
#define SDL_SetSurfaceColorspace SDL_SetSurfaceColorspace_REAL
|
||||
#define SDL_GetSurfaceColorspace SDL_GetSurfaceColorspace_REAL
|
||||
#define SDL_ConvertSurfaceFormatAndColorspace SDL_ConvertSurfaceFormatAndColorspace_REAL
|
||||
|
||||
@@ -1015,3 +1015,7 @@ SDL_DYNAPI_PROC(int,SDL_SetTextureAlphaModFloat,(SDL_Texture *a, float b),(a,b),
|
||||
SDL_DYNAPI_PROC(int,SDL_GetTextureAlphaModFloat,(SDL_Texture *a, float *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetRenderDrawColorFloat,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GetRenderDrawColorFloat,(SDL_Renderer *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_ConvertPixelsAndColorspace,(int a, int b, Uint32 c, SDL_Colorspace d, const void *e, int f, Uint32 g, SDL_Colorspace h, void *i, int j),(a,b,c,d,e,f,g,h,i,j),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurfaceFormatAndColorspace,(SDL_Surface *a, Uint32 b, SDL_Colorspace c),(a,b,c),return)
|
||||
|
||||
@@ -865,7 +865,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
SDL_Renderer *renderer = NULL;
|
||||
const int n = SDL_GetNumRenderDrivers();
|
||||
const char *hint;
|
||||
int i;
|
||||
int i, attempted = 0;
|
||||
|
||||
if (!window && surface) {
|
||||
return SDL_CreateSoftwareRenderer(surface);
|
||||
@@ -904,6 +904,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
const SDL_RenderDriver *driver = render_drivers[i];
|
||||
if (SDL_strcasecmp(name, driver->info.name) == 0) {
|
||||
/* Create a new renderer instance */
|
||||
++attempted;
|
||||
renderer = driver->CreateRenderer(window, props);
|
||||
break;
|
||||
}
|
||||
@@ -912,6 +913,7 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
for (i = 0; i < n; i++) {
|
||||
const SDL_RenderDriver *driver = render_drivers[i];
|
||||
/* Create a new renderer instance */
|
||||
++attempted;
|
||||
renderer = driver->CreateRenderer(window, props);
|
||||
if (renderer) {
|
||||
/* Yay, we got one! */
|
||||
@@ -921,7 +923,9 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
|
||||
}
|
||||
|
||||
if (!renderer) {
|
||||
SDL_SetError("Couldn't find matching render driver");
|
||||
if (!name || !attempted) {
|
||||
SDL_SetError("Couldn't find matching render driver");
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1175,19 +1179,6 @@ static SDL_ScaleMode SDL_GetScaleMode(void)
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Colorspace SDL_GetDefaultTextureColorspace(Uint32 format)
|
||||
{
|
||||
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
||||
return SDL_COLORSPACE_BT709_FULL;
|
||||
} else if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
||||
return SDL_COLORSPACE_SCRGB;
|
||||
} else if (SDL_ISPIXELFORMAT_10BIT(format)) {
|
||||
return SDL_COLORSPACE_HDR10;
|
||||
} else {
|
||||
return SDL_COLORSPACE_SRGB;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props)
|
||||
{
|
||||
SDL_Texture *texture;
|
||||
@@ -1195,7 +1186,7 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert
|
||||
int access = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
|
||||
int w = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, 0);
|
||||
int h = (int)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, 0);
|
||||
Uint32 default_colorspace;
|
||||
SDL_Colorspace default_colorspace;
|
||||
SDL_bool texture_is_fourcc_and_target;
|
||||
|
||||
CHECK_RENDERER_MAGIC(renderer, NULL);
|
||||
@@ -1223,14 +1214,14 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert
|
||||
return NULL;
|
||||
}
|
||||
|
||||
default_colorspace = SDL_GetDefaultTextureColorspace(format);
|
||||
default_colorspace = SDL_GetDefaultColorspaceForFormat(format);
|
||||
|
||||
texture = (SDL_Texture *)SDL_calloc(1, sizeof(*texture));
|
||||
if (!texture) {
|
||||
return NULL;
|
||||
}
|
||||
texture->magic = &SDL_texture_magic;
|
||||
texture->colorspace = (Uint32)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, default_colorspace);
|
||||
texture->colorspace = (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER, default_colorspace);
|
||||
texture->format = format;
|
||||
texture->access = access;
|
||||
texture->w = w;
|
||||
@@ -1334,7 +1325,7 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
||||
Uint32 format = SDL_PIXELFORMAT_UNKNOWN;
|
||||
SDL_Texture *texture;
|
||||
SDL_PropertiesID props;
|
||||
SDL_Colorspace default_colorspace, colorspace;
|
||||
SDL_Colorspace colorspace = SDL_COLORSPACE_UNKNOWN;
|
||||
|
||||
CHECK_RENDERER_MAGIC(renderer, NULL);
|
||||
|
||||
@@ -1414,12 +1405,8 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
|
||||
direct_update = SDL_FALSE;
|
||||
}
|
||||
|
||||
if (direct_update) {
|
||||
default_colorspace = SDL_GetDefaultTextureColorspace(format);
|
||||
colorspace = (SDL_Colorspace)SDL_GetNumberProperty(SDL_GetSurfaceProperties(surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, default_colorspace);
|
||||
} else {
|
||||
/* We're updating through an intermediate surface, so we lose colorspace information */
|
||||
colorspace = SDL_COLORSPACE_RGB_DEFAULT;
|
||||
if (SDL_GetSurfaceColorspace(surface, &colorspace) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
props = SDL_CreateProperties();
|
||||
|
||||
@@ -1566,6 +1566,14 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (D3D_RenderData *)SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
SDL_free(renderer);
|
||||
@@ -1573,9 +1581,9 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
|
||||
}
|
||||
|
||||
if (!D3D_LoadDLL(&data->d3dDLL, &data->d3d)) {
|
||||
SDL_SetError("Unable to create Direct3D interface");
|
||||
SDL_free(renderer);
|
||||
SDL_free(data);
|
||||
SDL_SetError("Unable to create Direct3D interface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,14 @@
|
||||
#include "../SDL_d3dmath.h"
|
||||
|
||||
#include <d3d11_1.h>
|
||||
#include <dxgi1_4.h>
|
||||
|
||||
#include "SDL_shaders_d3d11.h"
|
||||
|
||||
#ifdef SDL_PLATFORM_WINRT
|
||||
|
||||
#if NTDDI_VERSION > NTDDI_WIN8
|
||||
#include <DXGI1_3.h>
|
||||
#include <dxgi1_3.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_render_winrt.h"
|
||||
@@ -189,6 +190,7 @@ static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a
|
||||
static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } };
|
||||
static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } };
|
||||
/*static const GUID SDL_IID_ID3D11Debug = { 0x79cf2233, 0x7536, 0x4948, { 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60 } };*/
|
||||
static const GUID SDL_IID_IDXGISwapChain2 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } };
|
||||
|
||||
#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
|
||||
#pragma GCC diagnostic pop
|
||||
@@ -203,6 +205,10 @@ Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat)
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
return SDL_PIXELFORMAT_XRGB8888;
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
return SDL_PIXELFORMAT_XBGR2101010;
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
return SDL_PIXELFORMAT_RGBA64_FLOAT;
|
||||
default:
|
||||
return SDL_PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
@@ -271,21 +277,12 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer)
|
||||
if (data) {
|
||||
int i;
|
||||
|
||||
SAFE_RELEASE(data->dxgiFactory);
|
||||
SAFE_RELEASE(data->dxgiAdapter);
|
||||
SAFE_RELEASE(data->d3dDevice);
|
||||
SAFE_RELEASE(data->d3dContext);
|
||||
SAFE_RELEASE(data->swapChain);
|
||||
SAFE_RELEASE(data->mainRenderTargetView);
|
||||
SAFE_RELEASE(data->currentOffscreenRenderTargetView);
|
||||
SAFE_RELEASE(data->inputLayout);
|
||||
for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) {
|
||||
SAFE_RELEASE(data->vertexBuffers[i]);
|
||||
}
|
||||
SAFE_RELEASE(data->vertexShader);
|
||||
for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
|
||||
SAFE_RELEASE(data->pixelShaders[i]);
|
||||
}
|
||||
SAFE_RELEASE(data->vertexShaderConstants);
|
||||
SAFE_RELEASE(data->clippedRasterizer);
|
||||
SAFE_RELEASE(data->mainRasterizer);
|
||||
SAFE_RELEASE(data->linearSampler);
|
||||
SAFE_RELEASE(data->nearestPixelSampler);
|
||||
|
||||
if (data->blendModesCount > 0) {
|
||||
for (i = 0; i < data->blendModesCount; ++i) {
|
||||
SAFE_RELEASE(data->blendModes[i].blendState);
|
||||
@@ -294,11 +291,26 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer)
|
||||
|
||||
data->blendModesCount = 0;
|
||||
}
|
||||
SAFE_RELEASE(data->nearestPixelSampler);
|
||||
SAFE_RELEASE(data->linearSampler);
|
||||
SAFE_RELEASE(data->mainRasterizer);
|
||||
SAFE_RELEASE(data->clippedRasterizer);
|
||||
SAFE_RELEASE(data->vertexShaderConstants);
|
||||
for (i = 0; i < SDL_arraysize(data->pixelShaders); ++i) {
|
||||
SAFE_RELEASE(data->pixelShaders[i]);
|
||||
}
|
||||
SAFE_RELEASE(data->vertexShader);
|
||||
for (i = 0; i < SDL_arraysize(data->vertexBuffers); ++i) {
|
||||
SAFE_RELEASE(data->vertexBuffers[i]);
|
||||
}
|
||||
SAFE_RELEASE(data->inputLayout);
|
||||
SAFE_RELEASE(data->currentOffscreenRenderTargetView);
|
||||
SAFE_RELEASE(data->mainRenderTargetView);
|
||||
SAFE_RELEASE(data->swapChain);
|
||||
|
||||
/* Make sure the swap chain is fully released */
|
||||
ID3D11DeviceContext_ClearState(data->d3dContext);
|
||||
ID3D11DeviceContext_Flush(data->d3dContext);
|
||||
|
||||
SAFE_RELEASE(data->d3dContext);
|
||||
SAFE_RELEASE(data->d3dDevice);
|
||||
SAFE_RELEASE(data->dxgiAdapter);
|
||||
SAFE_RELEASE(data->dxgiFactory);
|
||||
|
||||
data->swapEffect = (DXGI_SWAP_EFFECT)0;
|
||||
data->rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
|
||||
@@ -779,7 +791,17 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
SDL_zero(swapChainDesc);
|
||||
swapChainDesc.Width = w;
|
||||
swapChainDesc.Height = h;
|
||||
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the most common swap chain format. */
|
||||
switch (renderer->output_colorspace) {
|
||||
case SDL_COLORSPACE_SCRGB:
|
||||
swapChainDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
case SDL_COLORSPACE_HDR10:
|
||||
swapChainDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
break;
|
||||
default:
|
||||
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the most common swap chain format. */
|
||||
break;
|
||||
}
|
||||
swapChainDesc.Stereo = FALSE;
|
||||
swapChainDesc.SampleDesc.Count = 1; /* Don't use multi-sampling. */
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
@@ -865,6 +887,28 @@ static HRESULT D3D11_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
}
|
||||
data->swapEffect = swapChainDesc.SwapEffect;
|
||||
|
||||
IDXGISwapChain3 *swapChain3 = NULL;
|
||||
if (SUCCEEDED(IDXGISwapChain1_QueryInterface(data->swapChain, &SDL_IID_IDXGISwapChain2, (void **)&swapChain3))) {
|
||||
DXGI_COLOR_SPACE_TYPE ColorSpace;
|
||||
switch (renderer->output_colorspace) {
|
||||
case SDL_COLORSPACE_SCRGB:
|
||||
ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
|
||||
break;
|
||||
case SDL_COLORSPACE_HDR10:
|
||||
ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||
break;
|
||||
default:
|
||||
/* sRGB */
|
||||
ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
||||
break;
|
||||
}
|
||||
result = IDXGISwapChain3_SetColorSpace1(swapChain3, ColorSpace);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain3::SetColorSpace1"), result);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
SAFE_RELEASE(coreWindow);
|
||||
return result;
|
||||
@@ -1004,10 +1048,20 @@ static HRESULT D3D11_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
|
||||
/* Create a render target view of the swap chain back buffer. */
|
||||
D3D11_RENDER_TARGET_VIEW_DESC desc;
|
||||
SDL_zero(desc);
|
||||
if (renderer->colorspace_conversion && renderer->output_colorspace == SDL_COLORSPACE_SRGB) {
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
} else {
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
switch (renderer->output_colorspace) {
|
||||
case SDL_COLORSPACE_SCRGB:
|
||||
desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
case SDL_COLORSPACE_HDR10:
|
||||
desc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
break;
|
||||
default:
|
||||
if (renderer->colorspace_conversion && renderer->output_colorspace == SDL_COLORSPACE_SRGB) {
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
} else {
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
result = ID3D11Device_CreateRenderTargetView(data->d3dDevice,
|
||||
@@ -2354,12 +2408,14 @@ static int D3D11_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
|
||||
/* Copy the data into the desired buffer, converting pixels to the
|
||||
* desired format at the same time:
|
||||
*/
|
||||
status = SDL_ConvertPixels(
|
||||
status = SDL_ConvertPixelsAndColorspace(
|
||||
rect->w, rect->h,
|
||||
D3D11_DXGIFormatToSDLPixelFormat(stagingTextureDesc.Format),
|
||||
renderer->target ? renderer->target->colorspace : renderer->output_colorspace,
|
||||
textureMemory.pData,
|
||||
textureMemory.RowPitch,
|
||||
format,
|
||||
renderer->input_colorspace,
|
||||
pixels,
|
||||
pitch);
|
||||
|
||||
@@ -2457,14 +2513,22 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
|
||||
renderer->output_colorspace != SDL_COLORSPACE_SCRGB &&
|
||||
renderer->output_colorspace != SDL_COLORSPACE_HDR10) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (D3D11_RenderData *)SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
data->identity = MatrixIdentity();
|
||||
|
||||
renderer->WindowEvent = D3D11_WindowEvent;
|
||||
|
||||
@@ -174,6 +174,7 @@ typedef struct
|
||||
ID3D12GraphicsCommandList2 *commandList;
|
||||
DXGI_SWAP_EFFECT swapEffect;
|
||||
UINT swapFlags;
|
||||
DXGI_FORMAT renderTargetFormat;
|
||||
SDL_bool pixelSizeChanged;
|
||||
|
||||
/* Descriptor heaps */
|
||||
@@ -278,6 +279,10 @@ Uint32 D3D12_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat)
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
return SDL_PIXELFORMAT_XRGB8888;
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
return SDL_PIXELFORMAT_XBGR2101010;
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
return SDL_PIXELFORMAT_RGBA64_FLOAT;
|
||||
default:
|
||||
return SDL_PIXELFORMAT_UNKNOWN;
|
||||
}
|
||||
@@ -751,6 +756,8 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer)
|
||||
SDL_BLENDMODE_MUL
|
||||
};
|
||||
const DXGI_FORMAT defaultRTVFormats[] = {
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_FORMAT_B8G8R8X8_UNORM,
|
||||
DXGI_FORMAT_R8_UNORM
|
||||
@@ -1178,7 +1185,24 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
SDL_zero(swapChainDesc);
|
||||
swapChainDesc.Width = w;
|
||||
swapChainDesc.Height = h;
|
||||
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the most common swap chain format. */
|
||||
switch (renderer->output_colorspace) {
|
||||
case SDL_COLORSPACE_SCRGB:
|
||||
swapChainDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
data->renderTargetFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
case SDL_COLORSPACE_HDR10:
|
||||
swapChainDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
data->renderTargetFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
break;
|
||||
default:
|
||||
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; /* This is the most common swap chain format. */
|
||||
if (renderer->colorspace_conversion && renderer->output_colorspace == SDL_COLORSPACE_SRGB) {
|
||||
data->renderTargetFormat = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
} else {
|
||||
data->renderTargetFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
swapChainDesc.Stereo = FALSE;
|
||||
swapChainDesc.SampleDesc.Count = 1; /* Don't use multi-sampling. */
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
@@ -1227,6 +1251,25 @@ static HRESULT D3D12_CreateSwapChain(SDL_Renderer *renderer, int w, int h)
|
||||
data->swapEffect = swapChainDesc.SwapEffect;
|
||||
data->swapFlags = swapChainDesc.Flags;
|
||||
|
||||
DXGI_COLOR_SPACE_TYPE ColorSpace;
|
||||
switch (renderer->output_colorspace) {
|
||||
case SDL_COLORSPACE_SCRGB:
|
||||
ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
|
||||
break;
|
||||
case SDL_COLORSPACE_HDR10:
|
||||
ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||
break;
|
||||
default:
|
||||
/* sRGB */
|
||||
ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
||||
break;
|
||||
}
|
||||
result = D3D_CALL(data->swapChain, SetColorSpace1, ColorSpace);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain3::SetColorSpace1"), result);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
SAFE_RELEASE(swapChain);
|
||||
return result;
|
||||
@@ -1354,11 +1397,7 @@ static HRESULT D3D12_CreateWindowSizeDependentResources(SDL_Renderer *renderer)
|
||||
#endif
|
||||
|
||||
SDL_zero(rtvDesc);
|
||||
if (renderer->colorspace_conversion && renderer->output_colorspace == SDL_COLORSPACE_SRGB) {
|
||||
rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
|
||||
} else {
|
||||
rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
rtvDesc.Format = data->renderTargetFormat;
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
|
||||
SDL_zero(rtvDescriptor);
|
||||
@@ -2379,7 +2418,7 @@ static int D3D12_SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *c
|
||||
SDL_bool updateSubresource = SDL_FALSE;
|
||||
int i;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE firstShaderResource;
|
||||
DXGI_FORMAT rtvFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
DXGI_FORMAT rtvFormat = rendererData->renderTargetFormat;
|
||||
|
||||
if (rendererData->textureRenderTarget) {
|
||||
rtvFormat = rendererData->textureRenderTarget->mainTextureFormat;
|
||||
@@ -2877,12 +2916,14 @@ static int D3D12_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
|
||||
/* Copy the data into the desired buffer, converting pixels to the
|
||||
* desired format at the same time:
|
||||
*/
|
||||
status = SDL_ConvertPixels(
|
||||
status = SDL_ConvertPixelsAndColorspace(
|
||||
rect->w, rect->h,
|
||||
D3D12_DXGIFormatToSDLPixelFormat(textureDesc.Format),
|
||||
renderer->target ? renderer->target->colorspace : renderer->output_colorspace,
|
||||
textureMemory,
|
||||
pitchedDesc.RowPitch,
|
||||
format,
|
||||
renderer->input_colorspace,
|
||||
pixels,
|
||||
pitch);
|
||||
|
||||
@@ -2997,14 +3038,22 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB &&
|
||||
renderer->output_colorspace != SDL_COLORSPACE_SCRGB &&
|
||||
renderer->output_colorspace != SDL_COLORSPACE_HDR10) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (D3D12_RenderData *)SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
data->identity = MatrixIdentity();
|
||||
|
||||
renderer->WindowEvent = D3D12_WindowEvent;
|
||||
|
||||
@@ -1737,6 +1737,15 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
|
||||
if (!renderer) {
|
||||
return NULL;
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SDL_PLATFORM_MACOS
|
||||
if (SDL_GetHintBoolean(SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE, SDL_TRUE)) {
|
||||
|
||||
@@ -1710,14 +1710,20 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
|
||||
goto error;
|
||||
}
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
goto error;
|
||||
}
|
||||
|
||||
data = (GL_RenderData *)SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
SDL_free(renderer);
|
||||
goto error;
|
||||
}
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
renderer->WindowEvent = GL_WindowEvent;
|
||||
renderer->SupportsBlendMode = GL_SupportsBlendMode;
|
||||
renderer->CreateTexture = GL_CreateTexture;
|
||||
@@ -1939,10 +1945,13 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
|
||||
error:
|
||||
if (changed_window) {
|
||||
/* Uh oh, better try to put it back... */
|
||||
char *error = SDL_strdup(SDL_GetError());
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
|
||||
SDL_RecreateWindow(window, window_flags);
|
||||
SDL_SetError("%s", error);
|
||||
SDL_free(error);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -886,7 +886,7 @@ static int GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
|
||||
verts->position.y = xy_[1] * scale_y;
|
||||
|
||||
if (colorswap) {
|
||||
Uint8 r = col_.r;
|
||||
float r = col_.r;
|
||||
col_.r = col_.b;
|
||||
col_.b = r;
|
||||
}
|
||||
@@ -2049,6 +2049,15 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
|
||||
if (!renderer) {
|
||||
goto error;
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
goto error;
|
||||
}
|
||||
|
||||
data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData));
|
||||
if (!data) {
|
||||
@@ -2207,10 +2216,13 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
|
||||
error:
|
||||
if (changed_window) {
|
||||
/* Uh oh, better try to put it back... */
|
||||
char *error = SDL_strdup(SDL_GetError());
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
|
||||
SDL_RecreateWindow(window, window_flags);
|
||||
SDL_SetError("%s", error);
|
||||
SDL_free(error);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -630,6 +630,15 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID cre
|
||||
if (!renderer) {
|
||||
return NULL;
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (PS2_RenderData *)SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
|
||||
@@ -1312,6 +1312,15 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
|
||||
if (!renderer) {
|
||||
return NULL;
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (PSP_RenderData *)SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
|
||||
@@ -1124,6 +1124,7 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface)
|
||||
if (!renderer) {
|
||||
return NULL;
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
data = (SW_RenderData *)SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
|
||||
@@ -220,6 +220,15 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID creat
|
||||
if (!renderer) {
|
||||
return NULL;
|
||||
}
|
||||
renderer->magic = &SDL_renderer_magic;
|
||||
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
|
||||
SDL_SetError("Unsupported output colorspace");
|
||||
SDL_free(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = (VITA_GXM_RenderData *)SDL_calloc(1, sizeof(VITA_GXM_RenderData));
|
||||
if (!data) {
|
||||
|
||||
@@ -183,23 +183,21 @@ static SDL_BlitFunc SDL_ChooseBlitFunc(Uint32 src_format, Uint32 dst_format, int
|
||||
}
|
||||
#endif /* SDL_HAVE_BLIT_AUTO */
|
||||
|
||||
static SDL_Colorspace GetSurfaceColorspace(SDL_Surface *surface)
|
||||
{
|
||||
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
|
||||
SDL_PropertiesID props = SDL_GetSurfaceProperties(surface);
|
||||
return (SDL_Colorspace)SDL_GetNumberProperty(props, SDL_PROP_SURFACE_COLORSPACE_NUMBER, SDL_COLORSPACE_RGB_DEFAULT);
|
||||
}
|
||||
return SDL_COLORSPACE_RGB_DEFAULT;
|
||||
}
|
||||
|
||||
/* Figure out which of many blit routines to set up on a surface */
|
||||
int SDL_CalculateBlit(SDL_Surface *surface)
|
||||
{
|
||||
SDL_BlitFunc blit = NULL;
|
||||
SDL_BlitMap *map = surface->map;
|
||||
SDL_Surface *dst = map->dst;
|
||||
SDL_Colorspace src_colorspace = GetSurfaceColorspace(surface);
|
||||
SDL_Colorspace dst_colorspace = GetSurfaceColorspace(dst);
|
||||
SDL_Colorspace src_colorspace = SDL_COLORSPACE_UNKNOWN;
|
||||
SDL_Colorspace dst_colorspace = SDL_COLORSPACE_UNKNOWN;
|
||||
|
||||
if (SDL_GetSurfaceColorspace(surface, &src_colorspace) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (SDL_GetSurfaceColorspace(dst, &dst_colorspace) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We don't currently support blitting to < 8 bpp surfaces */
|
||||
if (dst->format->BitsPerPixel < 8) {
|
||||
|
||||
@@ -262,13 +262,16 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
|
||||
a = (a * 3) / 255; \
|
||||
Pixel = (a << 30) | (r << 20) | (g << 10) | b; \
|
||||
}
|
||||
#define ARGB2101010_FROM_RGBAFLOAT(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = SDL_clamp(r, 0.0f, 1.0f) * 1023.0f; \
|
||||
g = SDL_clamp(g, 0.0f, 1.0f) * 1023.0f; \
|
||||
b = SDL_clamp(b, 0.0f, 1.0f) * 1023.0f; \
|
||||
a = SDL_clamp(a, 0.0f, 1.0f) * 3.0f; \
|
||||
Pixel = (((Uint32)a) << 30) | (((Uint32)r) << 20) | (((Uint32)g) << 10) | (Uint32)b; \
|
||||
#define ARGB2101010_FROM_RGBAFLOAT(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = SDL_clamp(r, 0.0f, 1.0f) * 1023.0f; \
|
||||
g = SDL_clamp(g, 0.0f, 1.0f) * 1023.0f; \
|
||||
b = SDL_clamp(b, 0.0f, 1.0f) * 1023.0f; \
|
||||
a = SDL_clamp(a, 0.0f, 1.0f) * 3.0f; \
|
||||
Pixel = (((Uint32)SDL_roundf(a)) << 30) | \
|
||||
(((Uint32)SDL_roundf(r)) << 20) | \
|
||||
(((Uint32)SDL_roundf(g)) << 10) | \
|
||||
(Uint32)SDL_roundf(b); \
|
||||
}
|
||||
#define ABGR2101010_FROM_RGBA(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
@@ -278,13 +281,16 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface);
|
||||
a = (a * 3) / 255; \
|
||||
Pixel = (a << 30) | (b << 20) | (g << 10) | r; \
|
||||
}
|
||||
#define ABGR2101010_FROM_RGBAFLOAT(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = SDL_clamp(r, 0.0f, 1.0f) * 1023.0f; \
|
||||
g = SDL_clamp(g, 0.0f, 1.0f) * 1023.0f; \
|
||||
b = SDL_clamp(b, 0.0f, 1.0f) * 1023.0f; \
|
||||
a = SDL_clamp(a, 0.0f, 1.0f) * 3.0f; \
|
||||
Pixel = (((Uint32)a) << 30) | (((Uint32)b) << 20) | (((Uint32)g) << 10) | (Uint32)r; \
|
||||
#define ABGR2101010_FROM_RGBAFLOAT(Pixel, r, g, b, a) \
|
||||
{ \
|
||||
r = SDL_clamp(r, 0.0f, 1.0f) * 1023.0f; \
|
||||
g = SDL_clamp(g, 0.0f, 1.0f) * 1023.0f; \
|
||||
b = SDL_clamp(b, 0.0f, 1.0f) * 1023.0f; \
|
||||
a = SDL_clamp(a, 0.0f, 1.0f) * 3.0f; \
|
||||
Pixel = (((Uint32)SDL_roundf(a)) << 30) | \
|
||||
(((Uint32)SDL_roundf(b)) << 20) | \
|
||||
(((Uint32)SDL_roundf(g)) << 10) | \
|
||||
(Uint32)SDL_roundf(r); \
|
||||
}
|
||||
#define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \
|
||||
{ \
|
||||
|
||||
@@ -366,65 +366,6 @@ static Uint16 float_to_half(float a)
|
||||
return ir;
|
||||
}
|
||||
|
||||
static float scRGBtoNits(float v)
|
||||
{
|
||||
return v * 80.0f;
|
||||
}
|
||||
|
||||
static float scRGBfromNits(float v)
|
||||
{
|
||||
return v / 80.0f;
|
||||
}
|
||||
|
||||
static float sRGBtoNits(float v)
|
||||
{
|
||||
if (v <= 0.04045f) {
|
||||
v = (v / 12.92f);
|
||||
} else {
|
||||
v = SDL_powf((v + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
return scRGBtoNits(v);
|
||||
}
|
||||
|
||||
static float sRGBfromNits(float v)
|
||||
{
|
||||
v = scRGBfromNits(v);
|
||||
|
||||
if (v <= 0.0031308f) {
|
||||
v = (v * 12.92f);
|
||||
} else {
|
||||
v = (SDL_powf(v, 1.0f / 2.4f) * 1.055f - 0.055f);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static float PQtoNits(float v)
|
||||
{
|
||||
const float c1 = 0.8359375f;
|
||||
const float c2 = 18.8515625f;
|
||||
const float c3 = 18.6875f;
|
||||
const float oo_m1 = 1.0f / 0.1593017578125f;
|
||||
const float oo_m2 = 1.0f / 78.84375f;
|
||||
|
||||
float num = SDL_max(SDL_powf(v, oo_m2) - c1, 0.0f);
|
||||
float den = c2 - c3 * SDL_powf(v, oo_m2);
|
||||
return 10000.0f * SDL_powf(num / den, oo_m1);
|
||||
}
|
||||
|
||||
static float PQfromNits(float v)
|
||||
{
|
||||
const float c1 = 0.8359375f;
|
||||
const float c2 = 18.8515625f;
|
||||
const float c3 = 18.6875f;
|
||||
const float m1 = 0.1593017578125f;
|
||||
const float m2 = 78.84375f;
|
||||
|
||||
float y = SDL_clamp(v / 10000.0f, 0.0f, 1.0f);
|
||||
float num = c1 + c2 * pow(y, m1);
|
||||
float den = 1.0f + c3 * pow(y, m1);
|
||||
return pow(num / den, m2);
|
||||
}
|
||||
|
||||
static void ReadFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_PixelFormat *fmt, SDL_Colorspace colorspace,
|
||||
float *outR, float *outG, float *outB, float *outA)
|
||||
{
|
||||
@@ -555,20 +496,20 @@ static void ReadFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_PixelF
|
||||
/* Convert to nits so src and dst are guaranteed to be linear and in the same units */
|
||||
switch (SDL_COLORSPACETRANSFER(colorspace)) {
|
||||
case SDL_TRANSFER_CHARACTERISTICS_SRGB:
|
||||
fR = sRGBtoNits(fR);
|
||||
fG = sRGBtoNits(fG);
|
||||
fB = sRGBtoNits(fB);
|
||||
fR = SDL_sRGBtoNits(fR);
|
||||
fG = SDL_sRGBtoNits(fG);
|
||||
fB = SDL_sRGBtoNits(fB);
|
||||
break;
|
||||
case SDL_TRANSFER_CHARACTERISTICS_PQ:
|
||||
fR = PQtoNits(fR);
|
||||
fG = PQtoNits(fG);
|
||||
fB = PQtoNits(fB);
|
||||
fR = SDL_PQtoNits(fR);
|
||||
fG = SDL_PQtoNits(fG);
|
||||
fB = SDL_PQtoNits(fB);
|
||||
break;
|
||||
case SDL_TRANSFER_CHARACTERISTICS_LINEAR:
|
||||
/* Assuming scRGB for now */
|
||||
fR = scRGBtoNits(fR);
|
||||
fG = scRGBtoNits(fG);
|
||||
fB = scRGBtoNits(fB);
|
||||
fR = SDL_scRGBtoNits(fR);
|
||||
fG = SDL_scRGBtoNits(fG);
|
||||
fB = SDL_scRGBtoNits(fB);
|
||||
break;
|
||||
default:
|
||||
/* Unknown, leave it alone */
|
||||
@@ -590,20 +531,20 @@ static void WriteFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_Pixel
|
||||
/* We converted to nits so src and dst are guaranteed to be linear and in the same units */
|
||||
switch (SDL_COLORSPACETRANSFER(colorspace)) {
|
||||
case SDL_TRANSFER_CHARACTERISTICS_SRGB:
|
||||
fR = sRGBfromNits(fR);
|
||||
fG = sRGBfromNits(fG);
|
||||
fB = sRGBfromNits(fB);
|
||||
fR = SDL_sRGBfromNits(fR);
|
||||
fG = SDL_sRGBfromNits(fG);
|
||||
fB = SDL_sRGBfromNits(fB);
|
||||
break;
|
||||
case SDL_TRANSFER_CHARACTERISTICS_PQ:
|
||||
fR = PQfromNits(fR);
|
||||
fG = PQfromNits(fG);
|
||||
fB = PQfromNits(fB);
|
||||
fR = SDL_PQfromNits(fR);
|
||||
fG = SDL_PQfromNits(fG);
|
||||
fB = SDL_PQfromNits(fB);
|
||||
break;
|
||||
case SDL_TRANSFER_CHARACTERISTICS_LINEAR:
|
||||
/* Assuming scRGB for now */
|
||||
fR = scRGBfromNits(fR);
|
||||
fG = scRGBfromNits(fG);
|
||||
fB = scRGBfromNits(fB);
|
||||
fR = SDL_scRGBfromNits(fR);
|
||||
fG = SDL_scRGBfromNits(fG);
|
||||
fB = SDL_scRGBfromNits(fB);
|
||||
break;
|
||||
default:
|
||||
/* Unknown, leave it alone */
|
||||
@@ -612,16 +553,16 @@ static void WriteFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_Pixel
|
||||
|
||||
switch (access) {
|
||||
case SlowBlitPixelAccess_RGB:
|
||||
R = (Uint8)(SDL_clamp(fR, 0.0f, 1.0f) * 255.0f);
|
||||
G = (Uint8)(SDL_clamp(fG, 0.0f, 1.0f) * 255.0f);
|
||||
B = (Uint8)(SDL_clamp(fB, 0.0f, 1.0f) * 255.0f);
|
||||
R = (Uint8)SDL_roundf(SDL_clamp(fR, 0.0f, 1.0f) * 255.0f);
|
||||
G = (Uint8)SDL_roundf(SDL_clamp(fG, 0.0f, 1.0f) * 255.0f);
|
||||
B = (Uint8)SDL_roundf(SDL_clamp(fB, 0.0f, 1.0f) * 255.0f);
|
||||
ASSEMBLE_RGB(pixels, fmt->BytesPerPixel, fmt, R, G, B);
|
||||
break;
|
||||
case SlowBlitPixelAccess_RGBA:
|
||||
R = (Uint8)(SDL_clamp(fR, 0.0f, 1.0f) * 255.0f);
|
||||
G = (Uint8)(SDL_clamp(fG, 0.0f, 1.0f) * 255.0f);
|
||||
B = (Uint8)(SDL_clamp(fB, 0.0f, 1.0f) * 255.0f);
|
||||
A = (Uint8)(SDL_clamp(fA, 0.0f, 1.0f) * 255.0f);
|
||||
R = (Uint8)SDL_roundf(SDL_clamp(fR, 0.0f, 1.0f) * 255.0f);
|
||||
G = (Uint8)SDL_roundf(SDL_clamp(fG, 0.0f, 1.0f) * 255.0f);
|
||||
B = (Uint8)SDL_roundf(SDL_clamp(fB, 0.0f, 1.0f) * 255.0f);
|
||||
A = (Uint8)SDL_roundf(SDL_clamp(fA, 0.0f, 1.0f) * 255.0f);
|
||||
ASSEMBLE_RGBA(pixels, fmt->BytesPerPixel, fmt, R, G, B, A);
|
||||
break;
|
||||
case SlowBlitPixelAccess_10Bit:
|
||||
@@ -692,11 +633,11 @@ static void WriteFloatPixel(Uint8 *pixels, SlowBlitPixelAccess access, SDL_Pixel
|
||||
}
|
||||
switch (SDL_PIXELTYPE(fmt->format)) {
|
||||
case SDL_PIXELTYPE_ARRAYU16:
|
||||
((Uint16 *)pixels)[0] = (Uint16)(SDL_clamp(v[0], 0.0f, 1.0f) * SDL_MAX_UINT16);
|
||||
((Uint16 *)pixels)[1] = (Uint16)(SDL_clamp(v[1], 0.0f, 1.0f) * SDL_MAX_UINT16);
|
||||
((Uint16 *)pixels)[2] = (Uint16)(SDL_clamp(v[2], 0.0f, 1.0f) * SDL_MAX_UINT16);
|
||||
((Uint16 *)pixels)[0] = (Uint16)SDL_roundf(SDL_clamp(v[0], 0.0f, 1.0f) * SDL_MAX_UINT16);
|
||||
((Uint16 *)pixels)[1] = (Uint16)SDL_roundf(SDL_clamp(v[1], 0.0f, 1.0f) * SDL_MAX_UINT16);
|
||||
((Uint16 *)pixels)[2] = (Uint16)SDL_roundf(SDL_clamp(v[2], 0.0f, 1.0f) * SDL_MAX_UINT16);
|
||||
if (fmt->BytesPerPixel == 8) {
|
||||
((Uint16 *)pixels)[3] = (Uint16)(SDL_clamp(v[3], 0.0f, 1.0f) * SDL_MAX_UINT16);
|
||||
((Uint16 *)pixels)[3] = (Uint16)SDL_roundf(SDL_clamp(v[3], 0.0f, 1.0f) * SDL_MAX_UINT16);
|
||||
}
|
||||
break;
|
||||
case SDL_PIXELTYPE_ARRAYF16:
|
||||
@@ -765,17 +706,26 @@ void SDL_Blit_Slow_Float(SDL_BlitInfo *info)
|
||||
int dstbpp = dst_fmt->BytesPerPixel;
|
||||
SlowBlitPixelAccess src_access;
|
||||
SlowBlitPixelAccess dst_access;
|
||||
SDL_PropertiesID src_props = SDL_GetSurfaceProperties(info->src_surface);
|
||||
SDL_Colorspace src_colorspace = (SDL_Colorspace)SDL_GetNumberProperty(src_props, SDL_PROP_SURFACE_COLORSPACE_NUMBER, SDL_COLORSPACE_RGB_DEFAULT);
|
||||
SDL_ColorPrimaries src_primaries = SDL_COLORSPACEPRIMARIES(src_colorspace);
|
||||
SDL_TransferCharacteristics src_transfer = SDL_COLORSPACETRANSFER(src_colorspace);
|
||||
SDL_PropertiesID dst_props = SDL_GetSurfaceProperties(info->dst_surface);
|
||||
SDL_Colorspace dst_colorspace = (SDL_Colorspace)SDL_GetNumberProperty(dst_props, SDL_PROP_SURFACE_COLORSPACE_NUMBER, SDL_COLORSPACE_RGB_DEFAULT);
|
||||
SDL_ColorPrimaries dst_primaries = SDL_COLORSPACEPRIMARIES(dst_colorspace);
|
||||
SDL_TransferCharacteristics dst_transfer = SDL_COLORSPACETRANSFER(dst_colorspace);
|
||||
const float *color_primaries_matrix = SDL_GetColorPrimariesConversionMatrix(src_primaries, dst_primaries);
|
||||
SDL_Colorspace src_colorspace;
|
||||
SDL_ColorPrimaries src_primaries;
|
||||
SDL_TransferCharacteristics src_transfer;
|
||||
SDL_Colorspace dst_colorspace;
|
||||
SDL_ColorPrimaries dst_primaries;
|
||||
SDL_TransferCharacteristics dst_transfer;
|
||||
const float *color_primaries_matrix;
|
||||
SDL_bool compress_PQ = SDL_FALSE;
|
||||
|
||||
if (SDL_GetSurfaceColorspace(info->src_surface, &src_colorspace) < 0 ||
|
||||
SDL_GetSurfaceColorspace(info->dst_surface, &dst_colorspace) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
src_primaries = SDL_COLORSPACEPRIMARIES(src_colorspace);
|
||||
src_transfer = SDL_COLORSPACETRANSFER(src_colorspace);
|
||||
dst_primaries = SDL_COLORSPACEPRIMARIES(dst_colorspace);
|
||||
dst_transfer = SDL_COLORSPACETRANSFER(dst_colorspace);
|
||||
color_primaries_matrix = SDL_GetColorPrimariesConversionMatrix(src_primaries, dst_primaries);
|
||||
|
||||
if (src_transfer == SDL_TRANSFER_CHARACTERISTICS_PQ &&
|
||||
dst_transfer != SDL_TRANSFER_CHARACTERISTICS_PQ &&
|
||||
dst_colorspace != SDL_COLORSPACE_SCRGB) {
|
||||
|
||||
@@ -692,6 +692,78 @@ void SDL_DestroyPixelFormat(SDL_PixelFormat *format)
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Colorspace SDL_GetDefaultColorspaceForFormat(Uint32 format)
|
||||
{
|
||||
if (SDL_ISPIXELFORMAT_FOURCC(format)) {
|
||||
return SDL_COLORSPACE_BT709_FULL;
|
||||
} else if (SDL_ISPIXELFORMAT_FLOAT(format)) {
|
||||
return SDL_COLORSPACE_SCRGB;
|
||||
} else if (SDL_ISPIXELFORMAT_10BIT(format)) {
|
||||
return SDL_COLORSPACE_HDR10;
|
||||
} else {
|
||||
return SDL_COLORSPACE_RGB_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
float SDL_scRGBtoNits(float v)
|
||||
{
|
||||
return v * 80.0f;
|
||||
}
|
||||
|
||||
float SDL_scRGBfromNits(float v)
|
||||
{
|
||||
return v / 80.0f;
|
||||
}
|
||||
|
||||
float SDL_sRGBtoNits(float v)
|
||||
{
|
||||
if (v <= 0.04045f) {
|
||||
v = (v / 12.92f);
|
||||
} else {
|
||||
v = SDL_powf((v + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
return SDL_scRGBtoNits(v);
|
||||
}
|
||||
|
||||
float SDL_sRGBfromNits(float v)
|
||||
{
|
||||
v = SDL_scRGBfromNits(v);
|
||||
|
||||
if (v <= 0.0031308f) {
|
||||
v = (v * 12.92f);
|
||||
} else {
|
||||
v = (SDL_powf(v, 1.0f / 2.4f) * 1.055f - 0.055f);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
float SDL_PQtoNits(float v)
|
||||
{
|
||||
const float c1 = 0.8359375f;
|
||||
const float c2 = 18.8515625f;
|
||||
const float c3 = 18.6875f;
|
||||
const float oo_m1 = 1.0f / 0.1593017578125f;
|
||||
const float oo_m2 = 1.0f / 78.84375f;
|
||||
|
||||
float num = SDL_max(SDL_powf(v, oo_m2) - c1, 0.0f);
|
||||
float den = c2 - c3 * SDL_powf(v, oo_m2);
|
||||
return 10000.0f * SDL_powf(num / den, oo_m1);
|
||||
}
|
||||
|
||||
float SDL_PQfromNits(float v)
|
||||
{
|
||||
const float c1 = 0.8359375f;
|
||||
const float c2 = 18.8515625f;
|
||||
const float c3 = 18.6875f;
|
||||
const float m1 = 0.1593017578125f;
|
||||
const float m2 = 78.84375f;
|
||||
|
||||
float y = SDL_clamp(v / 10000.0f, 0.0f, 1.0f);
|
||||
float num = c1 + c2 * pow(y, m1);
|
||||
float den = 1.0f + c3 * pow(y, m1);
|
||||
return pow(num / den, m2);
|
||||
}
|
||||
|
||||
SDL_Palette *SDL_CreatePalette(int ncolors)
|
||||
{
|
||||
SDL_Palette *palette;
|
||||
|
||||
@@ -31,6 +31,16 @@
|
||||
/* Pixel format functions */
|
||||
extern int SDL_InitFormat(SDL_PixelFormat *format, Uint32 pixel_format);
|
||||
extern int SDL_CalculateSize(Uint32 format, int width, int height, size_t *size, size_t *pitch, SDL_bool minimalPitch);
|
||||
extern SDL_Colorspace SDL_GetDefaultColorspaceForFormat(Uint32 pixel_format);
|
||||
|
||||
/* Colorspace conversion functions */
|
||||
extern float SDL_scRGBtoNits(float v);
|
||||
extern float SDL_scRGBfromNits(float v);
|
||||
extern float SDL_sRGBtoNits(float v);
|
||||
extern float SDL_sRGBfromNits(float v);
|
||||
extern float SDL_PQtoNits(float v);
|
||||
extern float SDL_PQfromNits(float v);
|
||||
|
||||
|
||||
/* Blit mapping functions */
|
||||
extern SDL_BlitMap *SDL_AllocBlitMap(void);
|
||||
|
||||
@@ -269,6 +269,36 @@ SDL_PropertiesID SDL_GetSurfaceProperties(SDL_Surface *surface)
|
||||
return props;
|
||||
}
|
||||
|
||||
int SDL_SetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace colorspace)
|
||||
{
|
||||
if (!surface) {
|
||||
return SDL_InvalidParamError("surface");
|
||||
}
|
||||
|
||||
return SDL_SetNumberProperty(SDL_GetSurfaceProperties(surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, colorspace);
|
||||
}
|
||||
|
||||
int SDL_GetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace *colorspace)
|
||||
{
|
||||
SDL_Colorspace surface_colorspace = SDL_COLORSPACE_UNKNOWN;
|
||||
|
||||
if (!surface) {
|
||||
return SDL_InvalidParamError("surface");
|
||||
}
|
||||
|
||||
if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
|
||||
surface_colorspace = (SDL_Colorspace)SDL_GetNumberProperty(SDL_GetSurfaceProperties(surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, SDL_COLORSPACE_UNKNOWN);
|
||||
}
|
||||
if (surface_colorspace == SDL_COLORSPACE_UNKNOWN) {
|
||||
surface_colorspace = SDL_GetDefaultColorspaceForFormat(surface->format->format);
|
||||
}
|
||||
|
||||
if (colorspace) {
|
||||
*colorspace = surface_colorspace;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)
|
||||
{
|
||||
if (!surface) {
|
||||
@@ -1159,25 +1189,10 @@ int SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new surface identical to the existing surface
|
||||
*/
|
||||
SDL_Surface *SDL_DuplicateSurface(SDL_Surface *surface)
|
||||
{
|
||||
if (!surface) {
|
||||
SDL_InvalidParamError("surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return SDL_ConvertSurface(surface, surface->format);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a surface into the specified pixel format.
|
||||
*/
|
||||
SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *format)
|
||||
static SDL_Surface *SDL_ConvertSurfaceWithPixelFormatAndColorspace(SDL_Surface *surface, const SDL_PixelFormat *format, Uint32 colorspace)
|
||||
{
|
||||
SDL_Surface *convert;
|
||||
SDL_Colorspace src_colorspace;
|
||||
Uint32 copy_flags;
|
||||
SDL_Color copy_color;
|
||||
SDL_Rect bounds;
|
||||
@@ -1211,19 +1226,23 @@ SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *for
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_GetSurfaceColorspace(surface, &src_colorspace) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create a new surface with the desired format */
|
||||
convert = SDL_CreateSurface(surface->w, surface->h, format->format);
|
||||
if (!convert) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (colorspace == SDL_COLORSPACE_UNKNOWN) {
|
||||
colorspace = src_colorspace;
|
||||
}
|
||||
SDL_SetSurfaceColorspace(convert, colorspace);
|
||||
|
||||
if (SDL_ISPIXELFORMAT_FOURCC(format->format) || SDL_ISPIXELFORMAT_FOURCC(surface->format->format)) {
|
||||
|
||||
ret = SDL_ConvertPixels(surface->w, surface->h,
|
||||
surface->format->format, surface->pixels, surface->pitch,
|
||||
convert->format->format, convert->pixels, convert->pitch);
|
||||
|
||||
if (ret < 0) {
|
||||
if (SDL_ConvertPixelsAndColorspace(surface->w, surface->h, surface->format->format, src_colorspace, surface->pixels, surface->pitch, convert->format->format, colorspace, convert->pixels, convert->pitch) < 0) {
|
||||
SDL_DestroySurface(convert);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1430,15 +1449,35 @@ end:
|
||||
return convert;
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_DuplicateSurface(SDL_Surface *surface)
|
||||
{
|
||||
if (!surface) {
|
||||
SDL_InvalidParamError("surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, surface->format, SDL_COLORSPACE_UNKNOWN);
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *format)
|
||||
{
|
||||
return SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, format, SDL_COLORSPACE_UNKNOWN);
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_ConvertSurfaceFormat(SDL_Surface *surface, Uint32 pixel_format)
|
||||
{
|
||||
SDL_PixelFormat *fmt;
|
||||
return SDL_ConvertSurfaceFormatAndColorspace(surface, pixel_format, SDL_COLORSPACE_UNKNOWN);
|
||||
}
|
||||
|
||||
SDL_Surface *SDL_ConvertSurfaceFormatAndColorspace(SDL_Surface *surface, Uint32 pixel_format, SDL_Colorspace colorspace)
|
||||
{
|
||||
SDL_PixelFormat *format;
|
||||
SDL_Surface *convert = NULL;
|
||||
|
||||
fmt = SDL_CreatePixelFormat(pixel_format);
|
||||
if (fmt) {
|
||||
convert = SDL_ConvertSurface(surface, fmt);
|
||||
SDL_DestroyPixelFormat(fmt);
|
||||
format = SDL_CreatePixelFormat(pixel_format);
|
||||
if (format) {
|
||||
convert = SDL_ConvertSurfaceWithPixelFormatAndColorspace(surface, format, colorspace);
|
||||
SDL_DestroyPixelFormat(format);
|
||||
}
|
||||
return convert;
|
||||
}
|
||||
@@ -1481,12 +1520,9 @@ static SDL_INLINE SDL_bool SDL_CreateSurfaceOnStack(int width, int height, Uint3
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a block of pixels of one format to another format
|
||||
*/
|
||||
int SDL_ConvertPixels(int width, int height,
|
||||
Uint32 src_format, const void *src, int src_pitch,
|
||||
Uint32 dst_format, void *dst, int dst_pitch)
|
||||
int SDL_ConvertPixelsAndColorspace(int width, int height,
|
||||
Uint32 src_format, SDL_Colorspace src_colorspace, const void *src, int src_pitch,
|
||||
Uint32 dst_format, SDL_Colorspace dst_colorspace, void *dst, int dst_pitch)
|
||||
{
|
||||
SDL_Surface src_surface, dst_surface;
|
||||
SDL_PixelFormat src_fmt, dst_fmt;
|
||||
@@ -1523,7 +1559,7 @@ int SDL_ConvertPixels(int width, int height,
|
||||
#endif
|
||||
|
||||
/* Fast path for same format copy */
|
||||
if (src_format == dst_format) {
|
||||
if (src_format == dst_format && src_colorspace == dst_colorspace) {
|
||||
int i;
|
||||
const int bpp = SDL_BYTESPERPIXEL(src_format);
|
||||
width *= bpp;
|
||||
@@ -1540,10 +1576,17 @@ int SDL_ConvertPixels(int width, int height,
|
||||
&src_surface, &src_fmt, &src_blitmap)) {
|
||||
return -1;
|
||||
}
|
||||
if (src_colorspace != SDL_COLORSPACE_UNKNOWN) {
|
||||
SDL_SetNumberProperty(SDL_GetSurfaceProperties(&src_surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, src_colorspace);
|
||||
}
|
||||
|
||||
if (!SDL_CreateSurfaceOnStack(width, height, dst_format, dst, dst_pitch,
|
||||
&dst_surface, &dst_fmt, &dst_blitmap)) {
|
||||
return -1;
|
||||
}
|
||||
if (dst_colorspace != SDL_COLORSPACE_UNKNOWN) {
|
||||
SDL_SetNumberProperty(SDL_GetSurfaceProperties(&dst_surface), SDL_PROP_SURFACE_COLORSPACE_NUMBER, dst_colorspace);
|
||||
}
|
||||
|
||||
/* Set up the rect and go! */
|
||||
rect.x = 0;
|
||||
@@ -1555,9 +1598,24 @@ int SDL_ConvertPixels(int width, int height,
|
||||
/* Free blitmap reference, after blitting between stack'ed surfaces */
|
||||
SDL_InvalidateMap(src_surface.map);
|
||||
|
||||
if (src_colorspace != SDL_COLORSPACE_UNKNOWN) {
|
||||
SDL_DestroyProperties(SDL_GetSurfaceProperties(&src_surface));
|
||||
}
|
||||
if (dst_colorspace != SDL_COLORSPACE_UNKNOWN) {
|
||||
SDL_DestroyProperties(SDL_GetSurfaceProperties(&dst_surface));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SDL_ConvertPixels(int width, int height,
|
||||
Uint32 src_format, const void *src, int src_pitch,
|
||||
Uint32 dst_format, void *dst, int dst_pitch)
|
||||
{
|
||||
return SDL_ConvertPixelsAndColorspace(width, height,
|
||||
src_format, SDL_COLORSPACE_UNKNOWN, src, src_pitch,
|
||||
dst_format, SDL_COLORSPACE_UNKNOWN, dst, dst_pitch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Premultiply the alpha on a block of pixels
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user