Implemented scRGB colorspace and HDR support on macOS

main
Sam Lantinga 2024-02-06 05:31:43 -08:00
parent 451dc41427
commit ba074acad4
24 changed files with 10547 additions and 8010 deletions

View File

@ -295,6 +295,7 @@ static int FlushRenderCommands(SDL_Renderer *renderer)
renderer->vertex_data_used = 0;
renderer->render_command_generation++;
renderer->color_queued = SDL_FALSE;
renderer->color_scale_queued = SDL_FALSE;
renderer->viewport_queued = SDL_FALSE;
renderer->cliprect_queued = SDL_FALSE;
return retval;
@ -481,6 +482,31 @@ static int QueueCmdSetDrawColor(SDL_Renderer *renderer, SDL_FColor *color)
return retval;
}
static int QueueCmdSetColorScale(SDL_Renderer *renderer)
{
int retval = 0;
if (!renderer->color_scale_queued ||
renderer->color_scale != renderer->last_queued_color_scale) {
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
retval = -1;
if (cmd) {
cmd->command = SDL_RENDERCMD_SETCOLORSCALE;
cmd->data.color.first = 0; /* render backend will fill this in. */
cmd->data.color.color_scale = renderer->color_scale;
retval = renderer->QueueSetColorScale(renderer, cmd);
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
} else {
renderer->last_queued_color_scale = renderer->color_scale;
renderer->color_scale_queued = SDL_TRUE;
}
}
}
return retval;
}
static int QueueCmdClear(SDL_Renderer *renderer)
{
SDL_RenderCommand *cmd = AllocateRenderCommand(renderer);
@ -514,6 +540,10 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
retval = QueueCmdSetDrawColor(renderer, color);
}
if (retval == 0) {
retval = QueueCmdSetColorScale(renderer);
}
/* Set the viewport and clip rect directly before draws, so the backends
* don't have to worry about that state not being valid at draw time. */
if (retval == 0 && !renderer->viewport_queued) {

View File

@ -99,6 +99,7 @@ typedef enum
SDL_RENDERCMD_SETVIEWPORT,
SDL_RENDERCMD_SETCLIPRECT,
SDL_RENDERCMD_SETDRAWCOLOR,
SDL_RENDERCMD_SETCOLORSCALE,
SDL_RENDERCMD_CLEAR,
SDL_RENDERCMD_DRAW_POINTS,
SDL_RENDERCMD_DRAW_LINES,
@ -166,6 +167,7 @@ struct SDL_Renderer
int (*CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props);
int (*QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
int (*QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
int (*QueueSetColorScale)(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
int (*QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points,
int count);
int (*QueueDrawLines)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points,
@ -262,10 +264,12 @@ struct SDL_Renderer
SDL_RenderCommand *render_commands_pool;
Uint32 render_command_generation;
SDL_FColor last_queued_color;
float last_queued_color_scale;
SDL_Rect last_queued_viewport;
SDL_Rect last_queued_cliprect;
SDL_bool last_queued_cliprect_enabled;
SDL_bool color_queued;
SDL_bool color_scale_queued;
SDL_bool viewport_queued;
SDL_bool cliprect_queued;

View File

@ -808,7 +808,7 @@ static int D3D_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
return D3D_SetRenderTargetInternal(renderer, texture);
}
static int D3D_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int D3D_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
@ -1179,6 +1179,11 @@ static int D3D_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
break;
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_SETVIEWPORT:
{
SDL_Rect *viewport = &data->drawstate.viewport;
@ -1615,8 +1620,9 @@ SDL_Renderer *D3D_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
renderer->UnlockTexture = D3D_UnlockTexture;
renderer->SetTextureScaleMode = D3D_SetTextureScaleMode;
renderer->SetRenderTarget = D3D_SetRenderTarget;
renderer->QueueSetViewport = D3D_QueueSetViewport;
renderer->QueueSetDrawColor = D3D_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueSetViewport = D3D_QueueNoOp;
renderer->QueueSetDrawColor = D3D_QueueNoOp;
renderer->QueueSetColorScale = D3D_QueueNoOp;
renderer->QueueDrawPoints = D3D_QueueDrawPoints;
renderer->QueueDrawLines = D3D_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = D3D_QueueGeometry;

View File

@ -1851,7 +1851,7 @@ static int D3D11_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
return 0;
}
static int D3D11_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int D3D11_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
@ -1860,6 +1860,7 @@ static int D3D11_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
{
VertexPositionColor *verts = (VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertexPositionColor), 0, &cmd->data.draw.first);
int i;
SDL_FColor color = cmd->data.draw.color;
SDL_bool convert_color = SDL_RenderingLinearSpace(renderer);
if (!verts) {
@ -1868,15 +1869,16 @@ static int D3D11_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
cmd->data.draw.count = count;
if (convert_color) {
SDL_ConvertToLinear(&color);
}
for (i = 0; i < count; i++) {
verts->pos.x = points[i].x + 0.5f;
verts->pos.y = points[i].y + 0.5f;
verts->tex.x = 0.0f;
verts->tex.y = 0.0f;
verts->color = cmd->data.draw.color;
if (convert_color) {
SDL_ConvertToLinear(&verts->color);
}
verts->color = color;
verts++;
}
@ -2358,6 +2360,11 @@ static int D3D11_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
break; /* this isn't currently used in this render backend. */
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_SETVIEWPORT:
{
SDL_Rect *viewport = &rendererData->currentViewport;
@ -2661,8 +2668,9 @@ SDL_Renderer *D3D11_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p
renderer->UnlockTexture = D3D11_UnlockTexture;
renderer->SetTextureScaleMode = D3D11_SetTextureScaleMode;
renderer->SetRenderTarget = D3D11_SetRenderTarget;
renderer->QueueSetViewport = D3D11_QueueSetViewport;
renderer->QueueSetDrawColor = D3D11_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueSetViewport = D3D11_QueueNoOp;
renderer->QueueSetDrawColor = D3D11_QueueNoOp;
renderer->QueueSetColorScale = D3D11_QueueNoOp;
renderer->QueueDrawPoints = D3D11_QueueDrawPoints;
renderer->QueueDrawLines = D3D11_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = D3D11_QueueGeometry;

View File

@ -2288,7 +2288,7 @@ static int D3D12_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
return 0;
}
static int D3D12_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int D3D12_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
@ -2297,6 +2297,7 @@ static int D3D12_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
{
VertexPositionColor *verts = (VertexPositionColor *)SDL_AllocateRenderVertices(renderer, count * sizeof(VertexPositionColor), 0, &cmd->data.draw.first);
int i;
SDL_FColor color = cmd->data.draw.color;
SDL_bool convert_color = SDL_RenderingLinearSpace(renderer);
if (!verts) {
@ -2305,15 +2306,16 @@ static int D3D12_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
cmd->data.draw.count = count;
if (convert_color) {
SDL_ConvertToLinear(&color);
}
for (i = 0; i < count; i++) {
verts->pos.x = points[i].x + 0.5f;
verts->pos.y = points[i].y + 0.5f;
verts->tex.x = 0.0f;
verts->tex.y = 0.0f;
verts->color = cmd->data.draw.color;
if (convert_color) {
SDL_ConvertToLinear(&verts->color);
}
verts->color = color;
verts++;
}
@ -2775,6 +2777,11 @@ static int D3D12_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
break; /* this isn't currently used in this render backend. */
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_SETVIEWPORT:
{
SDL_Rect *viewport = &rendererData->currentViewport;
@ -3168,8 +3175,9 @@ SDL_Renderer *D3D12_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_p
renderer->UnlockTexture = D3D12_UnlockTexture;
renderer->SetTextureScaleMode = D3D12_SetTextureScaleMode;
renderer->SetRenderTarget = D3D12_SetRenderTarget;
renderer->QueueSetViewport = D3D12_QueueSetViewport;
renderer->QueueSetDrawColor = D3D12_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueSetViewport = D3D12_QueueNoOp;
renderer->QueueSetDrawColor = D3D12_QueueNoOp;
renderer->QueueSetColorScale = D3D12_QueueNoOp;
renderer->QueueDrawPoints = D3D12_QueueDrawPoints;
renderer->QueueDrawLines = D3D12_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = D3D12_QueueGeometry;

View File

@ -556,10 +556,18 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
switch (texture->format) {
case SDL_PIXELFORMAT_ABGR8888:
pixfmt = MTLPixelFormatRGBA8Unorm;
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB) {
pixfmt = MTLPixelFormatRGBA8Unorm_sRGB;
} else {
pixfmt = MTLPixelFormatRGBA8Unorm;
}
break;
case SDL_PIXELFORMAT_ARGB8888:
pixfmt = MTLPixelFormatBGRA8Unorm;
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB) {
pixfmt = MTLPixelFormatBGRA8Unorm_sRGB;
} else {
pixfmt = MTLPixelFormatBGRA8Unorm;
}
break;
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_YV12:
@ -567,6 +575,12 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL
case SDL_PIXELFORMAT_NV21:
pixfmt = MTLPixelFormatR8Unorm;
break;
case SDL_PIXELFORMAT_RGBA64_FLOAT:
pixfmt = MTLPixelFormatRGBA16Float;
break;
case SDL_PIXELFORMAT_RGBA128_FLOAT:
pixfmt = MTLPixelFormatRGBA32Float;
break;
default:
return SDL_SetError("Texture format %s not supported by Metal", SDL_GetPixelFormatName(texture->format));
}
@ -1042,15 +1056,29 @@ static int METAL_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd
return 0;
}
static int METAL_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int METAL_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
static int METAL_QueueSetColorScale(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
const size_t vertlen = (2 * sizeof(float));
float *verts = (float *)SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.color.first);
if (!verts) {
return -1;
}
*verts++ = (float)SDL_RenderingLinearSpace(renderer);
*verts++ = cmd->data.color.color_scale;
return 0;
}
static int METAL_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
{
SDL_FColor color = cmd->data.draw.color;
const float color_scale = cmd->data.draw.color_scale;
SDL_bool convert_color = SDL_RenderingLinearSpace(renderer);
const size_t vertlen = (2 * sizeof(float) + 4 * sizeof(float)) * count;
float *verts = (float *)SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
@ -1059,9 +1087,9 @@ static int METAL_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
}
cmd->data.draw.count = count;
color.r *= color_scale;
color.g *= color_scale;
color.b *= color_scale;
if (convert_color) {
SDL_ConvertToLinear(&color);
}
for (int i = 0; i < count; i++, points++) {
*(verts++) = points->x;
@ -1077,7 +1105,7 @@ static int METAL_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
static int METAL_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
{
SDL_FColor color = cmd->data.draw.color;
const float color_scale = cmd->data.draw.color_scale;
SDL_bool convert_color = SDL_RenderingLinearSpace(renderer);
size_t vertlen;
float *verts;
@ -1090,9 +1118,9 @@ static int METAL_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
}
cmd->data.draw.count = count;
color.r *= color_scale;
color.g *= color_scale;
color.b *= color_scale;
if (convert_color) {
SDL_ConvertToLinear(&color);
}
for (int i = 0; i < count; i++, points++) {
*(verts++) = points->x;
@ -1135,7 +1163,7 @@ static int METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
int num_vertices, const void *indices, int num_indices, int size_indices,
float scale_x, float scale_y)
{
const float color_scale = cmd->data.draw.color_scale;
SDL_bool convert_color = SDL_RenderingLinearSpace(renderer);
int count = indices ? num_indices : num_vertices;
const size_t vertlen = (2 * sizeof(float) + 4 * sizeof(float) + (texture ? 2 : 0) * sizeof(float)) * count;
float *verts = (float *)SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
@ -1149,7 +1177,7 @@ static int METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
for (int i = 0; i < count; i++) {
int j;
float *xy_;
SDL_FColor *col_;
SDL_FColor col_;
if (size_indices == 4) {
j = ((const Uint32 *)indices)[i];
} else if (size_indices == 2) {
@ -1165,12 +1193,16 @@ static int METAL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, S
*(verts++) = xy_[0] * scale_x;
*(verts++) = xy_[1] * scale_y;
col_ = (SDL_FColor *)((char *)color + j * color_stride);
col_ = *(SDL_FColor *)((char *)color + j * color_stride);
*(verts++) = col_->r * color_scale;
*(verts++) = col_->g * color_scale;
*(verts++) = col_->b * color_scale;
*(verts++) = col_->a;
if (convert_color) {
SDL_ConvertToLinear(&col_);
}
*(verts++) = col_.r;
*(verts++) = col_.g;
*(verts++) = col_.b;
*(verts++) = col_.a;
if (texture) {
float *uv_ = (float *)((char *)uv + j * uv_stride);
@ -1196,6 +1228,8 @@ typedef struct
size_t projection_offset;
SDL_bool color_dirty;
size_t color_offset;
SDL_bool color_scale_dirty;
size_t color_scale_offset;
} METAL_DrawStateCache;
static SDL_bool SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_MetalFragmentFunction shader,
@ -1256,10 +1290,17 @@ static SDL_bool SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cm
statecache->cliprect_dirty = SDL_FALSE;
}
#if 0 /* Not used... */
if (statecache->color_dirty) {
[data.mtlcmdencoder setFragmentBufferOffset:statecache->color_offset atIndex:0];
statecache->color_dirty = SDL_FALSE;
}
#endif
if (statecache->color_scale_dirty) {
[data.mtlcmdencoder setFragmentBufferOffset:statecache->color_scale_offset atIndex:0];
statecache->color_dirty = SDL_FALSE;
}
newpipeline = ChoosePipelineState(data, data.activepipelines, shader, blend);
if (newpipeline != statecache->pipeline) {
@ -1381,6 +1422,13 @@ static int METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
break;
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
statecache.color_scale_offset = cmd->data.color.first;
statecache.color_scale_dirty = SDL_TRUE;
break;
}
case SDL_RENDERCMD_CLEAR:
{
/* If we're already encoding a command buffer, dump it without committing it. We'd just
@ -1404,15 +1452,19 @@ static int METAL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
statecache.viewport_dirty = SDL_TRUE;
{
const float r = cmd->data.color.color.r * cmd->data.color.color_scale;
const float g = cmd->data.color.color.g * cmd->data.color.color_scale;
const float b = cmd->data.color.color.b * cmd->data.color.color_scale;
const float a = cmd->data.color.color.a;
MTLClearColor color = MTLClearColorMake(r, g, b, a);
SDL_bool convert_color = SDL_RenderingLinearSpace(renderer);
SDL_FColor color = cmd->data.color.color;
if (convert_color) {
SDL_ConvertToLinear(&color);
}
color.r *= cmd->data.color.color_scale;
color.g *= cmd->data.color.color_scale;
color.b *= cmd->data.color.color_scale;
MTLClearColor mtlcolor = MTLClearColorMake(color.r, color.g, color.b, color.a);
// get new command encoder, set up with an initial clear operation.
// (this might fail, and future draw operations will notice.)
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, mtlbufvertex);
METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &mtlcolor, mtlbufvertex);
}
break;
}
@ -1502,7 +1554,22 @@ static SDL_Surface *METAL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rec
mtlregion = MTLRegionMake2D(rect->x, rect->y, rect->w, rect->h);
format = (mtltexture.pixelFormat == MTLPixelFormatBGRA8Unorm) ? SDL_PIXELFORMAT_ARGB8888 : SDL_PIXELFORMAT_ABGR8888;
switch (mtltexture.pixelFormat) {
case MTLPixelFormatBGRA8Unorm:
case MTLPixelFormatBGRA8Unorm_sRGB:
format = SDL_PIXELFORMAT_ARGB8888;
break;
case MTLPixelFormatRGBA8Unorm:
case MTLPixelFormatRGBA8Unorm_sRGB:
format = SDL_PIXELFORMAT_ABGR8888;
break;
case MTLPixelFormatRGBA16Float:
format = SDL_PIXELFORMAT_RGBA64_FLOAT;
break;
default:
SDL_SetError("Unknown framebuffer pixel format");
return NULL;
}
surface = SDL_CreateSurface(rect->w, rect->h, format);
if (surface) {
[mtltexture getBytes:surface->pixels bytesPerRow:surface->pitch fromRegion:mtlregion mipmapLevel:0];
@ -1672,6 +1739,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices;
id<MTLCommandBuffer> cmdbuffer;
id<MTLBlitCommandEncoder> blitcmd;
SDL_bool scRGB_supported = SDL_FALSE;
/* Note: matrices are column major. */
float identitytransform[16] = {
@ -1726,10 +1794,19 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
SDL_SetupRendererColorspace(renderer, create_props);
#ifndef SDL_PLATFORM_TVOS
if (@available(macos 10.11, iOS 16.0, *)) {
scRGB_supported = SDL_TRUE;
}
#endif
if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB && scRGB_supported) {
/* This colorspace is supported */
} else {
SDL_SetError("Unsupported output colorspace");
SDL_free(renderer);
return NULL;
}
}
#ifdef SDL_PLATFORM_MACOS
@ -1790,6 +1867,22 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
layer = (CAMetalLayer *)[(__bridge UIView *)view layer];
#endif
#ifndef SDL_PLATFORM_TVOS
if (renderer->output_colorspace == SDL_COLORSPACE_SCRGB) {
if (@available(macos 10.11, iOS 16.0, *)) {
layer.wantsExtendedDynamicRangeContent = YES;
} else {
SDL_assert(!"Logic error, scRGB is not actually supported");
}
layer.pixelFormat = MTLPixelFormatRGBA16Float;
const CFStringRef name = kCGColorSpaceExtendedLinearSRGB;
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(name);
layer.colorspace = colorspace;
CGColorSpaceRelease(colorspace);
}
#endif /* !SDL_PLATFORM_TVOS */
layer.device = mtldevice;
/* Necessary for RenderReadPixels. */
@ -1889,7 +1982,8 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
renderer->SetTextureScaleMode = METAL_SetTextureScaleMode;
renderer->SetRenderTarget = METAL_SetRenderTarget;
renderer->QueueSetViewport = METAL_QueueSetViewport;
renderer->QueueSetDrawColor = METAL_QueueSetDrawColor;
renderer->QueueSetDrawColor = METAL_QueueNoOp;
renderer->QueueSetColorScale = METAL_QueueSetColorScale;
renderer->QueueDrawPoints = METAL_QueueDrawPoints;
renderer->QueueDrawLines = METAL_QueueDrawLines;
renderer->QueueGeometry = METAL_QueueGeometry;
@ -1964,9 +2058,11 @@ SDL_RenderDriver METAL_RenderDriver = {
{
"metal",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
6,
8,
{ SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_RGBA64_FLOAT,
SDL_PIXELFORMAT_RGBA128_FLOAT,
SDL_PIXELFORMAT_YV12,
SDL_PIXELFORMAT_IYUV,
SDL_PIXELFORMAT_NV12,

View File

@ -1,8 +1,88 @@
#include <metal_common>
#include <metal_texture>
#include <metal_matrix>
using namespace metal;
float3 scRGBtoNits(float3 v)
{
return v * 80.0;
}
float3 scRGBfromNits(float3 v)
{
return v / 80.0;
}
float sRGBtoLinear(float v)
{
if (v <= 0.04045) {
v = (v / 12.92);
} else {
v = pow(abs(v + 0.055) / 1.055, 2.4);
}
return v;
}
float sRGBfromLinear(float v)
{
if (v <= 0.0031308) {
v = (v * 12.92);
} else {
v = (pow(abs(v), 1.0 / 2.4) * 1.055 - 0.055);
}
return v;
}
float4 GetOutputColor(float4 rgba, float color_scale)
{
float4 output;
output.rgb = rgba.rgb * color_scale;
output.a = rgba.a;
return output;
}
float4 GetOutputColorFromSRGB(float3 rgb, float scRGB_output, float color_scale)
{
float4 output;
if (scRGB_output) {
rgb.r = sRGBtoLinear(rgb.r);
rgb.g = sRGBtoLinear(rgb.g);
rgb.b = sRGBtoLinear(rgb.b);
}
output.rgb = rgb * color_scale;
output.a = 1.0;
return output;
}
float4 GetOutputColorFromSCRGB(float3 rgb, float scRGB_output, float color_scale)
{
float4 output;
output.rgb = rgb * color_scale;
output.a = 1.0;
if (!scRGB_output) {
output.r = sRGBfromLinear(output.r);
output.g = sRGBfromLinear(output.g);
output.b = sRGBfromLinear(output.b);
output.rgb = clamp(output.rgb, 0.0, 1.0);
}
return output;
}
struct ShaderConstants
{
float scRGB_output;
float color_scale;
};
struct SolidVertexInput
{
float2 position [[attribute(0)]];
@ -27,9 +107,10 @@ vertex SolidVertexOutput SDL_Solid_vertex(SolidVertexInput in [[stage_in]],
return v;
}
fragment float4 SDL_Solid_fragment(SolidVertexInput in [[stage_in]])
fragment float4 SDL_Solid_fragment(SolidVertexInput in [[stage_in]],
constant ShaderConstants &c [[buffer(0)]])
{
return in.color;
return GetOutputColor(1.0, c.color_scale) * in.color;
}
struct CopyVertexInput
@ -58,10 +139,11 @@ vertex CopyVertexOutput SDL_Copy_vertex(CopyVertexInput in [[stage_in]],
}
fragment float4 SDL_Copy_fragment(CopyVertexOutput vert [[stage_in]],
constant ShaderConstants &c [[buffer(0)]],
texture2d<float> tex [[texture(0)]],
sampler s [[sampler(0)]])
{
return tex.sample(s, vert.texcoord) * vert.color;
return GetOutputColor(tex.sample(s, vert.texcoord), c.color_scale) * vert.color;
}
struct YUVDecode
@ -73,6 +155,7 @@ struct YUVDecode
};
fragment float4 SDL_YUV_fragment(CopyVertexOutput vert [[stage_in]],
constant ShaderConstants &c [[buffer(0)]],
constant YUVDecode &decode [[buffer(1)]],
texture2d<float> texY [[texture(0)]],
texture2d_array<float> texUV [[texture(1)]],
@ -83,38 +166,52 @@ fragment float4 SDL_YUV_fragment(CopyVertexOutput vert [[stage_in]],
yuv.y = texUV.sample(s, vert.texcoord, 0).r;
yuv.z = texUV.sample(s, vert.texcoord, 1).r;
float3 rgb;
yuv += decode.offset;
rgb.r = dot(yuv, decode.Rcoeff);
rgb.g = dot(yuv, decode.Gcoeff);
rgb.b = dot(yuv, decode.Bcoeff);
return vert.color * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
return GetOutputColorFromSRGB(rgb, c.scRGB_output, c.color_scale) * vert.color;
}
fragment float4 SDL_NV12_fragment(CopyVertexOutput vert [[stage_in]],
constant YUVDecode &decode [[buffer(1)]],
texture2d<float> texY [[texture(0)]],
texture2d<float> texUV [[texture(1)]],
sampler s [[sampler(0)]])
constant ShaderConstants &c [[buffer(0)]],
constant YUVDecode &decode [[buffer(1)]],
texture2d<float> texY [[texture(0)]],
texture2d<float> texUV [[texture(1)]],
sampler s [[sampler(0)]])
{
float3 yuv;
yuv.x = texY.sample(s, vert.texcoord).r;
yuv.yz = texUV.sample(s, vert.texcoord).rg;
float3 rgb;
yuv += decode.offset;
rgb.r = dot(yuv, decode.Rcoeff);
rgb.g = dot(yuv, decode.Gcoeff);
rgb.b = dot(yuv, decode.Bcoeff);
return vert.color * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
return GetOutputColorFromSRGB(rgb, c.scRGB_output, c.color_scale) * vert.color;
}
fragment float4 SDL_NV21_fragment(CopyVertexOutput vert [[stage_in]],
constant YUVDecode &decode [[buffer(1)]],
texture2d<float> texY [[texture(0)]],
texture2d<float> texUV [[texture(1)]],
sampler s [[sampler(0)]])
constant ShaderConstants &c [[buffer(0)]],
constant YUVDecode &decode [[buffer(1)]],
texture2d<float> texY [[texture(0)]],
texture2d<float> texUV [[texture(1)]],
sampler s [[sampler(0)]])
{
float3 yuv;
yuv.x = texY.sample(s, vert.texcoord).r;
yuv.yz = texUV.sample(s, vert.texcoord).gr;
float3 rgb;
yuv += decode.offset;
rgb.r = dot(yuv, decode.Rcoeff);
rgb.g = dot(yuv, decode.Gcoeff);
rgb.b = dot(yuv, decode.Bcoeff);
return vert.color * float4(dot(yuv, decode.Rcoeff), dot(yuv, decode.Gcoeff), dot(yuv, decode.Bcoeff), 1.0);
return GetOutputColorFromSRGB(rgb, c.scRGB_output, c.color_scale) * vert.color;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -910,7 +910,7 @@ static int GL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
/* !!! FIXME: all these Queue* calls set up the vertex buffer the way the immediate mode
!!! FIXME: renderer wants it, but this might want to operate differently if we move to
!!! FIXME: VBOs at some point. */
static int GL_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int GL_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
@ -1251,6 +1251,11 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
break;
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_SETVIEWPORT:
{
SDL_Rect *viewport = &data->drawstate.viewport;
@ -1700,8 +1705,9 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, SDL_PropertiesID crea
renderer->UnlockTexture = GL_UnlockTexture;
renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
renderer->SetRenderTarget = GL_SetRenderTarget;
renderer->QueueSetViewport = GL_QueueSetViewport;
renderer->QueueSetDrawColor = GL_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueSetViewport = GL_QueueNoOp;
renderer->QueueSetDrawColor = GL_QueueNoOp;
renderer->QueueSetColorScale = GL_QueueNoOp;
renderer->QueueDrawPoints = GL_QueueDrawPoints;
renderer->QueueDrawLines = GL_QueueDrawLines;
renderer->QueueGeometry = GL_QueueGeometry;

View File

@ -733,7 +733,7 @@ fault:
return -1;
}
static int GLES2_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int GLES2_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
@ -1238,6 +1238,11 @@ static int GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
break;
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_SETVIEWPORT:
{
SDL_Rect *viewport = &data->drawstate.viewport;
@ -2181,8 +2186,9 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, SDL_PropertiesID c
renderer->UnlockTexture = GLES2_UnlockTexture;
renderer->SetTextureScaleMode = GLES2_SetTextureScaleMode;
renderer->SetRenderTarget = GLES2_SetRenderTarget;
renderer->QueueSetViewport = GLES2_QueueSetViewport;
renderer->QueueSetDrawColor = GLES2_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueSetViewport = GLES2_QueueNoOp;
renderer->QueueSetDrawColor = GLES2_QueueNoOp;
renderer->QueueSetColorScale = GLES2_QueueNoOp;
renderer->QueueDrawPoints = GLES2_QueueDrawPoints;
renderer->QueueDrawLines = GLES2_QueueDrawLines;
renderer->QueueGeometry = GLES2_QueueGeometry;

View File

@ -228,7 +228,7 @@ static int PS2_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
return 0;
}
static int PS2_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int PS2_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
@ -504,6 +504,10 @@ static int PS2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
PS2_RenderSetDrawColor(renderer, cmd);
break;
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_CLEAR:
{
PS2_RenderClear(renderer, cmd);
@ -692,7 +696,8 @@ static SDL_Renderer *PS2_CreateRenderer(SDL_Window *window, SDL_PropertiesID cre
renderer->SetTextureScaleMode = PS2_SetTextureScaleMode;
renderer->SetRenderTarget = PS2_SetRenderTarget;
renderer->QueueSetViewport = PS2_QueueSetViewport;
renderer->QueueSetDrawColor = PS2_QueueSetDrawColor;
renderer->QueueSetDrawColor = PS2_QueueNoOp;
renderer->QueueSetColorScale = PS2_QueueNoOp;
renderer->QueueDrawPoints = PS2_QueueDrawPoints;
renderer->QueueDrawLines = PS2_QueueDrawPoints;
renderer->QueueGeometry = PS2_QueueGeometry;

View File

@ -624,7 +624,7 @@ static int PSP_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
return 0;
}
static int PSP_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int PSP_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
@ -1072,6 +1072,11 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
break;
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_SETVIEWPORT:
{
SDL_Rect *viewport = &cmd->data.viewport.rect;
@ -1320,8 +1325,9 @@ SDL_Renderer *PSP_CreateRenderer(SDL_Window *window, SDL_PropertiesID create_pro
renderer->UnlockTexture = PSP_UnlockTexture;
renderer->SetTextureScaleMode = PSP_SetTextureScaleMode;
renderer->SetRenderTarget = PSP_SetRenderTarget;
renderer->QueueSetViewport = PSP_QueueSetViewport;
renderer->QueueSetDrawColor = PSP_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueSetViewport = PSP_QueueNoOp;
renderer->QueueSetDrawColor = PSP_QueueNoOp;
renderer->QueueSetColorScale = PSP_QueueNoOp;
renderer->QueueDrawPoints = PSP_QueueDrawPoints;
renderer->QueueDrawLines = PSP_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueGeometry = PSP_QueueGeometry;

View File

@ -188,7 +188,7 @@ static int SW_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
return 0;
}
static int SW_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int SW_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
@ -706,6 +706,11 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
break;
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_SETVIEWPORT:
{
drawstate.viewport = &cmd->data.viewport.rect;
@ -1149,8 +1154,9 @@ SDL_Renderer *SW_CreateRendererForSurface(SDL_Surface *surface)
renderer->UnlockTexture = SW_UnlockTexture;
renderer->SetTextureScaleMode = SW_SetTextureScaleMode;
renderer->SetRenderTarget = SW_SetRenderTarget;
renderer->QueueSetViewport = SW_QueueSetViewport;
renderer->QueueSetDrawColor = SW_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueSetViewport = SW_QueueNoOp;
renderer->QueueSetDrawColor = SW_QueueNoOp;
renderer->QueueSetColorScale = SW_QueueNoOp;
renderer->QueueDrawPoints = SW_QueueDrawPoints;
renderer->QueueDrawLines = SW_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueFillRects = SW_QueueFillRects;

View File

@ -75,7 +75,7 @@ static void VITA_GXM_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *te
static int VITA_GXM_SetRenderTarget(SDL_Renderer *renderer,
SDL_Texture *texture);
static int VITA_GXM_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
static int VITA_GXM_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
static int VITA_GXM_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
@ -247,8 +247,9 @@ SDL_Renderer *VITA_GXM_CreateRenderer(SDL_Window *window, SDL_PropertiesID creat
renderer->UnlockTexture = VITA_GXM_UnlockTexture;
renderer->SetTextureScaleMode = VITA_GXM_SetTextureScaleMode;
renderer->SetRenderTarget = VITA_GXM_SetRenderTarget;
renderer->QueueSetViewport = VITA_GXM_QueueSetViewport;
renderer->QueueSetViewport = VITA_GXM_QueueNoOp;
renderer->QueueSetDrawColor = VITA_GXM_QueueSetDrawColor;
renderer->QueueSetColorScale = VITA_GXM_QueueNoOp;
renderer->QueueDrawPoints = VITA_GXM_QueueDrawPoints;
renderer->QueueDrawLines = VITA_GXM_QueueDrawLines;
renderer->QueueGeometry = VITA_GXM_QueueGeometry;
@ -661,7 +662,7 @@ static void VITA_GXM_SetBlendMode(VITA_GXM_RenderData *data, int blendMode)
}
}
static int VITA_GXM_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
static int VITA_GXM_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
{
return 0;
}
@ -1005,6 +1006,11 @@ static int VITA_GXM_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *c
break;
}
case SDL_RENDERCMD_SETCOLORSCALE:
{
break;
}
case SDL_RENDERCMD_CLEAR:
{
VITA_GXM_RenderClear(renderer, cmd);

View File

@ -156,6 +156,11 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
selector:@selector(focusSomeWindow:)
name:NSApplicationDidBecomeActiveNotification
object:nil];
[center addObserver:self
selector:@selector(screenParametersChanged:)
name:NSApplicationDidChangeScreenParametersNotification
object:nil];
}
[center addObserver:self
@ -178,6 +183,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
[center removeObserver:self name:NSWindowWillCloseNotification object:nil];
[center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
[center removeObserver:self name:NSApplicationDidChangeScreenParametersNotification object:nil];
[center removeObserver:self name:NSCurrentLocaleDidChangeNotification object:nil];
[NSApp removeObserver:self forKeyPath:@"effectiveAppearance"];
@ -276,6 +282,11 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
}
}
- (void)screenParametersChanged:(NSNotification *)aNotification
{
Cocoa_UpdateDisplays(SDL_GetVideoDevice());
}
- (void)localeDidChange:(NSNotification *)notification
{
SDL_SendLocaleChangedEvent();

View File

@ -34,6 +34,7 @@ struct SDL_DisplayModeData
};
extern void Cocoa_InitModes(SDL_VideoDevice *_this);
extern void Cocoa_UpdateDisplays(SDL_VideoDevice *_this);
extern int Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
extern int Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
extern int Cocoa_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display);

View File

@ -83,6 +83,20 @@ static int CG_SetError(const char *prefix, CGDisplayErr result)
return SDL_SetError("%s: %s", prefix, error);
}
static NSScreen *GetNSScreenForDisplayID(CGDirectDisplayID displayID)
{
NSArray *screens = [NSScreen screens];
/* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
for (NSScreen *screen in screens) {
const CGDirectDisplayID thisDisplay = (CGDirectDisplayID)[[[screen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
if (thisDisplay == displayID) {
return screen;
}
}
return nil;
}
static float GetDisplayModeRefreshRate(CGDisplayModeRef vidmode, CVDisplayLinkRef link)
{
double refreshRate = CGDisplayModeGetRefreshRate(vidmode);
@ -261,13 +275,13 @@ static SDL_bool GetDisplayMode(SDL_VideoDevice *_this, CGDisplayModeRef vidmode,
return SDL_TRUE;
}
static const char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
static char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
{
/* This API is deprecated in 10.9 with no good replacement (as of 10.15). */
io_service_t servicePort = CGDisplayIOServicePort(displayID);
CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
NSDictionary *localizedNames = [(__bridge NSDictionary *)deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
const char *displayName = NULL;
char *displayName = NULL;
if ([localizedNames count] > 0) {
displayName = SDL_strdup([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
@ -276,6 +290,21 @@ static const char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
return displayName;
}
static void Cocoa_GetHDRProperties(CGDirectDisplayID displayID, SDL_HDRDisplayProperties *HDR)
{
HDR->enabled = SDL_FALSE;
HDR->SDR_whitelevel = 0.0f;
if (@available(macOS 10.15, *)) {
NSScreen *screen = GetNSScreenForDisplayID(displayID);
if (screen && screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1.0f) {
HDR->enabled = SDL_TRUE;
HDR->SDR_whitelevel = 80.0f; /* SDR content is always at scRGB 1.0 */
}
}
}
void Cocoa_InitModes(SDL_VideoDevice *_this)
{
@autoreleasepool {
@ -337,8 +366,8 @@ void Cocoa_InitModes(SDL_VideoDevice *_this)
CVDisplayLinkCreateWithCGDisplay(displays[i], &link);
SDL_zero(display);
/* this returns a stddup'ed string */
display.name = (char *)Cocoa_GetDisplayName(displays[i]);
/* this returns a strdup'ed string */
display.name = Cocoa_GetDisplayName(displays[i]);
if (!GetDisplayMode(_this, moderef, SDL_TRUE, NULL, link, &mode)) {
CVDisplayLinkRelease(link);
CGDisplayModeRelease(moderef);
@ -350,6 +379,8 @@ void Cocoa_InitModes(SDL_VideoDevice *_this)
CVDisplayLinkRelease(link);
CGDisplayModeRelease(moderef);
Cocoa_GetHDRProperties(displaydata->display, &display.HDR);
display.desktop_mode = mode;
display.driverdata = displaydata;
SDL_AddVideoDisplay(&display, SDL_FALSE);
@ -360,6 +391,20 @@ void Cocoa_InitModes(SDL_VideoDevice *_this)
}
}
void Cocoa_UpdateDisplays(SDL_VideoDevice *_this)
{
SDL_HDRDisplayProperties HDR;
int i;
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *display = _this->displays[i];
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
Cocoa_GetHDRProperties(displaydata->display, &HDR);
SDL_SetDisplayHDRProperties(display, &HDR);
}
}
int Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
{
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
@ -376,22 +421,10 @@ int Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SD
int Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
{
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
const CGDirectDisplayID cgdisplay = displaydata->display;
NSArray *screens = [NSScreen screens];
NSScreen *screen = nil;
NSScreen *screen = GetNSScreenForDisplayID(displaydata->display);
/* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
for (NSScreen *i in screens) {
const CGDirectDisplayID thisDisplay = (CGDirectDisplayID)[[[i deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
if (thisDisplay == cgdisplay) {
screen = i;
break;
}
}
SDL_assert(screen != nil); /* didn't find it?! */
if (screen == nil) {
return -1;
return SDL_SetError("Couldn't get NSScreen for display");
}
{

View File

@ -242,6 +242,15 @@ int UIKit_AddDisplay(UIScreen *uiscreen, SDL_bool send_event)
}
display.desktop_mode = mode;
#ifndef SDL_PLATFORM_TVOS
if (@available(iOS 16.0, *)) {
if (uiscreen.potentialEDRHeadroom > 1.0f) {
display.HDR.enabled = SDL_TRUE;
display.HDR.SDR_whitelevel = 80.0f; /* SDR content is always at scRGB 1.0 */
}
}
#endif /* !SDL_PLATFORM_TVOS */
/* Allocate the display data */
#ifdef SDL_PLATFORM_VISIONOS
SDL_UIKitDisplayData *data = [[SDL_UIKitDisplayData alloc] init];
@ -273,13 +282,13 @@ int UIKit_AddDisplay(SDL_bool send_event){
mode.pixel_density = 1;
mode.format = SDL_PIXELFORMAT_ABGR8888;
mode.refresh_rate = 60;
display.natural_orientation = SDL_ORIENTATION_LANDSCAPE;
display.desktop_mode = mode;
SDL_UIKitDisplayData *data = [[SDL_UIKitDisplayData alloc] init];
if (!data) {
UIKit_FreeDisplayModeData(&display.desktop_mode);
return SDL_OutOfMemory();
@ -341,7 +350,7 @@ int UIKit_InitModes(SDL_VideoDevice *_this)
}
}
#endif
#if !defined(SDL_PLATFORM_TVOS) && !defined(SDL_PLATFORM_VISIONOS)
SDL_OnApplicationDidChangeStatusBarOrientation();
#endif

View File

@ -145,6 +145,8 @@ static void CreateRenderer(void)
renderer_name = info.name;
UpdateSDRWhiteLevel();
SDL_Log("HDR is %s\n", HDR_enabled ? "enabled" : "disabled");
}
static void NextRenderer( void )
@ -745,6 +747,7 @@ static void loop(void)
OnMouseHeld(event.button.x, event.button.y);
}
} else if (event.type == SDL_EVENT_DISPLAY_HDR_STATE_CHANGED) {
SDL_Log("HDR %s\n", event.display.data1 ? "enabled" : "disabled");
UpdateSDRWhiteLevel();
} else if (event.type == SDL_EVENT_QUIT) {
done = 1;

View File

@ -127,7 +127,9 @@ static void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite)
/* Test horizontal and vertical lines */
SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
SDL_RenderLine(renderer, 1.0f, 0.0f, (float)(viewport.w - 2), 0.0f);
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
SDL_RenderLine(renderer, 1.0f, (float)(viewport.h - 1), (float)(viewport.w - 2), (float)(viewport.h - 1));
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0xFF, 0xFF);
SDL_RenderLine(renderer, 0.0f, 1.0f, 0.0f, (float)(viewport.h - 2));
SDL_RenderLine(renderer, (float)(viewport.w - 1), 1.0f, (float)(viewport.w - 1), (float)(viewport.h - 2));