route old functions to new drawing interface

- hardware display temporarily removed
- rain, fps and other non-window elements not drawn
This commit is contained in:
Ted John 2016-06-02 23:53:38 +01:00
parent 2de332369c
commit 3da57d0865
8 changed files with 150 additions and 364 deletions

View File

@ -45,6 +45,7 @@
<ClCompile Include="src\drawing\engines\SoftwareDrawingEngine.cpp" />
<ClCompile Include="src\drawing\font.c" />
<ClCompile Include="src\drawing\line.c" />
<ClCompile Include="src\drawing\NewDrawing.cpp" />
<ClCompile Include="src\drawing\rain.c" />
<ClCompile Include="src\drawing\rect.c" />
<ClCompile Include="src\drawing\scrolling_text.c" />
@ -337,6 +338,7 @@
<ClInclude Include="src\drawing\font.h" />
<ClInclude Include="src\drawing\IDrawingContext.h" />
<ClInclude Include="src\drawing\IDrawingEngine.h" />
<ClInclude Include="src\drawing\NewDrawing.h" />
<ClInclude Include="src\editor.h" />
<ClInclude Include="src\game.h" />
<ClInclude Include="src\hook.h" />

View File

@ -26,7 +26,13 @@ interface IDrawingEngine
virtual void Initialise(SDL_Window * window) abstract;
virtual void Resize(uint32 width, uint32 height) abstract;
virtual void SetPalette(SDL_Color * colours) abstract;
virtual void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) abstract;
virtual void Draw() abstract;
};
namespace DrawingEngineFactory
{
IDrawingEngine * CreateSoftware();
};

View File

@ -0,0 +1,72 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include "IDrawingEngine.h"
extern "C"
{
#include "../platform/platform.h"
}
static IDrawingEngine * _drawingEngine = nullptr;
extern "C"
{
void drawing_engine_init()
{
assert(_drawingEngine == nullptr);
_drawingEngine = DrawingEngineFactory::CreateSoftware();
_drawingEngine->Initialise(gWindow);
}
void drawing_engine_resize()
{
if (_drawingEngine == nullptr)
{
drawing_engine_init();
}
_drawingEngine->Resize(gScreenWidth, gScreenHeight);
}
void drawing_engine_set_palette(SDL_Color * colours)
{
_drawingEngine->SetPalette(colours);
}
void drawing_engine_draw()
{
_drawingEngine->Draw();
}
void drawing_engine_dispose()
{
delete _drawingEngine;
_drawingEngine = nullptr;
}
void gfx_set_dirty_blocks(sint16 left, sint16 top, sint16 right, sint16 bottom)
{
if (_drawingEngine != nullptr)
{
_drawingEngine->Invalidate(left, top, right, bottom);
}
}
void gfx_draw_all_dirty_blocks()
{
}
}

33
src/drawing/NewDrawing.h Normal file
View File

@ -0,0 +1,33 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#ifdef _cplusplus
extern "C"
{
#endif
void drawing_engine_init();
void drawing_engine_resize();
void drawing_engine_set_palette(SDL_Color * colours);
void drawing_engine_draw();
void drawing_engine_dispose();
#ifdef _cplusplus
}
#endif

View File

