SDL: riscos: Refactor framebuffer code

From fe9bb74764dcc03f3859c67ffc12390cd6ea0df0 Mon Sep 17 00:00:00 2001
From: Cameron Cawley <[EMAIL REDACTED]>
Date: Fri, 12 Feb 2021 23:46:11 +0000
Subject: [PATCH] riscos: Refactor framebuffer code

---
 src/video/riscos/SDL_riscosdefs.h          |  51 +++++++++
 src/video/riscos/SDL_riscosframebuffer.c   | 114 +++++++++------------
 src/video/riscos/SDL_riscosframebuffer_c.h |   6 +-
 src/video/riscos/SDL_riscosvideo.c         |  24 ++---
 src/video/riscos/SDL_riscoswindow.c        |  76 ++++++++++++++
 src/video/riscos/SDL_riscoswindow.h        |  42 ++++++++
 6 files changed, 224 insertions(+), 89 deletions(-)
 create mode 100644 src/video/riscos/SDL_riscosdefs.h
 create mode 100644 src/video/riscos/SDL_riscoswindow.c
 create mode 100644 src/video/riscos/SDL_riscoswindow.h

diff --git a/src/video/riscos/SDL_riscosdefs.h b/src/video/riscos/SDL_riscosdefs.h
new file mode 100644
index 0000000000..3179fbed8b
--- /dev/null
+++ b/src/video/riscos/SDL_riscosdefs.h
@@ -0,0 +1,51 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_riscosdefs_h_
+#define SDL_riscosdefs_h_
+
+typedef struct sprite_area {
+    int size;  /*  +0 */
+    int count; /*  +4 */
+    int start; /*  +8 */
+    int end;   /* +12 */
+} sprite_area;
+
+SDL_COMPILE_TIME_ASSERT(sprite_area, sizeof(sprite_area) == 16);
+
+typedef struct sprite_header {
+    int next;         /*  +0 */
+    char name[12];    /*  +4 */
+    int width;        /* +16 */
+    int height;       /* +20 */
+    int first_bit;    /* +24 */
+    int last_bit;     /* +28 */
+    int image_offset; /* +32 */
+    int mask_offset;  /* +36 */
+    int mode;         /* +40 */
+} sprite_header;
+
+SDL_COMPILE_TIME_ASSERT(sprite_header, sizeof(sprite_header) == 44);
+
+#endif /* SDL_riscosdefs_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscosframebuffer.c b/src/video/riscos/SDL_riscosframebuffer.c
index 7764c42374..fe269753dd 100644
--- a/src/video/riscos/SDL_riscosframebuffer.c
+++ b/src/video/riscos/SDL_riscosframebuffer.c
@@ -25,122 +25,100 @@
 #include "../SDL_sysvideo.h"
 #include "SDL_riscosframebuffer_c.h"
 #include "SDL_riscosvideo.h"
+#include "SDL_riscoswindow.h"
 
 #include <kernel.h>
 #include <swis.h>
 
