Implemented scRGB colorspace and HDR support on macOS

This commit is contained in:
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);