@ -201,130 +201,6 @@ void gfx_invalidate_screen()
gfx_set_dirty_blocks(0, 0, gScreenWidth, gScreenHeight);
}
uint8* gfx_get_dirty_blocks()
{
int size = _screenDirtyBlockColumns * _screenDirtyBlockRows;
if (_screenDirtyBlocksSize != size) {
if (_screenDirtyBlocks) {
_screenDirtyBlocks = realloc(_screenDirtyBlocks, size);
} else {
_screenDirtyBlocks = malloc(size);
}
_screenDirtyBlocksSize = size;
}
return _screenDirtyBlocks;
}
/**
*
* rct2: 0x006E732D
* left (ax)
* top (bx)
* right (dx)
* bottom (bp)
*/
void gfx_set_dirty_blocks(sint16 left, sint16 top, sint16 right, sint16 bottom)
{
int x, y;
uint8 *screenDirtyBlocks = gfx_get_dirty_blocks();
left = max(left, 0);
top = max(top, 0);
right = min(right, gScreenWidth);
bottom = min(bottom, gScreenHeight);
if (left >= right)
return;
if (top >= bottom)
return;
right--;
bottom--;
left >>= _screenDirtyBlockShiftX;
right >>= _screenDirtyBlockShiftX;
top >>= _screenDirtyBlockShiftY;
bottom >>= _screenDirtyBlockShiftY;
uint32 dirtyBlockColumns = _screenDirtyBlockColumns;
for (y = top; y <= bottom; y++) {
uint32 yOffset = y * dirtyBlockColumns;
for (x = left; x <= right; x++) {
screenDirtyBlocks[yOffset + x] = 0xFF;
}
}
}
/**
*
* rct2: 0x006E73BE
*/
void gfx_draw_all_dirty_blocks()
{
uint32 x, y, xx, yy, columns, rows;
uint32 dirtyBlockColumns = _screenDirtyBlockColumns;
uint32 dirtyBlockRows = _screenDirtyBlockRows;
uint8 *screenDirtyBlocks = gfx_get_dirty_blocks();
for (x = 0; x < dirtyBlockColumns; x++) {
for (y = 0; y < dirtyBlockRows; y++) {
uint32 yOffset = y * dirtyBlockColumns;
if (screenDirtyBlocks[yOffset + x] == 0) {
continue;
}
// Determine columns
for (xx = x; xx < dirtyBlockColumns; xx++) {
if (screenDirtyBlocks[yOffset + xx] == 0) {
break;
}
}
columns = xx - x;
// Check rows
for (yy = y; yy < dirtyBlockRows; yy++) {
uint32 yyOffset = yy * dirtyBlockColumns;
for (xx = x; xx < x + columns; xx++) {
if (screenDirtyBlocks[yyOffset + xx] == 0) {
goto endRowCheck;
}
}
}
endRowCheck:
rows = yy - y;
gfx_draw_dirty_blocks(x, y, columns, rows);
}
}
}
static void gfx_draw_dirty_blocks(int x, int y, int columns, int rows)
{
uint32 left, top, right, bottom;
uint32 dirtyBlockColumns = _screenDirtyBlockColumns;
uint8 *screenDirtyBlocks = gfx_get_dirty_blocks();
// Unset dirty blocks
for (top = y; top < y + (uint32)rows; top++) {
uint32 topOffset = top * dirtyBlockColumns;
for (left = x; left < x + (uint32)columns; left++) {
screenDirtyBlocks[topOffset + left] = 0;
}
}
// Determine region in pixels
left = max(0, x * _screenDirtyBlockWidth);
top = max(0, y * _screenDirtyBlockHeight);
right = min((uint32)gScreenWidth, left + (columns * _screenDirtyBlockWidth));
bottom = min((uint32)gScreenHeight, top + (rows * _screenDirtyBlockHeight));
if (right <= left || bottom <= top) {
return;
}
// Draw region
gfx_redraw_screen_rect(left, top, right, bottom);
}
/**
*
* rct2: 0x006E7499

View File

@ -191,4 +191,6 @@ int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrolling
void gfx_configure_dirty_grid();
#include "NewDrawing.h"
#endif

View File

@ -14,13 +14,13 @@
*****************************************************************************/
#pragma endregion
#include "../../config.h"
#include "../../core/Math.hpp"
#include "../../core/Memory.hpp"
#include "../IDrawingEngine.h"
extern "C"
{
#include "../../config.h"
#include "../drawing.h"
}
@ -104,6 +104,22 @@ public:
ConfigureBits(width, height, _surface->pitch);
}
void SetPalette(SDL_Color * palette) override
{
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, gPalette, 0, 256))
{
log_fatal("SDL_SetPaletteColors failed %s", SDL_GetError());
exit(1);
}
}
void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) override
{
left = Math::Max(left, 0);
@ -341,3 +357,8 @@ private:
}
}
};
IDrawingEngine * DrawingEngineFactory::CreateSoftware()
{
return new SoftwareDrawingEngine();
}