-#define DUMMY_SURFACE   "_SDL_DummySurface"
-
-typedef struct {
-    Uint32 size;
-    Uint32 count;
-    Uint32 start;
-    Uint32 end;
-} sprite_area;
-
-int SDL_RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
+int RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
 {
+    SDL_WindowData *driverdata = (SDL_WindowData *) window->driverdata;
     const char *sprite_name = "display";
-    int width, height, size, bytesPerRow;
     unsigned int sprite_mode;
     _kernel_oserror *error;
     _kernel_swi_regs regs;
-    sprite_area *buffer;
-    Uint32 pixelformat;
     SDL_DisplayMode mode;
+    int size;
 
     /* Free the old framebuffer surface */
-    buffer = (sprite_area *) SDL_SetWindowData(window, DUMMY_SURFACE, NULL);
-    SDL_free(buffer);
+    RISCOS_DestroyWindowFramebuffer(_this, window);
 
     /* Create a new one */
-    SDL_GetWindowSize(window, &width, &height);
     SDL_GetCurrentDisplayMode(SDL_GetWindowDisplayIndex(window), &mode);
-
     if ((SDL_ISPIXELFORMAT_PACKED(mode.format) || SDL_ISPIXELFORMAT_ARRAY(mode.format))) {
-        pixelformat = mode.format;
+        *format = mode.format;
         sprite_mode = (unsigned int)mode.driverdata;
     } else {
-        pixelformat = SDL_PIXELFORMAT_BGR888;
+        *format = SDL_PIXELFORMAT_BGR888;
         sprite_mode = (1 | (90 << 1) | (90 << 14) | (6 << 27));
     }
 
-    bytesPerRow = SDL_BYTESPERPIXEL(pixelformat) * width;
-    if ((bytesPerRow & 3) != 0) {
-        bytesPerRow += 4 - (bytesPerRow & 3);
-    }
-    size = 60 + (bytesPerRow * height);
+    /* Calculate pitch */
+    *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
 
-    buffer = SDL_malloc(size);
-    if (!buffer) {
-        SDL_OutOfMemory();
-        return -1;
+    /* Allocate the sprite area */
+    size = sizeof(sprite_area) + sizeof(sprite_header) + ((*pitch) * window->h);
+    driverdata->fb_area = SDL_malloc(size);
+    if (!driverdata->fb_area) {
+        return SDL_OutOfMemory();
     }
 
-    /* Initialise a sprite area */
-
-    buffer->size  = size;
-    buffer->start = 16;
-
-    regs.r[0] = 256+9;
-    regs.r[1] = (unsigned int)buffer;
-    error = _kernel_swi(OS_SpriteOp, &regs, &regs);
-    if (error != NULL) {
-        SDL_SetError("Unable to initialise sprite area: %s (%i)", error->errmess, error->errnum);
-        SDL_free(buffer);
-        return -1;
-    }
+    driverdata->fb_area->size  = size;
+    driverdata->fb_area->count = 0;
+    driverdata->fb_area->start = 16;
+    driverdata->fb_area->end   = 16;
 
+    /* Create the actual image */
     regs.r[0] = 256+15;
-    regs.r[1] = (unsigned int)buffer;
-    regs.r[2] = (unsigned int)sprite_name;
+    regs.r[1] = (int)driverdata->fb_area;
+    regs.r[2] = (int)sprite_name;
     regs.r[3] = 0;
-    regs.r[4] = width;
-    regs.r[5] = height;
+    regs.r[4] = window->w;
+    regs.r[5] = window->h;
     regs.r[6] = sprite_mode;
     error = _kernel_swi(OS_SpriteOp, &regs, &regs);
     if (error != NULL) {
-        SDL_SetError("Unable to create sprite: %s (%i)", error->errmess, error->errnum);
-        SDL_free(buffer);
-        return -1;
+        SDL_free(driverdata->fb_area);
+        return SDL_SetError("Unable to create sprite: %s (%i)", error->errmess, error->errnum);
     }
 
-    /* Save the info and return! */
-    SDL_SetWindowData(window, DUMMY_SURFACE, buffer);
-    *format = pixelformat;
-    *pixels = ((Uint8 *)buffer) + 60;
-    *pitch = bytesPerRow;
+    driverdata->fb_sprite = (sprite_header *)(((Uint8 *)driverdata->fb_area) + driverdata->fb_area->start);
+    *pixels = ((Uint8 *)driverdata->fb_sprite) + driverdata->fb_sprite->image_offset;
 
     return 0;
 }
 
-int SDL_RISCOS_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+int RISCOS_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
 {
+    SDL_WindowData *driverdata = (SDL_WindowData *) window->driverdata;
     _kernel_swi_regs regs;
-    sprite_area *buffer;
-
-    buffer = (sprite_area *) SDL_GetWindowData(window, DUMMY_SURFACE);
-    if (!buffer) {
-        return SDL_SetError("Couldn't find sprite for window");
-    }
+    _kernel_oserror *error;
 
     regs.r[0] = 512+52;
-    regs.r[1] = (unsigned int)buffer;
-    regs.r[2] = (unsigned int)buffer + buffer->start;
-    regs.r[3] = window->x * 2;
-    regs.r[4] = window->y * 2;
+    regs.r[1] = (int)driverdata->fb_area;
+    regs.r[2] = (int)driverdata->fb_sprite;
+    regs.r[3] = window->x << 1;
+    regs.r[4] = window->y << 1;
     regs.r[5] = 0x50;
     regs.r[6] = 0;
     regs.r[7] = 0;
-    _kernel_swi(OS_SpriteOp, &regs, &regs);
+    error = _kernel_swi(OS_SpriteOp, &regs, &regs);
+    if (error != NULL) {
+        return SDL_SetError("OS_SpriteOp 52 failed: %s (%i)", error->errmess, error->errnum);
+    }
 
     return 0;
 }
 
-void SDL_RISCOS_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
+void RISCOS_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
 {
-    sprite_area *buffer = (sprite_area *) SDL_SetWindowData(window, DUMMY_SURFACE, NULL);
-    SDL_free(buffer);
+    SDL_WindowData *driverdata = (SDL_WindowData *) window->driverdata;
+
+    if (driverdata->fb_area) {
+        SDL_free(driverdata->fb_area);
+        driverdata->fb_area = NULL;
+    }
+    driverdata->fb_sprite = NULL;
 }
 
 #endif /* SDL_VIDEO_DRIVER_RISCOS */
diff --git a/src/video/riscos/SDL_riscosframebuffer_c.h b/src/video/riscos/SDL_riscosframebuffer_c.h
index 196a33338d..0307c4e9b8 100644
--- a/src/video/riscos/SDL_riscosframebuffer_c.h
+++ b/src/video/riscos/SDL_riscosframebuffer_c.h
@@ -24,9 +24,9 @@
 
 #include "../../SDL_internal.h"
 
-extern int SDL_RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
-extern int SDL_RISCOS_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
-extern void SDL_RISCOS_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
+extern int RISCOS_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
+extern int RISCOS_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
+extern void RISCOS_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
 
 #endif /* SDL_riscosframebuffer_c_h_ */
 
diff --git a/src/video/riscos/SDL_riscosvideo.c b/src/video/riscos/SDL_riscosvideo.c
index d39a3df2c0..d2f34f6a41 100644
--- a/src/video/riscos/SDL_riscosvideo.c
+++ b/src/video/riscos/SDL_riscosvideo.c
@@ -37,10 +37,8 @@
  *  SDL video driver.  Renamed to "DUMMY" by Sam Lantinga.
  */
 
-#include "SDL_version.h"
 #include "SDL_video.h"
 #include "SDL_mouse.h"
-#include "SDL_syswm.h"
 #include "../SDL_sysvideo.h"
 #include "../SDL_pixels_c.h"
 #include "../../events/SDL_events_c.h"
@@ -48,6 +46,7 @@
 #include "SDL_riscosvideo.h"
 #include "SDL_riscosevents_c.h"
 #include "SDL_riscosframebuffer_c.h"
+#include "SDL_riscoswindow.h"
 
 #include <kernel.h>
 #include <swis.h>
@@ -58,7 +57,6 @@
 static int RISCOS_VideoInit(_THIS);
 static int RISCOS_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
 static void RISCOS_VideoQuit(_THIS);
-SDL_bool RISCOS_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info);
 
 /* RISC OS driver bootstrap functions */
 
