From 2fa0c7977a232f9bf60b0085618bc1322edc4db6 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 4 Jun 2016 14:44:05 +0100 Subject: [PATCH] add OpenGL drawing engine with FillRect impl --- openrct2.vcxproj | 1 + src/drawing/IDrawingEngine.h | 1 + src/drawing/NewDrawing.cpp | 3 +- src/drawing/engines/OpenGLDrawingEngine.cpp | 324 ++++++++++++++++++++ src/drawing/rect.c | 2 +- src/drawing/sprite.c | 2 +- src/platform/shared.c | 2 +- src/ride/ride.c | 2 +- 8 files changed, 332 insertions(+), 5 deletions(-) create mode 100644 src/drawing/engines/OpenGLDrawingEngine.cpp diff --git a/openrct2.vcxproj b/openrct2.vcxproj index af74b6c92e..a93969114f 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -42,6 +42,7 @@ + diff --git a/src/drawing/IDrawingEngine.h b/src/drawing/IDrawingEngine.h index 91d1c7a0fa..3dad79b63b 100644 --- a/src/drawing/IDrawingEngine.h +++ b/src/drawing/IDrawingEngine.h @@ -40,6 +40,7 @@ interface IDrawingEngine namespace DrawingEngineFactory { IDrawingEngine * CreateSoftware(); + IDrawingEngine * CreateOpenGL(); }; interface IRainDrawer diff --git a/src/drawing/NewDrawing.cpp b/src/drawing/NewDrawing.cpp index 0565df03dd..26e28af42b 100644 --- a/src/drawing/NewDrawing.cpp +++ b/src/drawing/NewDrawing.cpp @@ -29,7 +29,8 @@ extern "C" void drawing_engine_init() { assert(_drawingEngine == nullptr); - _drawingEngine = DrawingEngineFactory::CreateSoftware(); + // _drawingEngine = DrawingEngineFactory::CreateSoftware(); + _drawingEngine = DrawingEngineFactory::CreateOpenGL(); _drawingEngine->Initialise(gWindow); } diff --git a/src/drawing/engines/OpenGLDrawingEngine.cpp b/src/drawing/engines/OpenGLDrawingEngine.cpp new file mode 100644 index 0000000000..859d825d23 --- /dev/null +++ b/src/drawing/engines/OpenGLDrawingEngine.cpp @@ -0,0 +1,324 @@ +#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 + +#ifdef __WINDOWS__ + #include + #pragma comment(lib, "opengl32.lib") +#endif + +#include +#include + +#include "../../core/Math.hpp" +#include "../../core/Memory.hpp" +#include "../IDrawingContext.h" +#include "../IDrawingEngine.h" +#include "../Rain.h" + +extern "C" +{ + #include "../../config.h" + #include "../drawing.h" + #include "../../interface/window.h" +} + +class OpenGLDrawingEngine; + +struct vec4f +{ + union { float x; float s; float r; }; + union { float y; float t; float g; }; + union { float z; float p; float b; }; + union { float w; float q; float a; }; +}; + +class OpenGLDrawingContext : public IDrawingContext +{ +private: + OpenGLDrawingEngine * _engine; + rct_drawpixelinfo * _dpi; + + sint32 _offsetX; + sint32 _offsetY; + sint32 _clipLeft; + sint32 _clipTop; + sint32 _clipRight; + sint32 _clipBottom; + +public: + OpenGLDrawingContext(OpenGLDrawingEngine * engine); + ~OpenGLDrawingContext() override; + + IDrawingEngine * GetEngine() override; + + void Clear(uint32 colour) override; + void FillRect(uint32 colour, sint32 x, sint32 y, sint32 w, sint32 h) override; + void DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) override; + void DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) override; + void DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) override; + + void SetDPI(rct_drawpixelinfo * dpi); +}; + +class OpenGLDrawingEngine : public IDrawingEngine +{ +private: + SDL_Window * _window = nullptr; + SDL_GLContext _context; + + uint32 _width = 0; + uint32 _height = 0; + uint32 _pitch = 0; + size_t _bitsSize = 0; + uint8 * _bits = nullptr; + + rct_drawpixelinfo _bitsDPI = { 0 }; + + OpenGLDrawingContext * _drawingContext; + +public: + vec4f GLPalette[256]; + + OpenGLDrawingEngine() + { + _drawingContext = new OpenGLDrawingContext(this); + } + + ~OpenGLDrawingEngine() override + { + delete _drawingContext; + delete _bits; + + SDL_GL_DeleteContext(_context); + } + + void Initialise(SDL_Window * window) override + { + _window = window; + + _context = SDL_GL_CreateContext(_window); + SDL_GL_MakeCurrent(_window, _context); + } + + void Resize(uint32 width, uint32 height) override + { + ConfigureBits(width, height, width); + + glViewport(0, 0, (GLsizei)width, (GLsizei)height); + } + + void SetPalette(SDL_Color * palette) override + { + for (int i = 0; i < 256; i++) + { + SDL_Color colour = palette[i]; + GLPalette[i] = { colour.r / 255.0f, + colour.g / 255.0f, + colour.b / 255.0f, + colour.a / 255.0f }; + } + } + + void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) override + { + } + + void Draw() override + { + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION_MATRIX); + glLoadIdentity(); + glOrtho(0, _width, _height, 0, -1.0, 1.0); + + glMatrixMode(GL_MODELVIEW_MATRIX); + glLoadIdentity(); + glScalef(1, -1.0f, 0); + glTranslatef(-1.0f, -1.0f, 0); + glScalef(2.0f / _width, 2.0f / _height, 0); + + gfx_redraw_screen_rect(0, 0, _width - 1, _height - 1); + window_update_all_viewports(); + gfx_redraw_screen_rect(0, 0, _width - 1, _height - 1); + window_update_all(); + + rct2_draw(); + Display(); + } + + IDrawingContext * GetDrawingContext(rct_drawpixelinfo * dpi) override + { + _drawingContext->SetDPI(dpi); + return _drawingContext; + } + + rct_drawpixelinfo * GetDPI() + { + return &_bitsDPI; + } + +private: + + void ConfigureBits(uint32 width, uint32 height, uint32 pitch) + { + size_t newBitsSize = pitch * height; + uint8 * newBits = new uint8[newBitsSize]; + if (_bits == nullptr) + { + Memory::Set(newBits, 0, newBitsSize); + } + else + { + if (_pitch == pitch) + { + Memory::Copy(newBits, _bits, Math::Min(_bitsSize, newBitsSize)); + } + else + { + uint8 * src = _bits; + uint8 * dst = newBits; + + uint32 minWidth = Math::Min(_width, width); + uint32 minHeight = Math::Min(_height, height); + for (uint32 y = 0; y < minHeight; y++) + { + Memory::Copy(dst, src, minWidth); + if (pitch - minWidth > 0) + { + Memory::Set(dst + minWidth, 0, pitch - minWidth); + } + src += _pitch; + dst += pitch; + } + } + delete _bits; + } + + _bits = newBits; + _bitsSize = newBitsSize; + _width = width; + _height = height; + _pitch = pitch; + + rct_drawpixelinfo * dpi = &_bitsDPI; + dpi->bits = _bits; + dpi->x = 0; + dpi->y = 0; + dpi->width = width; + dpi->height = height; + dpi->pitch = _pitch - width; + + gScreenDPI = *dpi; + } + + void Display() + { + SDL_GL_SwapWindow(_window); + } +}; + +IDrawingEngine * DrawingEngineFactory::CreateOpenGL() +{ + return new OpenGLDrawingEngine(); +} + +OpenGLDrawingContext::OpenGLDrawingContext(OpenGLDrawingEngine * engine) +{ + _engine = engine; +} + +OpenGLDrawingContext::~OpenGLDrawingContext() +{ + +} + +IDrawingEngine * OpenGLDrawingContext::GetEngine() +{ + return _engine; +} + +void OpenGLDrawingContext::Clear(uint32 colour) +{ +} + +void OpenGLDrawingContext::FillRect(uint32 colour, sint32 left, sint32 top, sint32 right, sint32 bottom) +{ + vec4f paletteColour = _engine->GLPalette[colour & 0xFF]; + + if (left > right) + { + left ^= right; + right ^= left; + left ^= right; + } + if (top > bottom) + { + top ^= bottom; + bottom ^= top; + top ^= bottom; + } + + left += _offsetX; + top += _offsetY; + right += _offsetX; + bottom += _offsetY; + + left = Math::Max(left, _clipLeft); + top = Math::Max(top, _clipTop); + right = Math::Min(right, _clipRight); + bottom = Math::Min(bottom, _clipBottom); + + glColor3f(paletteColour.r, paletteColour.g, paletteColour.b); + glBegin(GL_QUADS); + glVertex2i(left, top); + glVertex2i(left, bottom); + glVertex2i(right, bottom); + glVertex2i(right, top); + glEnd(); +} + +void OpenGLDrawingContext::DrawSprite(uint32 image, sint32 x, sint32 y, uint32 tertiaryColour) +{ +} + +void OpenGLDrawingContext::DrawSpritePaletteSet(uint32 image, sint32 x, sint32 y, uint8 * palette, uint8 * unknown) +{ +} + +void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskImage, uint32 colourImage) +{ +} + +void OpenGLDrawingContext::SetDPI(rct_drawpixelinfo * dpi) +{ + rct_drawpixelinfo * screenDPI = _engine->GetDPI(); + size_t bitsSize = (size_t)screenDPI->height * (size_t)(screenDPI->width + screenDPI->pitch); + size_t bitsOffset = (size_t)(dpi->bits - screenDPI->bits); + + assert(bitsOffset < bitsSize); + + _clipLeft = bitsOffset % (screenDPI->width + screenDPI->pitch); + _clipTop = bitsOffset / (screenDPI->width + screenDPI->pitch); + _clipRight = _clipLeft + dpi->width; + _clipBottom = _clipTop + dpi->height; + _offsetX = _clipLeft + dpi->x; + _offsetY = _clipTop + dpi->y; + + _dpi = dpi; +} diff --git a/src/drawing/rect.c b/src/drawing/rect.c index 4e9ffb6c67..1163fb7500 100644 --- a/src/drawing/rect.c +++ b/src/drawing/rect.c @@ -53,7 +53,7 @@ void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, short left, short top, short ri colour = colour | 0x2000000; //Transparent if (flags & no_border) { - gfx_fill_rect(dpi, left, top, bottom, right, colour); + gfx_fill_rect(dpi, left, top, right, bottom, colour); } else if (flags & pressed) { // Draw outline of box gfx_fill_rect(dpi, left, top, left, bottom, colour + 1); diff --git a/src/drawing/sprite.c b/src/drawing/sprite.c index 596a13a6ff..3fb9dfed32 100644 --- a/src/drawing/sprite.c +++ b/src/drawing/sprite.c @@ -354,7 +354,7 @@ void FASTCALL gfx_draw_sprite_software(rct_drawpixelinfo *dpi, int image_id, int //For backwards compatibility RCT2_GLOBAL(0x9ABDA4, uint8*) = palette_pointer; - gfx_draw_sprite_palette_set(dpi, image_id, x, y, palette_pointer, unknown_pointer); + gfx_draw_sprite_palette_set_software(dpi, image_id, x, y, palette_pointer, unknown_pointer); } /* diff --git a/src/platform/shared.c b/src/platform/shared.c index 8f710085ab..889325a36c 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -640,7 +640,7 @@ static void platform_create_window() // Create window in window first rather than fullscreen so we have the display the window is on first gWindow = SDL_CreateWindow( - "OpenRCT2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_RESIZABLE + "OpenRCT2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL ); if (!gWindow) { diff --git a/src/ride/ride.c b/src/ride/ride.c index 9d6a0a2f30..efe8f7af7c 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -6923,7 +6923,7 @@ void set_vehicle_type_image_max_sizes(rct_ride_entry_vehicle* vehicle_type, int }; for (int i = 0; i < num_images; ++i){ - gfx_draw_sprite(&dpi, vehicle_type->base_image_id + i, 0, 0, 0); + gfx_draw_sprite_software(&dpi, vehicle_type->base_image_id + i, 0, 0, 0); } int al = -1; for (int i = 99; i != 0; --i){