Skip to content

Commit 5748777

Browse files
Rotation support
1 parent bfe1b0d commit 5748777

File tree

13 files changed

+168
-85
lines changed

13 files changed

+168
-85
lines changed

LibretroRT.FrontendComponents.Common/CoreCoordinator.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ private void UnregisterEvents()
8484
Core.PixelFormatChanged -= Renderer.PixelFormatChanged;
8585
Core.RenderVideoFrame -= Renderer.RenderVideoFrame;
8686
Core.TimingChanged -= Renderer.TimingChanged;
87+
Core.RotationChanged -= Renderer.RotationChanged;
8788
}
8889

8990
if (AudioPlayer != null)
@@ -107,6 +108,7 @@ private void RegisterEvents()
107108
Core.PixelFormatChanged += Renderer.PixelFormatChanged;
108109
Core.RenderVideoFrame += Renderer.RenderVideoFrame;
109110
Core.TimingChanged += Renderer.TimingChanged;
111+
Core.RotationChanged += Renderer.RotationChanged;
110112
}
111113

112114
if (AudioPlayer != null)

LibretroRT.FrontendComponents.Common/IRenderer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public interface IRenderer
66
{
77
void GeometryChanged(GameGeometry geometry);
88
void PixelFormatChanged(PixelFormats format);
9+
void RotationChanged(Rotations rotation);
910
void TimingChanged(SystemTiming timings);
1011
void RenderVideoFrame([ReadOnlyArray] byte[] frameBuffer, uint width, uint height, uint pitch);
1112
}

LibretroRT.FrontendComponents.Renderer/Renderer.cpp

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using namespace LibretroRT_FrontendComponents_Renderer;
66

77
using namespace Windows::Graphics::DirectX::Direct3D11;
8+
using namespace Windows::Foundation::Numerics;
89

910
Renderer::Renderer(CanvasAnimatedControl^ canvas) :
1011
Canvas(canvas),
@@ -60,6 +61,11 @@ void Renderer::PixelFormatChanged(PixelFormats format)
6061
PixelFormat = format;
6162
}
6263

64+
void Renderer::RotationChanged(Rotations rotation)
65+
{
66+
Rotation = rotation;
67+
}
68+
6369
void Renderer::TimingChanged(SystemTiming^ timings)
6470
{
6571
TimeSpan newTargetDuration = { 10000000.0 / timings->FPS };
@@ -138,16 +144,40 @@ void Renderer::CanvasDraw(ICanvasAnimatedControl^ sender, CanvasAnimatedDrawEven
138144
{
139145
auto drawingSession = args->DrawingSession;
140146
auto canvasSize = sender->Size;
147+
auto aspectRatio = Geometry->AspectRatio;
141148

142149
if (Win2DTexture == nullptr || RenderTargetViewport.Width <= 0 || RenderTargetViewport.Height <= 0)
143150
{
144151
return;
145152
}
146153

147-
critical_section::scoped_lock lock(RenderTargetCriticalSection);
154+
static const float piValue = 3.14159265358979323846f;
155+
auto rotAngle = 0.0f;
156+
switch (Rotation)
157+
{
158+
case Rotations::CCW90:
159+
rotAngle = -0.5f * piValue;
160+
aspectRatio = 1.0f / aspectRatio;
161+
break;
162+
case Rotations::CCW180:
163+
rotAngle = -piValue;
164+
break;
165+
case Rotations::CCW270:
166+
rotAngle = -1.5f * piValue;
167+
aspectRatio = 1.0f / aspectRatio;
168+
break;
169+
}
170+
171+
auto destinationSize = ComputeBestFittingSize(canvasSize, aspectRatio);
172+
auto scaleMatrix = make_float3x2_scale(destinationSize.Width, destinationSize.Height);
173+
auto rotMatrix = make_float3x2_rotation(rotAngle);
174+
auto transMatrix = make_float3x2_translation(0.5f * canvasSize.Width, 0.5f * canvasSize.Height);
175+
auto transformMatrix = rotMatrix * scaleMatrix * transMatrix;
148176

149-
auto destinationRect = ComputeBestFittingSize(canvasSize, Geometry->AspectRatio);
150-
drawingSession->DrawImage(Win2DTexture, destinationRect, RenderTargetViewport);
177+
critical_section::scoped_lock lock(RenderTargetCriticalSection);
178+
drawingSession->Transform = transformMatrix;
179+
drawingSession->DrawImage(Win2DTexture, Rect(-0.5f, -0.5f, 1.0f, 1.0f), RenderTargetViewport);
180+
drawingSession->Transform = float3x2::identity();
151181
}
152182

153183
void Renderer::CreateRenderTargets(CanvasAnimatedControl^ canvas, unsigned int width, unsigned int height)
@@ -198,22 +228,17 @@ void Renderer::DestroyRenderTargets()
198228
}
199229
}
200230