@@ -86,11 +84,13 @@ RISCOS_CreateDevice(int devindex)
     device->SetDisplayMode = RISCOS_SetDisplayMode;
     device->PumpEvents = RISCOS_PumpEvents;
 
+    device->CreateSDLWindow = RISCOS_CreateWindow;
+    device->DestroyWindow = RISCOS_DestroyWindow;
     device->GetWindowWMInfo = RISCOS_GetWindowWMInfo;
 
-    device->CreateWindowFramebuffer = SDL_RISCOS_CreateWindowFramebuffer;
-    device->UpdateWindowFramebuffer = SDL_RISCOS_UpdateWindowFramebuffer;
-    device->DestroyWindowFramebuffer = SDL_RISCOS_DestroyWindowFramebuffer;
+    device->CreateWindowFramebuffer = RISCOS_CreateWindowFramebuffer;
+    device->UpdateWindowFramebuffer = RISCOS_UpdateWindowFramebuffer;
+    device->DestroyWindowFramebuffer = RISCOS_DestroyWindowFramebuffer;
 
     device->free = RISCOS_DeleteDevice;
 
@@ -234,18 +234,6 @@ RISCOS_VideoQuit(_THIS)
 {
 }
 
-SDL_bool RISCOS_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info) {
-    if (info->version.major == SDL_MAJOR_VERSION &&
-        info->version.minor == SDL_MINOR_VERSION) {
-        info->subsystem = SDL_SYSWM_RISCOS;
-        return SDL_TRUE;
-    } else {
-        SDL_SetError("Application not compiled with SDL %d.%d",
-                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
-        return SDL_FALSE;
-    }
-}
-
 #endif /* SDL_VIDEO_DRIVER_RISCOS */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscoswindow.c b/src/video/riscos/SDL_riscoswindow.c
new file mode 100644
index 0000000000..37ec8c6211
--- /dev/null
+++ b/src/video/riscos/SDL_riscoswindow.c
@@ -0,0 +1,76 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_RISCOS
+
+#include "SDL_version.h"
+#include "SDL_syswm.h"
+#include "../SDL_sysvideo.h"
+
+#include "SDL_riscosvideo.h"
+#include "SDL_riscoswindow.h"
+
+int
+RISCOS_CreateWindow(_THIS, SDL_Window * window)
+{
+    SDL_WindowData *driverdata;
+
+    driverdata = (SDL_WindowData *) SDL_calloc(1, sizeof(*driverdata));
+    if (!driverdata) {
+        return SDL_OutOfMemory();
+    }
+    driverdata->window = window;
+
+    /* All done! */
+    window->driverdata = driverdata;
+    return 0;
+}
+
+void
+RISCOS_DestroyWindow(_THIS, SDL_Window * window)
+{
+    SDL_WindowData *driverdata = (SDL_WindowData *) window->driverdata;
+
+    if (!driverdata)
+        return;
+
+    SDL_free(driverdata);
+    window->driverdata = NULL;
+}
+
+SDL_bool
+RISCOS_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
+{
+    if (info->version.major == SDL_MAJOR_VERSION &&
+        info->version.minor == SDL_MINOR_VERSION) {
+        info->subsystem = SDL_SYSWM_RISCOS;
+        return SDL_TRUE;
+    } else {
+        SDL_SetError("Application not compiled with SDL %d.%d",
+                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
+        return SDL_FALSE;
+    }
+}
+
+#endif /* SDL_VIDEO_DRIVER_RISCOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/riscos/SDL_riscoswindow.h b/src/video/riscos/SDL_riscoswindow.h
new file mode 100644
index 0000000000..2266eea9f9
--- /dev/null
+++ b/src/video/riscos/SDL_riscoswindow.h
@@ -0,0 +1,42 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_riscoswindow_h_
+#define SDL_riscoswindow_h_
+
+#include "SDL_riscosdefs.h"
+
+typedef struct
+{
+    SDL_Window *window;
+    sprite_area *fb_area;
+    sprite_header *fb_sprite;
+} SDL_WindowData;
+
+extern int RISCOS_CreateWindow(_THIS, SDL_Window * window);
+extern void RISCOS_DestroyWindow(_THIS, SDL_Window * window);
+extern SDL_bool RISCOS_GetWindowWMInfo(_THIS, SDL_Window * window,
+                                    struct SDL_SysWMinfo *info);
+
+#endif /* SDL_riscoswindow_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */