mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-06 06:32:56 +01:00
reinstate hardware display
This commit is contained in:
@@ -43,7 +43,7 @@ extern "C"
|
||||
_drawingEngine = DrawingEngineFactory::CreateSoftware();
|
||||
break;
|
||||
case DRAWING_ENGINE_SOFTWARE_WITH_HARDWARE_DISPLAY:
|
||||
_drawingEngine = DrawingEngineFactory::CreateSoftware();
|
||||
_drawingEngine = DrawingEngineFactory::CreateSoftwareWithHardwareDisplay();
|
||||
break;
|
||||
case DRAWING_ENGINE_OPENGL:
|
||||
_drawingEngine = DrawingEngineFactory::CreateOpenGL();
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
extern "C"
|
||||
{
|
||||
#include "../../config.h"
|
||||
#include "../../game.h"
|
||||
#include "../../interface/screenshot.h"
|
||||
#include "../../interface/window.h"
|
||||
#include "../../intro.h"
|
||||
@@ -185,6 +186,18 @@ private:
|
||||
SDL_Surface * _RGBASurface = nullptr;
|
||||
SDL_Palette * _palette = nullptr;
|
||||
|
||||
// For hardware display only
|
||||
SDL_Renderer * _sdlRenderer = nullptr;
|
||||
SDL_Texture * _screenTexture = nullptr;
|
||||
SDL_PixelFormat * _screenTextureFormat = nullptr;
|
||||
uint32 _paletteHWMapped[256] = { 0 };
|
||||
|
||||
// Steam overlay checking
|
||||
uint32 _pixelBeforeOverlay = 0;
|
||||
uint32 _pixelAfterOverlay = 0;
|
||||
bool _overlayActive = false;
|
||||
bool _pausedBeforeOverlay = false;
|
||||
|
||||
uint32 _width = 0;
|
||||
uint32 _height = 0;
|
||||
uint32 _pitch = 0;
|
||||
@@ -213,6 +226,9 @@ public:
|
||||
SDL_FreeSurface(_surface);
|
||||
SDL_FreeSurface(_RGBASurface);
|
||||
SDL_FreePalette(_palette);
|
||||
SDL_DestroyTexture(_screenTexture);
|
||||
SDL_FreeFormat(_screenTextureFormat);
|
||||
SDL_DestroyRenderer(_sdlRenderer);
|
||||
}
|
||||
|
||||
void Initialise(SDL_Window * window) override
|
||||
@@ -225,42 +241,88 @@ public:
|
||||
SDL_FreeSurface(_surface);
|
||||
SDL_FreeSurface(_RGBASurface);
|
||||
SDL_FreePalette(_palette);
|
||||
SDL_DestroyTexture(_screenTexture);
|
||||
SDL_FreeFormat(_screenTextureFormat);
|
||||
SDL_DestroyRenderer(_sdlRenderer);
|
||||
|
||||
_surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
|
||||
_RGBASurface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
|
||||
SDL_SetSurfaceBlendMode(_RGBASurface, SDL_BLENDMODE_NONE);
|
||||
_palette = SDL_AllocPalette(256);
|
||||
|
||||
if (_surface == nullptr ||
|
||||
_palette == nullptr ||
|
||||
_RGBASurface == nullptr)
|
||||
if (_hardwareDisplay)
|
||||
{
|
||||
log_fatal("%p || %p || %p == NULL %s", _surface, _palette, _RGBASurface, SDL_GetError());
|
||||
exit(-1);
|
||||
}
|
||||
_sdlRenderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
|
||||
if (SDL_SetSurfacePalette(_surface, _palette))
|
||||
SDL_RendererInfo rendererInfo;
|
||||
SDL_GetRendererInfo(_sdlRenderer, &rendererInfo);
|
||||
|
||||
uint32 pixelFormat = SDL_PIXELFORMAT_UNKNOWN;
|
||||
for (uint32 i = 0; i < rendererInfo.num_texture_formats; i++)
|
||||
{
|
||||
uint32 format = rendererInfo.texture_formats[i];
|
||||
if (!SDL_ISPIXELFORMAT_FOURCC(format) &&
|
||||
!SDL_ISPIXELFORMAT_INDEXED(format) &&
|
||||
(pixelFormat == SDL_PIXELFORMAT_UNKNOWN || SDL_BYTESPERPIXEL(format) < SDL_BYTESPERPIXEL(pixelFormat)))
|
||||
{
|
||||
pixelFormat = format;
|
||||
}
|
||||
}
|
||||
|
||||
_screenTexture = SDL_CreateTexture(_sdlRenderer, pixelFormat, SDL_TEXTUREACCESS_STREAMING, width, height);
|
||||
|
||||
uint32 format;
|
||||
SDL_QueryTexture(_screenTexture, &format, 0, 0, 0);
|
||||
_screenTextureFormat = SDL_AllocFormat(format);
|
||||
|
||||
ConfigureBits(width, height, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_fatal("SDL_SetSurfacePalette failed %s", SDL_GetError());
|
||||
exit(-1);
|
||||
}
|
||||
_surface = SDL_CreateRGBSurface(0, width, height, 8, 0, 0, 0, 0);
|
||||
_RGBASurface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
|
||||
SDL_SetSurfaceBlendMode(_RGBASurface, SDL_BLENDMODE_NONE);
|
||||
_palette = SDL_AllocPalette(256);
|
||||
|
||||
ConfigureBits(width, height, _surface->pitch);
|
||||
if (_surface == nullptr ||
|
||||
_palette == nullptr ||
|
||||
_RGBASurface == nullptr)
|
||||
{
|
||||
log_fatal("%p || %p || %p == NULL %s", _surface, _palette, _RGBASurface, SDL_GetError());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (SDL_SetSurfacePalette(_surface, _palette))
|
||||
{
|
||||
log_fatal("SDL_SetSurfacePalette failed %s", SDL_GetError());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ConfigureBits(width, height, _surface->pitch);
|
||||
}
|
||||
}
|
||||
|
||||
void SetPalette(SDL_Color * palette) override
|
||||
{
|
||||
SDL_Surface * windowSurface = SDL_GetWindowSurface(gWindow);
|
||||
if (windowSurface == nullptr)
|
||||
if (_hardwareDisplay)
|
||||
{
|
||||
log_fatal("SDL_GetWindowSurface failed %s", SDL_GetError());
|
||||
exit(1);
|
||||
if (_screenTextureFormat != nullptr)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
_paletteHWMapped[i] = SDL_MapRGB(_screenTextureFormat, palette[i].r, palette[i].g, palette[i].b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_palette != nullptr && SDL_SetPaletteColors(_palette, gPalette, 0, 256))
|
||||
else
|
||||
{
|
||||
log_fatal("SDL_SetPaletteColors failed %s", SDL_GetError());
|
||||
exit(1);
|
||||
SDL_Surface * windowSurface = SDL_GetWindowSurface(gWindow);
|
||||
if (windowSurface == nullptr)
|
||||
{
|
||||
log_fatal("SDL_GetWindowSurface failed %s", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (_palette != nullptr && SDL_SetPaletteColors(_palette, palette, 0, 256))
|
||||
{
|
||||
log_fatal("SDL_SetPaletteColors failed %s", SDL_GetError());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +379,15 @@ public:
|
||||
|
||||
rct2_draw(&_bitsDPI);
|
||||
}
|
||||
Display();
|
||||
|
||||
if (_hardwareDisplay)
|
||||
{
|
||||
DisplayViaTexture();
|
||||
}
|
||||
else
|
||||
{
|
||||
Display();
|
||||
}
|
||||
}
|
||||
|
||||
void CopyRect(sint32 x, sint32 y, sint32 width, sint32 height, sint32 dx, sint32 dy) override
|
||||
@@ -588,6 +658,106 @@ private:
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayViaTexture()
|
||||
{
|
||||
void * pixels;
|
||||
int pitch;
|
||||
if (SDL_LockTexture(_screenTexture, nullptr, &pixels, &pitch) == 0)
|
||||
{
|
||||
uint8 * src = _bits;
|
||||
int padding = pitch - (_width * 4);
|
||||
if (pitch == _width * 4) {
|
||||
uint32 * dst = (uint32 *)pixels;
|
||||
for (int i = _width * _height; i > 0; i--)
|
||||
{
|
||||
*dst++ = *(uint32 *)(&_paletteHWMapped[*src++]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pitch == (_width * 2) + padding)
|
||||
{
|
||||
uint16 * dst = (uint16 *)pixels;
|
||||
for (sint32 y = (sint32)_height; y > 0; y--) {
|
||||
for (sint32 x = (sint32)_width; x > 0; x--) {
|
||||
const uint8 lower = *(uint8 *)(&_paletteHWMapped[*src++]);
|
||||
const uint8 upper = *(uint8 *)(&_paletteHWMapped[*src++]);
|
||||
*dst++ = (lower << 8) | upper;
|
||||
}
|
||||
dst = (uint16*)(((uint8 *)dst) + padding);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pitch == _width + padding)
|
||||
{
|
||||
uint8 * dst = (uint8 *)pixels;
|
||||
for (sint32 y = (sint32)_height; y > 0; y--) {
|
||||
for (sint32 x = (sint32)_width; x > 0; x--)
|
||||
{
|
||||
*dst++ = *(uint8 *)(&_paletteHWMapped[*src++]);
|
||||
}
|
||||
dst += padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_UnlockTexture(_screenTexture);
|
||||
}
|
||||
|
||||
SDL_RenderCopy(_sdlRenderer, _screenTexture, NULL, NULL);
|
||||
|
||||
if (gSteamOverlayActive && gConfigGeneral.steam_overlay_pause)
|
||||
{
|
||||
OverlayPreRenderCheck();
|
||||
}
|
||||
|
||||
SDL_RenderPresent(_sdlRenderer);
|
||||
|
||||
if (gSteamOverlayActive && gConfigGeneral.steam_overlay_pause)
|
||||
{
|
||||
OverlayPostRenderCheck();
|
||||
}
|
||||
}
|
||||
|
||||
void ReadCentrePixel(uint32 * pixel)
|
||||
{
|
||||
SDL_Rect centrePixelRegion = { (sint32)(_width / 2), (sint32)(_height / 2), 1, 1 };
|
||||
SDL_RenderReadPixels(_sdlRenderer, ¢rePixelRegion, SDL_PIXELFORMAT_RGBA8888, pixel, sizeof(uint32));
|
||||
}
|
||||
|
||||
// Should be called before SDL_RenderPresent to capture frame buffer before Steam overlay is drawn.
|
||||
void OverlayPreRenderCheck()
|
||||
{
|
||||
ReadCentrePixel(&_pixelBeforeOverlay);
|
||||
}
|
||||
|
||||
// Should be called after SDL_RenderPresent, when Steam overlay has had the chance to be drawn.
|
||||
void OverlayPostRenderCheck()
|
||||
{
|
||||
ReadCentrePixel(&_pixelAfterOverlay);
|
||||
|
||||
// Detect an active Steam overlay by checking if the center pixel is changed by the gray fade.
|
||||
// Will not be triggered by applications rendering to corners, like FRAPS, MSI Afterburner and Friends popups.
|
||||
bool newOverlayActive = _pixelBeforeOverlay != _pixelAfterOverlay;
|
||||
|
||||
// Toggle game pause state consistently with base pause state
|
||||
if (!_overlayActive && newOverlayActive)
|
||||
{
|
||||
_pausedBeforeOverlay = gGamePaused & GAME_PAUSED_NORMAL;
|
||||
if (!_pausedBeforeOverlay)
|
||||
{
|
||||
pause_toggle();
|
||||
}
|
||||
}
|
||||
else if (_overlayActive && !newOverlayActive && !_pausedBeforeOverlay)
|
||||
{
|
||||
pause_toggle();
|
||||
}
|
||||
|
||||
_overlayActive = newOverlayActive;
|
||||
}
|
||||
};
|
||||
|
||||
IDrawingEngine * DrawingEngineFactory::CreateSoftware()
|
||||
|
||||
@@ -171,39 +171,6 @@ void platform_get_closest_resolution(int inWidth, int inHeight, int *outWidth, i
|
||||
}
|
||||
}
|
||||
|
||||
static void read_center_pixel(int width, int height, uint32 *pixel) {
|
||||
SDL_Rect centerPixelRegion = {width / 2, height / 2, 1, 1};
|
||||
SDL_RenderReadPixels(gRenderer, ¢erPixelRegion, SDL_PIXELFORMAT_RGBA8888, pixel, sizeof(uint32));
|
||||
}
|
||||
|
||||
// Should be called before SDL_RenderPresent to capture frame buffer before Steam overlay is drawn.
|
||||
static void overlay_pre_render_check(int width, int height) {
|
||||
read_center_pixel(width, height, &_pixelBeforeOverlay);
|
||||
}
|
||||
|
||||
// Should be called after SDL_RenderPresent, when Steam overlay has had the chance to be drawn.
|
||||
static void overlay_post_render_check(int width, int height) {
|
||||
static bool overlayActive = false;
|
||||
static bool pausedBeforeOverlay = false;
|
||||
|
||||
read_center_pixel(width, height, &_pixelAfterOverlay);
|
||||
|
||||
// Detect an active Steam overlay by checking if the center pixel is changed by the gray fade.
|
||||
// Will not be triggered by applications rendering to corners, like FRAPS, MSI Afterburner and Friends popups.
|
||||
bool newOverlayActive = _pixelBeforeOverlay != _pixelAfterOverlay;
|
||||
|
||||
// Toggle game pause state consistently with base pause state
|
||||
if (!overlayActive && newOverlayActive) {
|
||||
pausedBeforeOverlay = gGamePaused & GAME_PAUSED_NORMAL;
|
||||
|
||||
if (!pausedBeforeOverlay) pause_toggle();
|
||||
} else if (overlayActive && !newOverlayActive && !pausedBeforeOverlay) {
|
||||
pause_toggle();
|
||||
}
|
||||
|
||||
overlayActive = newOverlayActive;
|
||||
}
|
||||
|
||||
void platform_draw()
|
||||
{
|
||||
if (!gOpenRCT2Headless) {
|
||||
|
||||
Reference in New Issue
Block a user