201-
Rect Renderer::ComputeBestFittingSize(Size viewportSize, float aspectRatio)
231+
Size Renderer::ComputeBestFittingSize(Size viewportSize, float aspectRatio)
202232
{
203233
auto candidateWidth = std::floor(viewportSize.Height * aspectRatio);
204-
if (viewportSize.Width >= candidateWidth)
205-
{
206-
Size size(candidateWidth, viewportSize.Height);
207-
Rect output(Point((viewportSize.Width - candidateWidth) / 2, 0), size);
208-
return output;
209-
}
210-
else
234+
Size size(candidateWidth, viewportSize.Height);
235+
if (viewportSize.Width < candidateWidth)
211236
{
212237
auto height = viewportSize.Width / aspectRatio;
213-
Size size(viewportSize.Width, height);
214-
Rect output(Point(0, (viewportSize.Height - height) / 2), size);
215-
return output;
238+
size = Size(viewportSize.Width, height);
216239
}
240+
241+
return size;
217242
}
218243

219244
unsigned int Renderer::ClosestGreaterPowerTwo(unsigned int value)

LibretroRT.FrontendComponents.Renderer/Renderer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace LibretroRT_FrontendComponents_Renderer
2525
virtual void GeometryChanged(GameGeometry^ geometry);
2626
virtual void PixelFormatChanged(PixelFormats format);
2727
virtual void TimingChanged(SystemTiming^ timings);
28+
virtual void RotationChanged(Rotations rotation);
2829

2930
virtual void RenderVideoFrame(const Array<byte>^ frameBuffer, unsigned int width, unsigned int height, unsigned int pitch);
3031
void CanvasDraw(ICanvasAnimatedControl^ sender, CanvasAnimatedDrawEventArgs^ args);
@@ -36,6 +37,7 @@ namespace LibretroRT_FrontendComponents_Renderer
3637

3738
GameGeometry^ Geometry = nullptr;
3839
PixelFormats PixelFormat = PixelFormats::FormatUknown;
40+
Rotations Rotation = Rotations::CCW0;
3941

4042
CanvasAnimatedControl^ const Canvas;
4143
ComPtr<ID3D11Device> Direct3DDevice;
@@ -50,7 +52,7 @@ namespace LibretroRT_FrontendComponents_Renderer
5052

5153
void CreateRenderTargets(CanvasAnimatedControl^ canvas, unsigned int width, unsigned int height);
5254
void DestroyRenderTargets();
53-
static Rect ComputeBestFittingSize(Size viewportSize, float aspectRatio);
55+
static Size ComputeBestFittingSize(Size viewportSize, float aspectRatio);
5456
static unsigned int ClosestGreaterPowerTwo(unsigned int value);
5557
};
5658
}

LibretroRT.FrontendComponents.Renderer/pch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include <math.h>
1111

12+
#include <WindowsNumerics.h>
13+
1214
// DirectX headers.
1315
#include <d3d11.h>
1416
#include <d2d1_3.h>

LibretroRT.FrontendComponents.Win2DRenderer/Win2DRenderer.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,5 +234,10 @@ public void TimingChanged(SystemTiming timings)
234234
{
235235
RenderPanel.TargetElapsedTime = TimeSpan.FromMilliseconds(1000.0 / timings.FPS);
236236
}
237+
238+
public void RotationChanged(Rotations rotation)
239+
{
240+
throw new NotImplementedException();
241+
}
237242
}
238243
}

LibretroRT/Enums.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ namespace LibretroRT
1010
FormatUknown,
1111
};
1212

13+
public enum class Rotations
14+
{
15+
CCW0 = 0,
16+
CCW90 = 1,
17+
CCW180 = 2,
18+
CCW270 = 3,
19+
};
20+
1321
public enum class InputTypes
1422
{
1523
DeviceIdJoypadB,

LibretroRT/ICore.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace LibretroRT
2121

2222
public delegate void GeometryChangedDelegate(GameGeometry^ geometry);
2323
public delegate void TimingChangedDelegate(SystemTiming^ timing);
24+
public delegate void RotationChangedDelegate(Rotations rotation);
2425
public delegate void PixelFormatChangedDelegate(PixelFormats format);
2526

2627
public delegate IRandomAccessStream^ OpenFileStreamDelegate(String^ path, FileAccessMode fileAccess);
@@ -44,7 +45,7 @@ namespace LibretroRT
4445
property PixelFormats PixelFormat { PixelFormats get(); }
4546
property GameGeometry^ Geometry { GameGeometry^ get(); }
4647
property SystemTiming^ Timing { SystemTiming^ get(); }
47-
48+
property Rotations Rotation { Rotations get(); }
4849
property unsigned int SerializationSize { unsigned int get(); }
4950

5051
bool LoadGame(String^ mainGameFilePath);
@@ -60,9 +61,10 @@ namespace LibretroRT
6061
event RenderAudioFramesDelegate^ RenderAudioFrames;
6162
property PollInputDelegate^ PollInput;
6263
property GetInputStateDelegate^ GetInputState;
64+
event PixelFormatChangedDelegate^ PixelFormatChanged;
6365
event GeometryChangedDelegate^ GeometryChanged;
6466
event TimingChangedDelegate^ TimingChanged;
65-
event PixelFormatChangedDelegate^ PixelFormatChanged;
67+
event RotationChangedDelegate^ RotationChanged;
6668
property OpenFileStreamDelegate^ OpenFileStream;
6769
property CloseFileStreamDelegate^ CloseFileStream;
6870
};

