Backport to Glide 2

Most games were using Glide 2, meaning there is more wrappers for Glide
2 available than for Glide 3. In particular, it seems there is no open
source Glide 3 wrapper.

FossilOrigin-Name: 16bb6bc399e5b4db4f5117199f6b534231c42072555575b70f40795651805648
This commit is contained in:
Jonathan Schleifer 2023-01-10 01:12:33 +00:00
parent c322610fe4
commit 4ea8389306
10 changed files with 255 additions and 543 deletions

228
src/O3DGlideRenderer.m Normal file
View file

@ -0,0 +1,228 @@
/*
* Copyright (c) 2022 Jonathan Schleifer <js@nil.im>
*
* All rights reserved.
*
* This file is part of Obj3DEngine. It may be distributed under the terms of
* the Q Public License 1.0, which can be found in the file LICENSE.QPL
* included in the packaging of this file.
*
* Alternatively, it may be distributed under the terms of the GNU General
* Public License, either version 2 or 3, which can be found in the file
* LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of
* this file.
*/
#include <assert.h>
#include <stdlib.h>
#import "O3DGlideRenderer.h"
#import "O3DWinAPIWindow.h"
static GrScreenResolution_t
sizeToScreenResolution(OFSize size)
{
if (size.width == 320 && size.height == 200)
return GR_RESOLUTION_320x200;
if (size.width == 320 && size.height == 240)
return GR_RESOLUTION_320x240;
if (size.width == 400 && size.height == 256)
return GR_RESOLUTION_400x256;
if (size.width == 512 && size.height == 384)
return GR_RESOLUTION_512x384;
if (size.width == 640 && size.height == 200)
return GR_RESOLUTION_640x200;
if (size.width == 640 && size.height == 350)
return GR_RESOLUTION_640x350;
if (size.width == 640 && size.height == 400)
return GR_RESOLUTION_640x400;
if (size.width == 640 && size.height == 480)
return GR_RESOLUTION_640x480;
if (size.width == 800 && size.height == 600)
return GR_RESOLUTION_800x600;
if (size.width == 960 && size.height == 720)
return GR_RESOLUTION_960x720;
if (size.width == 856 && size.height == 480)
return GR_RESOLUTION_856x480;
if (size.width == 512 && size.height == 256)
return GR_RESOLUTION_512x256;
if (size.width == 1024 && size.height == 768)
return GR_RESOLUTION_1024x768;
if (size.width == 1280 && size.height == 1024)
return GR_RESOLUTION_1280x1024;
if (size.width == 1600 && size.height == 1200)
return GR_RESOLUTION_1600x1200;
if (size.width == 400 && size.height == 300)
return GR_RESOLUTION_400x300;
if (size.width == 1152 && size.height == 864)
return GR_RESOLUTION_1152x864;
if (size.width == 1280 && size.height == 960)
return GR_RESOLUTION_1280x960;
if (size.width == 1600 && size.height == 1024)
return GR_RESOLUTION_1600x1024;
if (size.width == 1792 && size.height == 1344)
return GR_RESOLUTION_1792x1344;
if (size.width == 1856 && size.height == 1392)
return GR_RESOLUTION_1856x1392;
if (size.width == 1920 && size.height == 1440)
return GR_RESOLUTION_1920x1440;
if (size.width == 2048 && size.height == 1536)
return GR_RESOLUTION_2048x1536;
if (size.width == 2048 && size.height == 2048)
return GR_RESOLUTION_2048x2048;
@throw [OFInvalidArgumentException exception];
}
static GrScreenRefresh_t
floatToScreenRefresh(float refresh)
{
if (refresh == 60)
return GR_REFRESH_60Hz;
if (refresh == 70)
return GR_REFRESH_70Hz;
if (refresh == 72)
return GR_REFRESH_72Hz;
if (refresh == 75)
return GR_REFRESH_75Hz;
if (refresh == 80)
return GR_REFRESH_80Hz;
if (refresh == 90)
return GR_REFRESH_90Hz;
if (refresh == 100)
return GR_REFRESH_100Hz;
if (refresh == 85)
return GR_REFRESH_85Hz;
if (refresh == 120)
return GR_REFRESH_120Hz;
@throw [OFInvalidArgumentException exception];
}
@implementation O3DGlideRenderer
@synthesize syncsToVerticalBlank = _syncsToVerticalBlank;
static void
grGlideShutdownCdecl(void)
{
grGlideShutdown();
}
+ (void)initialize
{
if (self != [O3DGlideRenderer class])
return;
grGlideInit();
atexit(grGlideShutdownCdecl);
}
+ (unsigned int)numAvailableDevices
{
GrHwConfiguration config;
if (!grSstQueryHardware(&config))
return 0;
if (config.num_sst < 0)
return 0;
return (unsigned int)config.num_sst;
}
- (instancetype)initWithResolution: (OFSize)resolution
bitsPerPixel: (uint8_t)bitsPerPixel
refreshRate: (float)refreshRate
options: (nullable OFDictionary *)options
{
self = [super init];
@try {
if (bitsPerPixel != 16)
@throw [OFInvalidArgumentException exception];
long long deviceIndex = [[options objectForKey:
O3DRendererDeviceIndex] longLongValue];
if (deviceIndex > [self.class numAvailableDevices])
@throw [OFInvalidArgumentException exception];
grSstSelect((int)deviceIndex);
FxU32 hWnd = 0;
#ifdef OF_WINDOWS
_winAPIWindow = [[O3DWinAPIWindow alloc]
initWithSize: resolution];
hWnd = (FxU32)_winAPIWindow.hWnd;
#endif
if (!grSstWinOpen(hWnd, sizeToScreenResolution(resolution),
floatToScreenRefresh(refreshRate), GR_COLORFORMAT_RGBA,
GR_ORIGIN_LOWER_LEFT, 2, 1))
@throw [OFInitializationFailedException
exceptionWithClass: self.class];
} @catch (id e) {
[self release];
@throw e;
}
return self;
}
- (void)dealloc
{
grSstWinClose();
#ifdef OF_WINDOWS
[_winAPIWindow release];
#endif
[super dealloc];
}
- (void)beginFrame
{
grBufferClear(0, 0, 0);
}
- (void)setColor: (OFColor *)color
{
float values[4];
[color getRed: &values[0]
green: &values[1]
blue: &values[2]
alpha: &values[3]];
for (uint_fast8_t i = 0; i < 4; i++)
values[i] *= 255;
grColorCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE,
GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE);
grConstantColorValue((((GrColor_t)values[0]) << 24) |
(((GrColor_t)values[1]) << 16) | (((GrColor_t)values[2]) << 8) |
(GrColor_t)values[2]);
}
- (void)drawPolygonVertices: (const O3DVertex *)vertices count: (size_t)count
{
/*
* Range is -1 to 1, we add 1, so we get 0 to 2 - so we need to
* multiply with half the width / height.
*/
float halfWidth = grSstScreenWidth() / 2;
float halfHeight = grSstScreenHeight() / 2;
GrVertex *glideVertices = OFAllocMemory(count, sizeof(GrVertex));
@try {
for (size_t i = 0; i < count; i++) {
glideVertices[i].x = (vertices[i].x + 1) * halfWidth;
glideVertices[i].y = (vertices[i].y + 1) * halfHeight;
}
grDrawPolygonVertexList((int)count, glideVertices);
} @finally {
OFFreeMemory(glideVertices);
}
}
- (void)endFrame
{
grBufferSwap(_syncsToVerticalBlank ? 1 : 0);
}
@end