1 /*****************************************************************************
2 * Copyright (c) 2014-2020 OpenRCT2 developers
3 *
4 * For a complete list of all authors, please refer to contributors.md
5 * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6 *
7 * OpenRCT2 is licensed under the GNU General Public License version 3.
8 *****************************************************************************/
9
10 #include "NewDrawing.h"
11
12 #include "../Context.h"
13 #include "../config/Config.h"
14 #include "../drawing/Drawing.h"
15 #include "../interface/Screenshot.h"
16 #include "../localisation/StringIds.h"
17 #include "../paint/Painter.h"
18 #include "../platform/Platform2.h"
19 #include "../ui/UiContext.h"
20 #include "../world/Location.hpp"
21 #include "IDrawingContext.h"
22 #include "IDrawingEngine.h"
23
24 #include <cmath>
25
26 using namespace OpenRCT2;
27 using namespace OpenRCT2::Drawing;
28 using namespace OpenRCT2::Paint;
29 using namespace OpenRCT2::Ui;
30
31 rct_string_id DrawingEngineStringIds[] = {
32 STR_DRAWING_ENGINE_SOFTWARE,
33 STR_DRAWING_ENGINE_SOFTWARE_WITH_HARDWARE_DISPLAY,
34 STR_DRAWING_ENGINE_OPENGL,
35 };
36
drawing_engine_get_type()37 DrawingEngine drawing_engine_get_type()
38 {
39 auto context = GetContext();
40 return context->GetDrawingEngineType();
41 }
42
GetDrawingEngine()43 static IDrawingEngine* GetDrawingEngine()
44 {
45 IDrawingEngine* result = nullptr;
46 auto context = GetContext();
47 if (context != nullptr)
48 {
49 result = context->GetDrawingEngine();
50 }
51 return result;
52 }
53
drawing_engine_requires_new_window(DrawingEngine srcEngine,DrawingEngine dstEngine)54 bool drawing_engine_requires_new_window(DrawingEngine srcEngine, DrawingEngine dstEngine)
55 {
56 bool openGL = srcEngine == DrawingEngine::OpenGL || dstEngine == DrawingEngine::OpenGL;
57 return Platform::RequireNewWindow(openGL);
58 }
59
drawing_engine_init()60 void drawing_engine_init()
61 {
62 auto context = GetContext();
63 if (context != nullptr)
64 {
65 context->InitialiseDrawingEngine();
66 }
67 }
68
drawing_engine_resize()69 void drawing_engine_resize()
70 {
71 auto context = GetContext();
72 if (context != nullptr)
73 {
74 auto drawingEngine = context->GetDrawingEngine();
75 if (drawingEngine != nullptr)
76 {
77 auto uiContext = context->GetUiContext();
78 drawingEngine->Resize(uiContext->GetWidth(), uiContext->GetHeight());
79 }
80 }
81 }
82
drawing_engine_set_palette(const GamePalette & colours)83 void drawing_engine_set_palette(const GamePalette& colours)
84 {
85 auto context = GetContext();
86 if (context != nullptr)
87 {
88 auto drawingEngine = context->GetDrawingEngine();
89 if (drawingEngine != nullptr)
90 {
91 drawingEngine->SetPalette(colours);
92 }
93 }
94 }
95
drawing_engine_copy_rect(int32_t x,int32_t y,int32_t width,int32_t height,int32_t dx,int32_t dy)96 void drawing_engine_copy_rect(int32_t x, int32_t y, int32_t width, int32_t height, int32_t dx, int32_t dy)
97 {
98 auto context = GetContext();
99 if (context != nullptr)
100 {
101 auto drawingEngine = context->GetDrawingEngine();
102 if (drawingEngine != nullptr)
103 {
104 drawingEngine->CopyRect(x, y, width, height, dx, dy);
105 }
106 }
107 }
108
drawing_engine_dispose()109 void drawing_engine_dispose()
110 {
111 auto context = GetContext();
112 if (context != nullptr)
113 {
114 context->DisposeDrawingEngine();
115 }
116 }
117
drawing_engine_get_dpi()118 rct_drawpixelinfo* drawing_engine_get_dpi()
119 {
120 auto context = GetContext();
121 auto drawingEngine = context->GetDrawingEngine();
122 return drawingEngine->GetDrawingPixelInfo();
123 }
124
drawing_engine_has_dirty_optimisations()125 bool drawing_engine_has_dirty_optimisations()
126 {
127 bool result = false;
128 auto drawingEngine = GetDrawingEngine();
129 if (drawingEngine != nullptr)
130 {
131 result = (drawingEngine->GetFlags() & DEF_DIRTY_OPTIMISATIONS);
132 }
133 return result;
134 }
135
drawing_engine_invalidate_image(uint32_t image)136 void drawing_engine_invalidate_image(uint32_t image)
137 {
138 auto drawingEngine = GetDrawingEngine();
139 if (drawingEngine != nullptr)
140 {
141 drawingEngine->InvalidateImage(image);
142 }
143 }
144
drawing_engine_set_vsync(bool vsync)145 void drawing_engine_set_vsync(bool vsync)
146 {
147 auto drawingEngine = GetDrawingEngine();
148 if (drawingEngine != nullptr)
149 {
150 drawingEngine->SetVSync(vsync);
151 }
152 }
153
gfx_set_dirty_blocks(const ScreenRect & rect)154 void gfx_set_dirty_blocks(const ScreenRect& rect)
155 {
156 auto drawingEngine = GetDrawingEngine();
157 if (drawingEngine != nullptr)
158 {
159 drawingEngine->Invalidate(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
160 }
161 }
162
gfx_clear(rct_drawpixelinfo * dpi,uint8_t paletteIndex)163 void gfx_clear(rct_drawpixelinfo* dpi, uint8_t paletteIndex)
164 {
165 auto drawingEngine = dpi->DrawingEngine;
166 if (drawingEngine != nullptr)
167 {
168 IDrawingContext* dc = drawingEngine->GetDrawingContext();
169 dc->Clear(dpi, paletteIndex);
170 }
171 }
172
gfx_fill_rect(rct_drawpixelinfo * dpi,const ScreenRect & rect,int32_t colour)173 void gfx_fill_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, int32_t colour)
174 {
175 auto drawingEngine = dpi->DrawingEngine;
176 if (drawingEngine != nullptr)
177 {
178 IDrawingContext* dc = drawingEngine->GetDrawingContext();
179 dc->FillRect(dpi, colour, rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
180 }
181 }
182
gfx_filter_rect(rct_drawpixelinfo * dpi,const ScreenRect & rect,FilterPaletteID palette)183 void gfx_filter_rect(rct_drawpixelinfo* dpi, const ScreenRect& rect, FilterPaletteID palette)
184 {
185 auto drawingEngine = dpi->DrawingEngine;
186 if (drawingEngine != nullptr)
187 {
188 IDrawingContext* dc = drawingEngine->GetDrawingContext();
189 dc->FilterRect(dpi, palette, rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
190 }
191 }
192
gfx_draw_line(rct_drawpixelinfo * dpi,const ScreenLine & line,int32_t colour)193 void gfx_draw_line(rct_drawpixelinfo* dpi, const ScreenLine& line, int32_t colour)
194 {
195 auto drawingEngine = dpi->DrawingEngine;
196 if (drawingEngine != nullptr)
197 {
198 IDrawingContext* dc = drawingEngine->GetDrawingContext();
199 dc->DrawLine(dpi, colour, line);
200 }
201 }
202
gfx_draw_dashed_line(rct_drawpixelinfo * dpi,const ScreenLine & screenLine,const int32_t dashedLineSegmentLength,const int32_t color)203 void gfx_draw_dashed_line(
204 rct_drawpixelinfo* dpi, const ScreenLine& screenLine, const int32_t dashedLineSegmentLength, const int32_t color)
205 {
206 assert(dashedLineSegmentLength > 0);
207
208 const auto drawingEngine = dpi->DrawingEngine;
209 if (drawingEngine != nullptr)
210 {
211 constexpr int32_t precisionFactor = 1000;
212
213 const int32_t dashedLineLength = std::hypot(
214 screenLine.GetX2() - screenLine.GetX1(), screenLine.GetY2() - screenLine.GetY1());
215 const int32_t lineSegmentCount = dashedLineLength / dashedLineSegmentLength / 2;
216 if (lineSegmentCount == 0)
217 {
218 return;
219 }
220
221 const int32_t lineXDist = std::abs(screenLine.GetX2() - screenLine.GetX1());
222 const int32_t lineYDist = std::abs(screenLine.GetY2() - screenLine.GetY1());
223 const int32_t dxPrecise = precisionFactor * lineXDist / lineSegmentCount / 2;
224 const int32_t dyPrecise = precisionFactor * lineYDist / lineSegmentCount / 2;
225 IDrawingContext* dc = drawingEngine->GetDrawingContext();
226
227 for (int32_t i = 0, x, y; i < lineSegmentCount; ++i)
228 {
229 x = screenLine.GetX1() + dxPrecise * i * 2 / precisionFactor;
230 y = screenLine.GetY1() + dyPrecise * i * 2 / precisionFactor;
231 dc->DrawLine(dpi, color, { { x, y }, { x + dxPrecise / precisionFactor, y + dyPrecise / precisionFactor } });
232 }
233 }
234 }
235
gfx_draw_sprite(rct_drawpixelinfo * dpi,ImageId image_id,const ScreenCoordsXY & coords)236 void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, ImageId image_id, const ScreenCoordsXY& coords)
237 {
238 gfx_draw_sprite(dpi, image_id.ToUInt32(), coords, image_id.GetTertiary());
239 }
240
gfx_draw_sprite(rct_drawpixelinfo * dpi,int32_t image,const ScreenCoordsXY & coords,uint32_t tertiary_colour)241 void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, int32_t image, const ScreenCoordsXY& coords, uint32_t tertiary_colour)
242 {
243 auto drawingEngine = dpi->DrawingEngine;
244 if (drawingEngine != nullptr)
245 {
246 IDrawingContext* dc = drawingEngine->GetDrawingContext();
247 dc->DrawSprite(dpi, image, coords.x, coords.y, tertiary_colour);
248 }
249 }
250
gfx_draw_glyph(rct_drawpixelinfo * dpi,int32_t image,const ScreenCoordsXY & coords,const PaletteMap & paletteMap)251 void FASTCALL gfx_draw_glyph(rct_drawpixelinfo* dpi, int32_t image, const ScreenCoordsXY& coords, const PaletteMap& paletteMap)
252 {
253 auto drawingEngine = dpi->DrawingEngine;
254 if (drawingEngine != nullptr)
255 {
256 IDrawingContext* dc = drawingEngine->GetDrawingContext();
257 dc->DrawGlyph(dpi, image, coords.x, coords.y, paletteMap);
258 }
259 }
260
261 void FASTCALL
gfx_draw_sprite_raw_masked(rct_drawpixelinfo * dpi,const ScreenCoordsXY & coords,int32_t maskImage,int32_t colourImage)262 gfx_draw_sprite_raw_masked(rct_drawpixelinfo* dpi, const ScreenCoordsXY& coords, int32_t maskImage, int32_t colourImage)
263 {
264 auto drawingEngine = dpi->DrawingEngine;
265 if (drawingEngine != nullptr)
266 {
267 IDrawingContext* dc = drawingEngine->GetDrawingContext();
268 dc->DrawSpriteRawMasked(dpi, coords.x, coords.y, maskImage, colourImage);
269 }
270 }
271
gfx_draw_sprite_solid(rct_drawpixelinfo * dpi,int32_t image,const ScreenCoordsXY & coords,uint8_t colour)272 void FASTCALL gfx_draw_sprite_solid(rct_drawpixelinfo* dpi, int32_t image, const ScreenCoordsXY& coords, uint8_t colour)
273 {
274 auto drawingEngine = dpi->DrawingEngine;
275 if (drawingEngine != nullptr)
276 {
277 IDrawingContext* dc = drawingEngine->GetDrawingContext();
278 dc->DrawSpriteSolid(dpi, image, coords.x, coords.y, colour);
279 }
280 }
281
screenshot_dump()282 std::string screenshot_dump()
283 {
284 auto drawingEngine = GetDrawingEngine();
285 if (drawingEngine != nullptr)
286 {
287 return drawingEngine->Screenshot();
288 }
289 return "";
290 }
291