SDL-1.2: atari:video: make OpenGL usable with a static OSMesa

From 527dfc98cc4f09dfd8e0c6d66018ea2e15ad277e Mon Sep 17 00:00:00 2001
From: Miro Kropacek <[EMAIL REDACTED]>
Date: Thu, 24 Sep 2026 11:33:02 +1000
Subject: [PATCH] atari:video: make OpenGL usable with a static OSMesa

Programs not using OpenGL no longer link the whole of OSMesa (~2.5 MB).
OSMesa itself has to link its context functions whenever any gl*()
function is used (it requires patched OSMesa build).

OpenGL surfaces are centered in GEM fullscreen, like 2D ones.
---
 src/video/SDL_video.c               |  2 --
 src/video/ataricommon/SDL_atarigl.c | 52 ++++++++++++++++++-----------
 src/video/gem/SDL_gemvideo.c        | 17 ++++++++++
 src/video/xbios/SDL_xbios.c         |  5 +++
 4 files changed, 55 insertions(+), 21 deletions(-)

diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 4618f5dec..75b889784 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -786,8 +786,6 @@ SDL_Surface * SDL_SetVideoMode (int width, int height, int bpp, Uint32 flags)
 
 #if defined(__QNXNTO__) && (_NTO_VERSION < 630)
 #define __SDL_NOGETPROCADDR__
-#elif defined(__MINT__)
-#define __SDL_NOGETPROCADDR__
 #endif
 #ifdef __SDL_NOGETPROCADDR__
     #define SDL_PROC(ret,func,params) video->func=func;
diff --git a/src/video/ataricommon/SDL_atarigl.c b/src/video/ataricommon/SDL_atarigl.c
index 1cf2689c9..46c4fae10 100644
--- a/src/video/ataricommon/SDL_atarigl.c
+++ b/src/video/ataricommon/SDL_atarigl.c
@@ -27,6 +27,16 @@
 
 #if SDL_VIDEO_OPENGL
 #include <GL/osmesa.h>
+
+/* Keep OSMesa out of programs that don't use OpenGL; any gl*() call pulls it in */
+#pragma weak OSMesaCreateContextExt
+#pragma weak OSMesaDestroyContext
+#pragma weak OSMesaMakeCurrent
+#pragma weak OSMesaPixelStore
+#pragma weak OSMesaGetProcAddress
+#pragma weak glGetIntegerv
+#pragma weak glFinish
+#pragma weak glFlush
 #endif
 
 #include <mint/osbind.h>
@@ -336,7 +346,7 @@ int SDL_AtariGL_MakeCurrent(_THIS)
 		type = GL_UNSIGNED_BYTE;
 	}
 
-	if (!(this->gl_data->OSMesaMakeCurrent(gl_ctx, surface->pixels, type, surface->w, surface->h))) {
+	if (!(this->gl_data->OSMesaMakeCurrent(gl_ctx, (Uint8 *)surface->pixels + surface->offset, type, surface->w, surface->h))) {
 		SDL_SetError("Can not make OpenGL context current");
 		return -1;
 	}
@@ -344,6 +354,9 @@ int SDL_AtariGL_MakeCurrent(_THIS)
 	/* OSMesa draws upside down */
 	this->gl_data->OSMesaPixelStore(OSMESA_Y_UP, 0);
 
+	/* The surface can be a part of a larger buffer */
+	this->gl_data->OSMesaPixelStore(OSMESA_ROW_LENGTH, surface->pitch / gl_pixelsize);
+
 	return 0;
 #else
 	return -1;
@@ -411,12 +424,13 @@ static int InitNew(_THIS, SDL_Surface *current)
 	int recreatecontext;
 	GLint newaccumsize;
 
-	if (this->gl_config.dll_handle) {
-		if (this->gl_data->OSMesaCreateContextExt == NULL) {
-			return 0;
-		}
+	if (this->gl_data->OSMesaCreateContextExt == NULL) {
+		return 0;
 	}
 
+	/* SDL_SetVideoMode() looks up GL functions via SDL_GL_GetProcAddress() */
+	this->gl_config.driver_loaded = 1;
+
 	/* Init OpenGL context using OSMesa */
 	gl_convert = ConvertNull;
 	gl_copyshadow = CopyShadowNull;
@@ -684,7 +698,7 @@ static void CopyShadowDirect(_THIS, SDL_Surface *surface)
 
 	srcline = gl_shadow;
 	srcpitch = surface->w * gl_pixelsize;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -707,7 +721,7 @@ static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint8 *)gl_shadow;
 	srcpitch = surface->w * gl_pixelsize;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch >>1;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -739,7 +753,7 @@ static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint8 *)gl_shadow;
 	srcpitch = surface->w * gl_pixelsize;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch >>1;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -772,7 +786,7 @@ static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint8 *)gl_shadow;
 	srcpitch = surface->w * gl_pixelsize;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -803,7 +817,7 @@ static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint8 *)gl_shadow;
 	srcpitch = surface->w * gl_pixelsize;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch >>2;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -837,7 +851,7 @@ static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint8 *)gl_shadow;
 	srcpitch = surface->w * gl_pixelsize;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch >>2;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -871,7 +885,7 @@ static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint8 *)gl_shadow;
 	srcpitch = surface->w * gl_pixelsize;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch >>2;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -905,7 +919,7 @@ static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint8 *)gl_shadow;
 	srcpitch = surface->w * gl_pixelsize;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch >>2;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -939,7 +953,7 @@ static void CopyShadow8888To555(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint32 *)gl_shadow;
 	srcpitch = (surface->w * gl_pixelsize) >>2;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch >>1;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -973,7 +987,7 @@ static void CopyShadow8888To565(_THIS, SDL_Surface *surface)
 
 	srcline = (Uint32 *)gl_shadow;
 	srcpitch = (surface->w * gl_pixelsize) >> 2;
-	dstline = surface->pixels;
+	dstline = (void *)((Uint8 *)surface->pixels + surface->offset);
 	dstpitch = surface->pitch >>1;
 	if (gl_upsidedown) {
 		srcline += (surface->h-1)*srcpitch;
@@ -1011,7 +1025,7 @@ static void Convert565To555be(_THIS, SDL_Surface *surface)
 	int x,y, pitch;
 	unsigned short *line, *pixel;
 
-	line = surface->pixels;
+	line = (void *)((Uint8 *)surface->pixels + surface->offset);
 	pitch = surface->pitch >> 1;
 	for (y=0; y<surface->h; y++) {
 		pixel = line;
@@ -1030,7 +1044,7 @@ static void Convert565To555le(_THIS, SDL_Surface *surface)
 	int x,y, pitch;
 	unsigned short *line, *pixel;
 
-	line = surface->pixels;
+	line = (void *)((Uint8 *)surface->pixels + surface->offset);
 	pitch = surface->pitch >>1;
 	for (y=0; y<surface->h; y++) {
 		pixel = line;
@@ -1050,7 +1064,7 @@ static void Convert565le(_THIS, SDL_Surface *surface)
 	int x,y, pitch;
 	unsigned short *line, *pixel;
 
-	line = surface->pixels;
+	line = (void *)((Uint8 *)surface->pixels + surface->offset);
 	pitch = surface->pitch >>1;
 	for (y=0; y<surface->h; y++) {
 		pixel = line;
@@ -1069,7 +1083,7 @@ static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface)
 	int x,y, pitch;
 	unsigned long *line, *pixel;
 
-	line = surface->pixels;
+	line = (void *)((Uint8 *)surface->pixels + surface->offset);
 	pitch = surface->pitch >>2;
 	for (y=0; y<surface->h; y++) {
 		pixel = line;
diff --git a/src/video/gem/SDL_gemvideo.c b/src/video/gem/SDL_gemvideo.c
index 9459ef980..f248bf6de 100644
--- a/src/video/gem/SDL_gemvideo.c
+++ b/src/video/gem/SDL_gemvideo.c
@@ -655,11 +655,18 @@ static SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current,
 {
 	Uint32 modeflags, screensize;
 	SDL_bool use_shadow1, use_shadow2;
+#if SDL_VIDEO_OPENGL
+	int surf_width, surf_height;
+#endif
 
 	/* width must be multiple of 16, for vro_cpyfm() and c2p_convert() */
 	if ((width & 15) != 0) {
 		width = (width | 15) +1;
 	}
+#if SDL_VIDEO_OPENGL
+	surf_width = width;
+	surf_height = height;
+#endif
 
 	/*--- Verify if asked mode can be used ---*/
 	if (VDI_bpp != bpp) {
@@ -867,6 +874,16 @@ static SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current,
 
 #if SDL_VIDEO_OPENGL
 	if (flags & SDL_OPENGL) {
+		/* SDL_SetVideoMode() centers a 2D surface only */
+		if (flags & SDL_FULLSCREEN) {
+			this->offset_x = (width - surf_width) / 2;
+			this->offset_y = (height - surf_height) / 2;
+			current->offset = this->offset_y * current->pitch +
+				this->offset_x * VDI_pixelsize;
+			current->w = surf_width;
+			current->h = surf_height;
+		}
+
 		if (!SDL_AtariGL_Init(this, current)) {
 			GEM_FreeBuffers(this);
 			SDL_SetError("Can not create OpenGL context");
diff --git a/src/video/xbios/SDL_xbios.c b/src/video/xbios/SDL_xbios.c
index c28987c13..9fd8ec343 100644
--- a/src/video/xbios/SDL_xbios.c
+++ b/src/video/xbios/SDL_xbios.c
@@ -571,6 +571,11 @@ static SDL_Surface *XBIOS_SetVideoMode(_THIS, SDL_Surface *current,
 
 #if SDL_VIDEO_OPENGL
 	if (flags & SDL_OPENGL) {
+		/* SDL_SetVideoMode() sets the offsets of a 2D surface only */
+		current->offset = 0;
+		this->offset_x = 0;
+		this->offset_y = 0;
+
 		if (!SDL_AtariGL_Init(this, current)) {
 			XBIOS_FreeBuffers(this);
 			SDL_SetError("Can not create OpenGL context");