Mac and Linux SDL2 binary snapshots
Edward Rudd
2021-06-15 dec7875a6e23212021e4d9080330a42832dfe02a
source/src/render/metal/SDL_render_metal.m
@@ -23,8 +23,6 @@
#if SDL_VIDEO_RENDER_METAL && !SDL_RENDER_DISABLED
#include "SDL_hints.h"
#include "SDL_log.h"
#include "SDL_assert.h"
#include "SDL_syswm.h"
#include "SDL_metal.h"
#include "../SDL_sysrender.h"
@@ -41,16 +39,27 @@
#ifdef __MACOSX__
#include "SDL_shaders_metal_osx.h"
#elif defined(__TVOS__)
#if TARGET_OS_SIMULATOR
#include "SDL_shaders_metal_tvsimulator.h"
#else
#include "SDL_shaders_metal_tvos.h"
#endif
#else
#if TARGET_OS_SIMULATOR
#include "SDL_shaders_metal_iphonesimulator.h"
#else
#include "SDL_shaders_metal_ios.h"
#endif
#endif
/* Apple Metal renderer implementation */
/* Used to re-create the window with Metal capability */
extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
/* macOS requires constants in a buffer to have a 256 byte alignment. */
/* Use native type alignments from https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf */
#ifdef __MACOSX__
#if defined(__MACOSX__) || TARGET_OS_SIMULATOR
#define CONSTANT_ALIGN(x) (256)
#else
#define CONSTANT_ALIGN(x) (x < 4 ? 4 : x)
@@ -1043,6 +1052,44 @@
}
static int
METAL_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
    SDL_assert(count >= 2);  /* should have been checked at the higher level. */
    const size_t vertlen = (sizeof (float) * 2) * count;
    float *verts = (float *) SDL_AllocateRenderVertices(renderer, vertlen, DEVICE_ALIGN(8), &cmd->data.draw.first);
    if (!verts) {
        return -1;
    }
    cmd->data.draw.count = count;
    SDL_memcpy(verts, points, vertlen);
    /* If the line segment is completely horizontal or vertical,
       make it one pixel longer, to satisfy the diamond-exit rule.
       We should probably do this for diagonal lines too, but we'd have to
       do some trigonometry to figure out the correct pixel and generally
       when we have problems with pixel perfection, it's for straight lines
       that are missing a pixel that frames something and not arbitrary
       angles. Maybe !!! FIXME for later, though. */
    points += count - 2;  /* update the last line. */
    verts += (count * 2) - 2;
    const float xstart = points[0].x;
    const float ystart = points[0].y;
    const float xend = points[1].x;
    const float yend = points[1].y;
    if (ystart == yend) {  /* horizontal line */
        verts[0] += (xend > xstart) ? 1.0f : -1.0f;
    } else if (xstart == xend) {  /* vertical line */
        verts[1] += (yend > ystart) ? 1.0f : -1.0f;
    }
    return 0;
}
static int
METAL_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
    const size_t vertlen = (sizeof (float) * 8) * count;
@@ -1516,15 +1563,21 @@
{ @autoreleasepool {
    METAL_RenderData *data = (__bridge METAL_RenderData *) renderer->driverdata;
    if (data.mtlcmdencoder != nil) {
        [data.mtlcmdencoder endEncoding];
    // If we don't have a command buffer, we can't present, so activate to get one.
    if (data.mtlcmdencoder == nil) {
        // We haven't even gotten a backbuffer yet? Clear it to black. Otherwise, load the existing data.
        if (data.mtlbackbuffer == nil) {
            MTLClearColor color = MTLClearColorMake(0.0f, 0.0f, 0.0f, 1.0f);
            METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionClear, &color, nil);
        } else {
            METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);
        }
    }
    if (data.mtlbackbuffer != nil) {
        [data.mtlcmdbuffer presentDrawable:data.mtlbackbuffer];
    }
    if (data.mtlcmdbuffer != nil) {
        [data.mtlcmdbuffer commit];
    }
    [data.mtlcmdencoder endEncoding];
    [data.mtlcmdbuffer presentDrawable:data.mtlbackbuffer];
    [data.mtlcmdbuffer commit];
    data.mtlcmdencoder = nil;
    data.mtlcmdbuffer = nil;
    data.mtlbackbuffer = nil;
@@ -1579,6 +1632,8 @@
    SDL_MetalView view = NULL;
    CAMetalLayer *layer = nil;
    SDL_SysWMinfo syswm;
    Uint32 window_flags;
    SDL_bool changed_window = SDL_FALSE;
    SDL_VERSION(&syswm.version);
    if (!SDL_GetWindowWMInfo(window, &syswm)) {
@@ -1589,9 +1644,20 @@
        return NULL;
    }
    window_flags = SDL_GetWindowFlags(window);
    if (!(window_flags & SDL_WINDOW_METAL)) {
        changed_window = SDL_TRUE;
        if (SDL_RecreateWindow(window, (window_flags & ~(SDL_WINDOW_VULKAN | SDL_WINDOW_OPENGL)) | SDL_WINDOW_METAL) < 0) {
            return NULL;
        }
    }
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
    if (!renderer) {
        SDL_OutOfMemory();
        if (changed_window) {
            SDL_RecreateWindow(window, window_flags);
        }
        return NULL;
    }
@@ -1601,6 +1667,9 @@
    if (mtldevice == nil) {
        SDL_free(renderer);
        SDL_SetError("Failed to obtain Metal device");
        if (changed_window) {
            SDL_RecreateWindow(window, window_flags);
        }
        return NULL;
    }
@@ -1611,6 +1680,9 @@
        [mtldevice release];
#endif
        SDL_free(renderer);
        if (changed_window) {
            SDL_RecreateWindow(window, window_flags);
        }
        return NULL;
    }
@@ -1623,6 +1695,9 @@
#endif
        SDL_Metal_DestroyView(view);
        SDL_free(renderer);
        if (changed_window) {
            SDL_RecreateWindow(window, window_flags);
        }
        return NULL;
    }
@@ -1783,7 +1858,7 @@
    renderer->QueueSetViewport = METAL_QueueSetViewport;
    renderer->QueueSetDrawColor = METAL_QueueSetDrawColor;
    renderer->QueueDrawPoints = METAL_QueueDrawPoints;
    renderer->QueueDrawLines = METAL_QueueDrawPoints;  // lines and points queue the same way.
    renderer->QueueDrawLines = METAL_QueueDrawLines;
    renderer->QueueFillRects = METAL_QueueFillRects;
    renderer->QueueCopy = METAL_QueueCopy;
    renderer->QueueCopyEx = METAL_QueueCopyEx;