View File

@ -60,16 +60,6 @@ bool gHardwareDisplay;
bool gSteamOverlayActive = false;
static SDL_Surface *_surface = NULL;
static SDL_Surface *_RGBASurface = NULL;
static SDL_Palette *_palette = NULL;
static void *_screenBuffer;
static int _screenBufferSize;
static int _screenBufferWidth;
static int _screenBufferHeight;
static int _screenBufferPitch;
static SDL_Cursor* _cursors[CURSOR_COUNT];
static const int _fullscreen_modes[] = { 0, SDL_WINDOW_FULLSCREEN, SDL_WINDOW_FULLSCREEN_DESKTOP };
static unsigned int _lastGestureTimestamp;
@ -82,8 +72,6 @@ static void platform_create_window();
static void platform_load_cursors();
static void platform_unload_cursors();
static void platform_refresh_screenbuffer(int width, int height, int pitch);
int resolution_sort_func(const void *pa, const void *pb)
{
const resolution *a = (resolution*)pa;
@ -219,96 +207,8 @@ static void overlay_post_render_check(int width, int height) {
void platform_draw()
{
int width = gScreenWidth;
int height = gScreenHeight;
if (!gOpenRCT2Headless) {
if (gHardwareDisplay) {
void *pixels;
int pitch;
if (SDL_LockTexture(gBufferTexture, NULL, &pixels, &pitch) == 0) {
uint8 *src = (uint8*)_screenBuffer;
int padding = pitch - (width * 4);
if (pitch == width * 4) {
uint32 *dst = pixels;
for (int i = width * height; i > 0; i--) { *dst++ = *(uint32 *)(&gPaletteHWMapped[*src++]); }
}
else
if (pitch == (width * 2) + padding) {
uint16 *dst = pixels;
for (int y = height; y > 0; y--) {
for (int x = width; x > 0; x--) {
const uint8 lower = *(uint8 *)(&gPaletteHWMapped[*src++]);
const uint8 upper = *(uint8 *)(&gPaletteHWMapped[*src++]);
*dst++ = (lower << 8) | upper;
}
dst = (uint16*)(((uint8 *)dst) + padding);
}
}
else
if (pitch == width + padding) {
uint8 *dst = pixels;
for (int y = height; y > 0; y--) {
for (int x = width; x > 0; x--) { *dst++ = *(uint8 *)(&gPaletteHWMapped[*src++]); }
dst += padding;
}
}
SDL_UnlockTexture(gBufferTexture);
}
SDL_RenderCopy(gRenderer, gBufferTexture, NULL, NULL);
if (gSteamOverlayActive && gConfigGeneral.steam_overlay_pause) {
overlay_pre_render_check(width, height);
}
SDL_RenderPresent(gRenderer);
if (gSteamOverlayActive && gConfigGeneral.steam_overlay_pause) {
overlay_post_render_check(width, height);
}
}
else {
// Lock the surface before setting its pixels
if (SDL_MUSTLOCK(_surface)) {
if (SDL_LockSurface(_surface) < 0) {
log_error("locking failed %s", SDL_GetError());
return;
}
}
// Copy pixels from the virtual screen buffer to the surface
memcpy(_surface->pixels, _screenBuffer, _surface->pitch * _surface->h);
// Unlock the surface
if (SDL_MUSTLOCK(_surface))
SDL_UnlockSurface(_surface);
// Copy the surface to the window
if (gConfigGeneral.window_scale == 1 || gConfigGeneral.window_scale <= 0)
{
if (SDL_BlitSurface(_surface, NULL, SDL_GetWindowSurface(gWindow), NULL)) {
log_fatal("SDL_BlitSurface %s", SDL_GetError());
exit(1);
}
} else {
// first blit to rgba surface to change the pixel format
if (SDL_BlitSurface(_surface, NULL, _RGBASurface, NULL)) {
log_fatal("SDL_BlitSurface %s", SDL_GetError());
exit(1);
}
// then scale to window size. Without changing to RGBA first, SDL complains
// about blit configurations being incompatible.
if (SDL_BlitScaled(_RGBASurface, NULL, SDL_GetWindowSurface(gWindow), NULL)) {
log_fatal("SDL_BlitScaled %s", SDL_GetError());
exit(1);
}
}
if (SDL_UpdateWindowSurface(gWindow)) {
log_fatal("SDL_UpdateWindowSurface %s", SDL_GetError());
exit(1);
}
}
drawing_engine_draw();
}
}
@ -321,7 +221,7 @@ static void platform_resize(int width, int height)
gScreenWidth = dst_w;
gScreenHeight = dst_h;
platform_refresh_video();
drawing_engine_resize();
flags = SDL_GetWindowFlags(gWindow);
@ -392,11 +292,9 @@ static uint8 lerp(uint8 a, uint8 b, float t)
void platform_update_palette(const uint8* colours, int start_index, int num_colours)
{
SDL_Surface *surface;
int i;
colours += start_index * 4;
for (i = start_index; i < num_colours + start_index; i++) {
for (int i = start_index; i < num_colours + start_index; i++) {
gPalette[i].r = colours[2];
gPalette[i].g = colours[1];
gPalette[i].b = colours[0];
@ -416,16 +314,7 @@ void platform_update_palette(const uint8* colours, int start_index, int num_colo
}
if (!gOpenRCT2Headless && !gHardwareDisplay) {
surface = SDL_GetWindowSurface(gWindow);
if (!surface) {
log_fatal("SDL_GetWindowSurface failed %s", SDL_GetError());
exit(1);
}
if (_palette != NULL && SDL_SetPaletteColors(_palette, gPalette, 0, 256)) {
log_fatal("SDL_SetPaletteColors failed %s", SDL_GetError());
exit(1);
}
drawing_engine_set_palette(gPalette);
}
}
@ -528,15 +417,15 @@ void platform_process_messages()
// Apple sends touchscreen events for trackpads, so ignore these events on OS X
#ifndef __MACOSX__
case SDL_FINGERMOTION:
RCT2_GLOBAL(0x0142406C, int) = (int)(e.tfinger.x * _screenBufferWidth);
RCT2_GLOBAL(0x01424070, int) = (int)(e.tfinger.y * _screenBufferHeight);
RCT2_GLOBAL(0x0142406C, int) = (int)(e.tfinger.x * gScreenWidth);
RCT2_GLOBAL(0x01424070, int) = (int)(e.tfinger.y * gScreenHeight);
gCursorState.x = (int)(e.tfinger.x * _screenBufferWidth);
gCursorState.y = (int)(e.tfinger.y * _screenBufferHeight);
gCursorState.x = (int)(e.tfinger.x * gScreenWidth);
gCursorState.y = (int)(e.tfinger.y * gScreenHeight);
break;
case SDL_FINGERDOWN:
RCT2_GLOBAL(0x01424318, int) = (int)(e.tfinger.x * _screenBufferWidth);
RCT2_GLOBAL(0x0142431C, int) = (int)(e.tfinger.y * _screenBufferHeight);
RCT2_GLOBAL(0x01424318, int) = (int)(e.tfinger.x * gScreenWidth);
RCT2_GLOBAL(0x0142431C, int) = (int)(e.tfinger.y * gScreenHeight);
gCursorState.touchIsDouble = (!gCursorState.touchIsDouble
&& e.tfinger.timestamp - gCursorState.touchDownTimestamp < TOUCH_DOUBLE_TIMEOUT);
@ -554,8 +443,8 @@ void platform_process_messages()
gCursorState.touchDownTimestamp = e.tfinger.timestamp;
break;
case SDL_FINGERUP:
RCT2_GLOBAL(0x01424318, int) = (int)(e.tfinger.x * _screenBufferWidth);
RCT2_GLOBAL(0x0142431C, int) = (int)(e.tfinger.y * _screenBufferHeight);
RCT2_GLOBAL(0x01424318, int) = (int)(e.tfinger.x * gScreenWidth);
RCT2_GLOBAL(0x0142431C, int) = (int)(e.tfinger.y * gScreenHeight);
if (gCursorState.touchIsDouble) {
store_mouse_input(4);
@ -703,14 +592,7 @@ void platform_process_messages()
static void platform_close_window()
{
if (gWindow != NULL)
SDL_DestroyWindow(gWindow);
if (_surface != NULL)
SDL_FreeSurface(_surface);
if (_palette != NULL)
SDL_FreePalette(_palette);
if (_RGBASurface != NULL)
SDL_FreeSurface(_RGBASurface);
drawing_engine_dispose();
platform_unload_cursors();
}
@ -920,114 +802,6 @@ void platform_refresh_video()
log_verbose("HardwareDisplay: %s", gHardwareDisplay ? "true" : "false");
if (gHardwareDisplay) {
if (gRenderer == NULL)
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (gRenderer == NULL) {
log_warning("SDL_CreateRenderer failed: %s", SDL_GetError());
log_warning("Falling back to software rendering...");
gHardwareDisplay = false;
platform_refresh_video(); // try again without hardware rendering
return;
}
if (gBufferTexture != NULL)
SDL_DestroyTexture(gBufferTexture);
if (gBufferTextureFormat != NULL)
SDL_FreeFormat(gBufferTextureFormat);
SDL_RendererInfo rendererinfo;
SDL_GetRendererInfo(gRenderer, &rendererinfo);
Uint32 pixelformat = SDL_PIXELFORMAT_UNKNOWN;
for(unsigned int 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;
}
}
gBufferTexture = SDL_CreateTexture(gRenderer, pixelformat, SDL_TEXTUREACCESS_STREAMING, width, height);
Uint32 format;
SDL_QueryTexture(gBufferTexture, &format, 0, 0, 0);
gBufferTextureFormat = SDL_AllocFormat(format);
platform_refresh_screenbuffer(width, height, width);
// Load the current palette into the HWmapped version.
for (int i = 0; i < 256; ++i) {
gPaletteHWMapped[i] = SDL_MapRGB(gBufferTextureFormat, gPalette[i].r, gPalette[i].g, gPalette[i].b);
}
} else {
if (_surface != NULL)
SDL_FreeSurface(_surface);
if (_RGBASurface != NULL)
SDL_FreeSurface(_RGBASurface);
if (_palette != NULL)
SDL_FreePalette(_palette);
_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 || !_palette || !_RGBASurface) {
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);
}
platform_refresh_screenbuffer(width, height, _surface->pitch);
}
}
static void platform_refresh_screenbuffer(int width, int height, int pitch)
{
int newScreenBufferSize = pitch * height;
char *newScreenBuffer = (char*)malloc(newScreenBufferSize);
if (_screenBuffer == NULL) {
memset(newScreenBuffer, 0, newScreenBufferSize);
} else {
if (_screenBufferPitch == pitch) {
memcpy(newScreenBuffer, _screenBuffer, min(_screenBufferSize, newScreenBufferSize));
} else {
char *src = _screenBuffer;
char *dst = newScreenBuffer;
int minWidth = min(_screenBufferWidth, width);
int minHeight = min(_screenBufferHeight, height);
for (int y = 0; y < minHeight; y++) {
memcpy(dst, src, minWidth);
if (pitch - minWidth > 0)
memset(dst + minWidth, 0, pitch - minWidth);
src += _screenBufferPitch;
dst += pitch;
}
}
//if (newScreenBufferSize - _screenBufferSize > 0)
// memset((uint8*)newScreenBuffer + _screenBufferSize, 0, newScreenBufferSize - _screenBufferSize);
free(_screenBuffer);
}
_screenBuffer = newScreenBuffer;
_screenBufferSize = newScreenBufferSize;
_screenBufferWidth = width;
_screenBufferHeight = height;
_screenBufferPitch = pitch;
rct_drawpixelinfo *screenDPI = &gScreenDPI;
screenDPI->bits = _screenBuffer;
screenDPI->x = 0;
screenDPI->y = 0;
screenDPI->width = width;
screenDPI->height = height;
screenDPI->pitch = _screenBufferPitch - width;
gfx_configure_dirty_grid();
}
void platform_hide_cursor()