Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
GPUFrame.cpp
Go to the documentation of this file.
1#include "GPUFrame.hpp"
2#include "Display.hpp"
3#include "LegacyAssets.hpp"
4#include "LogicalViewport.hpp"
5
6#include <algorithm>
7#include <cmath>
8#include <limits>
9
10namespace
11{
13 double value,
14 Uint32 maximum)
15 {
16 const long long rounded = std::llround(value);
17
18 if (rounded <= 0)
19 {
20 return 0;
21 }
22
23 if (rounded >= static_cast<long long>(maximum))
24 {
25 return maximum;
26 }
27
28 return static_cast<Uint32>(rounded);
29 }
30}
31
33{
34 std::expected<World3DRenderStats, World3DRendererError> recordWorld3D(
37 const SequenceWorld3DSlot& world)
38 {
39 if (!world.view()) return World3DRenderStats{};
40 if (width > static_cast<Uint32>(std::numeric_limits<int>::max()) ||
41 height > static_cast<Uint32>(std::numeric_limits<int>::max()))
42 return std::unexpected(World3DRendererError{
44 "World3D target exceeds logical viewport range", {}, {}});
45 const auto rect = world.view()->viewport;
46 const auto transform = logicalviewport::makeWorld3DTransform(
47 static_cast<int>(width), static_cast<int>(height));
48 const auto pixels = logicalviewport::logicalToPixelRect(transform,
49 {static_cast<double>(rect.left), static_cast<double>(rect.top),
50 static_cast<double>(rect.right - rect.left),
51 static_cast<double>(rect.bottom - rect.top)});
52 const SDL_GPUViewport viewport{static_cast<float>(pixels.x),
53 static_cast<float>(pixels.y), static_cast<float>(pixels.width),
54 static_cast<float>(pixels.height), 0, 1};
55 return renderer.render(command, target, width, height, viewport, world);
56 }
57 bool present(
58 SDL_GPUDevice* device,
61 const SequenceWorld3DSlot* world,
64 {
65 if (device == nullptr || window == nullptr)
66 {
67 return false;
68 }
69
72
73 if (commandBuffer == nullptr)
74 {
75 return false;
76 }
77
79
80 Uint32 width = 0;
81 Uint32 height = 0;
82
85 window,
87 &width,
88 &height))
89 {
91 return false;
92 }
93
94 if (swapchainTexture != nullptr)
95 {
97
98 target.texture = swapchainTexture;
99
100 // Extend the optional menu palette into widescreen gutters.
101 // The authored UI projection and hit rectangles remain unchanged.
102 target.clear_color = backdrop;
103
104 target.load_op =
106
107 target.store_op =
109
110 target.cycle = true;
111
115 &target,
116 1,
117 nullptr
118 );
119
120 if (renderPass == nullptr)
121 {
123 return false;
124 }
125
127
128
129 // ------------------------------------------------
130 // Background du viewport 3D.
131 //
132 // PC3D/view.cpp original calcule :
133 //
134 // horizontalScale =
135 // backgroundWidth / viewportWidth
136 //
137 // verticalScale =
138 // backgroundHeight / viewportHeight
139 //
140 // puis effectue un stretch blit.
141 // ------------------------------------------------
142
143 const legacyassets::Texture2D& background =
145
146 if (background.texture != nullptr &&
148 {
150 display::stateReadOnly().viewportInUse);
152 static_cast<double>(logicalView.left),
153 static_cast<double>(logicalView.top),
154 static_cast<double>(logicalView.right - logicalView.left),
155 static_cast<double>(logicalView.bottom - logicalView.top)};
156
157
158 if (logicalDestination.width > 0.0 &&
159 logicalDestination.height > 0.0 &&
160 width <= static_cast<Uint32>(
161 std::numeric_limits<int>::max()) &&
162 height <= static_cast<Uint32>(
163 std::numeric_limits<int>::max()))
164 {
165 const auto transform =
167 static_cast<int>(width),
168 static_cast<int>(height)
169 );
170
171 const auto destination =
173 transform,
175 );
176
177 const Uint32 destinationX =
179
180 const Uint32 destinationY =
182
185 destination.x + destination.width,
186 width
187 );
188
191 destination.y + destination.height,
192 height
193 );
194
197
200
201
202 SDL_GPUBlitInfo blit{};
203
204 blit.source.texture =
205 background.texture;
206
207 blit.source.mip_level = 0;
208 blit.source.layer_or_depth_plane = 0;
209
210 blit.source.x = 0;
211 blit.source.y = 0;
212
213 blit.source.w =
214 background.width;
215
216 blit.source.h =
217 background.height;
218
219
220 blit.destination.texture =
222
223 blit.destination.mip_level = 0;
224 blit.destination.layer_or_depth_plane = 0;
225
226 blit.destination.x =
228
229 blit.destination.y =
231
232 blit.destination.w =
234
235 blit.destination.h =
237
238
239 // Le framebuffer a déjà été vidé en noir
240 // par le render pass précédent.
241 blit.load_op =
243
244 // Le nearest-neighbour conserve les pixels nets du
245 // bitmap 1999, y compris apres redimensionnement.
246 blit.filter =
248
249 blit.flip_mode =
251
252 // Le swapchain vient d'etre entierement vide en noir
253 // plus haut dans le meme command buffer. Un cycle ici
254 // basculerait vers un backing texture indefini, puis
255 // LOAD lirait ces donnees indefinies au lieu de garder
256 // les bandes letterbox noires.
257 blit.cycle = false;
258
259
260 // A subpixel background must not skip later render slots.
261 if (destinationWidth != 0 && destinationHeight != 0)
263 }
264 }
265
266 // Slot 1 follows the clear and the historical 3D background.
267 // LOAD in World3DRenderer preserves both and the letterbox bars.
268 if (renderer && world && world->view())
269 {
271 width, height, *renderer, *world);
272 if (!drawn)
273 {
274 // SDL forbids cancelling a command after swapchain acquire.
276 return SDL_SetError("World3D: %s", drawn.error().detail.c_str());
277 }
278 }
279 }
280
281 if (swapchainTexture && overlayRenderer && overlay)
282 {
283 const auto result = overlayRenderer->render(commandBuffer, swapchainTexture,
284 width, height, *overlay);
285 if (!result)
286 {
288 return SDL_SetError("World2D render: %s", result.error().c_str());
289 }
290 }
293 );
294 }
295}
296
std::uint32_t height
std::uint32_t width
unsigned index
Rect rect
std::uint16_t value
Definition Timers.cpp:16
const std::optional< World3DProjectionState > & view() const noexcept
engine::World3DRect worldViewport(Viewport3D viewport) noexcept
Definition Display.hpp:76
const State & stateReadOnly()
Definition Display.cpp:704
bool present(SDL_GPUDevice *device, SDL_Window *window, World3DRenderer *renderer, const SequenceWorld3DSlot *world, World2DRenderer *overlayRenderer, const SequenceWorld2DSlot *overlay, SDL_FColor backdrop)
Definition GPUFrame.cpp:57
std::expected< World3DRenderStats, World3DRendererError > recordWorld3D(SDL_GPUCommandBuffer *command, SDL_GPUTexture *target, Uint32 width, Uint32 height, World3DRenderer &renderer, const SequenceWorld3DSlot &world)
Definition GPUFrame.cpp:34
const Texture2D & background3D()
PixelRect logicalToPixelRect(const Transform &transform, const LogicalRect &logicalRect) noexcept
Transform makeWorld3DTransform(int targetWidth, int targetHeight) noexcept