LibretroRT_Shared/Converter.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,24 @@ SystemTiming^ Converter::CToRTSystemTiming(const retro_system_timing & timing)
1919
return ref new SystemTiming(timing.fps, timing.sample_rate);
2020
}
2121

22+
Rotations Converter::CToRTRotation(const unsigned int rotation)
23+
{
24+
switch (rotation)
25+
{
26+
case 1:
27+
return Rotations::CCW90;
28+
break;
29+
case 2:
30+
return Rotations::CCW180;
31+
break;
32+
case 3:
33+
return Rotations::CCW270;
34+
break;
35+
}
36+
37+
return Rotations::CCW0;
38+
}
39+
2240
CoreOption^ Converter::RetroVariableToCoreOptionDescription(const std::string payload)
2341
{
2442
auto description = payload.substr(0, payload.find(';'));

LibretroRT_Shared/Converter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace LibretroRT_Shared
1515
public:
1616
static GameGeometry^ CToRTGameGeometry(const retro_game_geometry& geometry);
1717
static SystemTiming^ CToRTSystemTiming(const retro_system_timing& timing);
18+
static Rotations CToRTRotation(const unsigned int rotation);
1819
static CoreOption^ RetroVariableToCoreOptionDescription(const std::string payload);
1920
static PixelFormats ConvertToPixelFormat(enum retro_pixel_format format);
2021
static InputTypes ConvertToInputType(unsigned device, unsigned index, unsigned id);

LibretroRT_Shared/CoreBase.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ bool CoreBase::EnvironmentHandler(unsigned cmd, void *data)
181181
Geometry = Converter::CToRTGameGeometry(*dataPtr);
182182
return true;
183183
}
184+
case RETRO_ENVIRONMENT_SET_ROTATION:
185+
{
186+
auto dataPtr = reinterpret_cast<const unsigned int*>(data);
187+
Rotation = Converter::CToRTRotation(*dataPtr);
188+
return true;
189+
}
184190
case RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO:
185191
{
186192
auto dataPtr = reinterpret_cast<retro_system_av_info*>(data);
@@ -449,6 +455,8 @@ bool CoreBase::LoadGame(String^ mainGameFilePath)
449455
gameInfo.size = size;
450456
}
451457

458+
Rotation = Rotations::CCW0;
459+
452460
auto loadSuccessful = retro_load_game(&gameInfo);
453461
if (loadSuccessful)
454462
{

LibretroRT_Shared/CoreBase.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace LibretroRT_Shared
3131
PixelFormats pixelFormat;
3232
GameGeometry^ geometry;
3333
SystemTiming^ timing;
34+
Rotations rotation;
3435

3536
bool coreRequiresGameFilePath;
3637

@@ -104,6 +105,13 @@ namespace LibretroRT_Shared
104105
void set(SystemTiming^ value) sealed { timing = value; TimingChanged(timing); }
105106
}
106107

108+
virtual property Rotations Rotation
109+
{
110+
Rotations get() { return rotation; }
111+
private:
112+
void set(Rotations value) sealed { rotation = value; RotationChanged(rotation); }
113+
}
114+
107115
virtual property unsigned int SerializationSize { unsigned int get(); }
108116

109117
virtual event RenderVideoFrameDelegate^ RenderVideoFrame;
@@ -112,6 +120,7 @@ namespace LibretroRT_Shared
112120
virtual property GetInputStateDelegate^ GetInputState;
113121
virtual event GeometryChangedDelegate^ GeometryChanged;
114122
virtual event TimingChangedDelegate^ TimingChanged;
123+
virtual event RotationChangedDelegate^ RotationChanged;
115124
virtual event PixelFormatChangedDelegate^ PixelFormatChanged;
116125
virtual property OpenFileStreamDelegate^ OpenFileStream;
117126
virtual property CloseFileStreamDelegate^ CloseFileStream;

0 commit comments

Comments
 (0)