1 // blitter effects via SDL2
2 #include "burner.h"
3 #include "vid_support.h"
4 #include "vid_softfx.h"
5
6 #ifdef INCLUDE_SWITCHRES
7 #include <switchres_wrapper.h>
8 #endif
9
10 #include <SDL.h>
11 #include <SDL_image.h>
12
13 extern int vsync;
14 extern char videofiltering[3];
15
16 static unsigned char* VidMem = NULL;
17 extern SDL_Window* sdlWindow;
18 SDL_Renderer* sdlRenderer = NULL;
19 static SDL_Texture* sdlTexture = NULL;
20 static int nRotateGame = 0;
21 static bool bFlipped = false;
22 static SDL_Rect dstrect;
23 static SDL_Rect title_texture_rect;
24 static SDL_Rect dest_title_texture_rect;
25
26 static int screenh, screenw;
27 static char Windowtitle[512];
28
29
RenderMessage()30 void RenderMessage()
31 {
32 // First render anything that is key-held based
33 if (bAppDoFast)
34 {
35 inprint_shadowed(sdlRenderer, "FFWD", 10, 10);
36 }
37 if (bAppShowFPS)
38 {
39 if (bAppFullscreen)
40 {
41 inprint_shadowed(sdlRenderer, fpsstring, 10, 50);
42 }
43 else
44 {
45 sprintf(Windowtitle, "FBNeo - FPS: %s - %s - %s", fpsstring, BurnDrvGetTextA(DRV_NAME), BurnDrvGetTextA(DRV_FULLNAME));
46 SDL_SetWindowTitle(sdlWindow, Windowtitle);
47 }
48 }
49
50 if (messageFrames > 1)
51 {
52 inprint_shadowed(sdlRenderer, lastMessage, 10, 30);
53 messageFrames--;
54 }
55 }
56
Exit()57 static int Exit()
58 {
59 #ifdef INCLUDE_SWITCHRES
60 sr_deinit();
61 #endif
62 kill_inline_font(); //TODO: This is not supposed to be here
63 SDL_DestroyTexture(sdlTexture);
64 SDL_DestroyRenderer(sdlRenderer);
65 SDL_DestroyWindow(sdlWindow);
66
67 if (VidMem)
68 {
69 free(VidMem);
70 }
71 return 0;
72 }
73 static int display_w = 400, display_h = 300;
74
75
Init()76 static int Init()
77 {
78 int nMemLen = 0;
79 int GameAspectX = 4, GameAspectY = 3;
80
81 #ifdef INCLUDE_SWITCHRES
82 sr_mode srm;
83 #endif
84 if (SDL_Init(SDL_INIT_VIDEO) < 0)
85 {
86 printf("vid init error\n");
87 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s", SDL_GetError());
88 return 3;
89 }
90
91 nRotateGame = 0;
92
93 if (bDrvOkay)
94 {
95 // Get the game screen size
96 BurnDrvGetVisibleSize(&nVidImageWidth, &nVidImageHeight);
97 if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)
98 {
99 BurnDrvGetAspect(&GameAspectY, &GameAspectX);
100 }
101 else
102 {
103 BurnDrvGetAspect(&GameAspectX, &GameAspectY);
104 }
105
106 display_w = nVidImageWidth;
107 #ifdef INCLUDE_SWITCHRES
108 sr_init();
109 // Don't force 4:3 aspect-ratio, until there is a command-line switch
110 display_h = nVidImageHeight;
111 if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)
112 {
113 BurnDrvGetVisibleSize(&nVidImageHeight, &nVidImageWidth);
114 printf("Vertical\n");
115 nRotateGame = 1;
116 sr_set_rotation(1);
117 display_w = nVidImageWidth;
118 display_h = nVidImageHeight;
119 }
120 #else
121 display_h = nVidImageWidth * GameAspectY / GameAspectX;
122
123 if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)
124 {
125 BurnDrvGetVisibleSize(&nVidImageHeight, &nVidImageWidth);
126 printf("Vertical\n");
127 nRotateGame = 1;
128 display_w = nVidImageHeight * GameAspectX / GameAspectY;
129 display_h = nVidImageHeight;
130 }
131 #endif
132
133 if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED)
134 {
135 printf("Flipped\n");
136 bFlipped = 1;
137 }
138 }
139
140 sprintf(Windowtitle, "FBNeo - %s - %s", BurnDrvGetTextA(DRV_NAME), BurnDrvGetTextA(DRV_FULLNAME));
141
142 Uint32 screenFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE;
143
144 if (bAppFullscreen)
145 {
146 screenFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN_DESKTOP;
147 }
148
149 dstrect.y = 0;
150 dstrect.x = 0;
151 dstrect.h = display_h;
152 dstrect.w = display_w;
153
154 //Test refresh rate availability
155 printf("Game resolution: %dx%d@%f\n", nVidImageWidth, nVidImageHeight, nBurnFPS/100.0);
156
157 #ifdef INCLUDE_SWITCHRES
158 unsigned char interlace = 0; // FBN doesn't handle interlace yet, force it to disabled
159 double rr = nBurnFPS / 100.0;
160 sr_init_disp();
161 sr_add_mode(display_w, display_h, rr, interlace, &srm);
162 sr_switch_to_mode(display_w, display_h, rr, interlace, &srm);
163 #endif
164
165 if (nRotateGame)
166 {
167 sdlWindow = SDL_CreateWindow(
168 Windowtitle,
169 SDL_WINDOWPOS_CENTERED,
170 SDL_WINDOWPOS_CENTERED,
171 display_h,
172 display_w,
173 screenFlags
174 );
175 dstrect.y = (display_w - display_h) / 2;
176 dstrect.x = (display_h - display_w) / 2;
177 dstrect.h = display_h;
178 dstrect.w = display_w;
179
180 }
181 else
182 {
183 sdlWindow = SDL_CreateWindow(
184 Windowtitle,
185 SDL_WINDOWPOS_CENTERED,
186 SDL_WINDOWPOS_CENTERED,
187 display_w,
188 display_h,
189 screenFlags
190 );
191 }
192
193 // Check that the window was successfully created
194 if (sdlWindow == NULL)
195 {
196 // In the case that the window could not be made...
197 printf("Could not create window: %s\n", SDL_GetError());
198 return 1;
199 }
200
201 Uint32 renderflags = SDL_RENDERER_ACCELERATED;
202
203 if (vsync)
204 {
205 renderflags = renderflags | SDL_RENDERER_PRESENTVSYNC;
206 }
207
208 sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, renderflags);
209 if (sdlRenderer == NULL)
210 {
211 sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_SOFTWARE);
212 if (sdlRenderer == NULL)
213 {
214 // In the case that the window could not be made...
215 printf("Could not create renderer: %s\n", SDL_GetError());
216 return 1;
217 }
218 }
219
220 SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BLENDMODE_NONE);
221
222 nVidImageDepth = 32;
223
224 if (BurnDrvGetFlags() & BDF_16BIT_ONLY)
225 {
226 nVidImageDepth = 16;
227 printf("Forcing 16bit color\n");
228 }
229 printf("bbp: %d\n", nVidImageDepth);
230
231 if (bIntegerScale)
232 {
233 SDL_RenderSetIntegerScale(sdlRenderer, SDL_TRUE);
234 }
235
236 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, videofiltering);
237
238 printf("setting logical size w: %d h: %d\n", display_w, display_h);
239
240 if (nRotateGame)
241 {
242 SDL_RenderSetLogicalSize(sdlRenderer, display_h, display_w);
243 }
244 else
245 {
246 SDL_RenderSetLogicalSize(sdlRenderer, display_w, display_h);
247 }
248
249 // Force to scale * 2
250 // TODO
251 int w;
252 int h;
253 SDL_GetWindowSize(sdlWindow, &w, &h);
254 SDL_SetWindowSize(sdlWindow, w*2, h*2);
255 SDL_SetWindowPosition(sdlWindow, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
256
257 inrenderer(sdlRenderer); //TODO: this is not supposed to be here
258 prepare_inline_font(); // TODO: BAD
259 incolor(0xFFF000, 0);
260
261 if (nVidImageDepth == 32)
262 {
263 sdlTexture = SDL_CreateTexture(sdlRenderer,
264 SDL_PIXELFORMAT_RGB888,
265 SDL_TEXTUREACCESS_STREAMING,
266 nVidImageWidth, nVidImageHeight);
267 }
268 else
269 {
270 sdlTexture = SDL_CreateTexture(sdlRenderer,
271 SDL_PIXELFORMAT_RGB565,
272 SDL_TEXTUREACCESS_STREAMING,
273 nVidImageWidth, nVidImageHeight);
274 }
275 if (!sdlTexture)
276 {
277 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create sdlTexture from surface: %s", SDL_GetError());
278 return 3;
279 }
280
281 nVidImageBPP = (nVidImageDepth + 7) >> 3;
282 nBurnBpp = nVidImageBPP;
283
284 SetBurnHighCol(nVidImageDepth);
285
286 nVidImagePitch = nVidImageWidth * nVidImageBPP;
287 nBurnPitch = nVidImagePitch;
288
289 nMemLen = nVidImageWidth * nVidImageHeight * nVidImageBPP;
290
291 printf("nVidImageWidth=%d nVidImageHeight=%d nVidImagePitch=%d\n", nVidImageWidth, nVidImageHeight, nVidImagePitch);
292
293 VidMem = (unsigned char*)malloc(nMemLen);
294 if (VidMem)
295 {
296 memset(VidMem, 0, nMemLen);
297 pVidImage = VidMem;
298 printf("Malloc for video Ok %d\n", nMemLen);
299 return 0;
300 }
301 else
302 {
303 pVidImage = NULL;
304 return 1;
305 }
306
307
308 printf("done vid init");
309 return 0;
310 }
311
vidScale(RECT *,int,int)312 static int vidScale(RECT*, int, int)
313 {
314 return 0;
315 }
316
317 // Run one frame and render the screen
Frame(bool bRedraw)318 static int Frame(bool bRedraw) // bRedraw = 0
319 {
320 if (pVidImage == NULL)
321 {
322 return 1;
323 }
324
325 VidFrameCallback(bRedraw);
326
327 return 0;
328 }
329
330 // Paint the BlitFX surface onto the primary surface
Paint(int bValidate)331 static int Paint(int bValidate)
332 {
333 void* pixels;
334 int pitch;
335
336 SDL_RenderClear(sdlRenderer);
337 SDL_UpdateTexture(sdlTexture, NULL, pVidImage, nVidImagePitch);
338 if (nRotateGame)
339 {
340 SDL_RenderCopyEx(sdlRenderer, sdlTexture, NULL, &dstrect, (bFlipped ? 90 : 270), NULL, SDL_FLIP_NONE);
341 }
342 else
343 {
344 if (bFlipped)
345 {
346 SDL_RenderCopyEx(sdlRenderer, sdlTexture, NULL, &dstrect, 180, NULL, SDL_FLIP_NONE);
347 }
348 else
349 {
350 SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, &dstrect);
351 }
352 }
353
354 RenderMessage();
355
356 SDL_RenderPresent(sdlRenderer);
357
358 return 0;
359 }
360
GetSettings(InterfaceInfo * pInfo)361 static int GetSettings(InterfaceInfo* pInfo)
362 {
363 return 0;
364 }
365
366 // The Video Output plugin:
367 struct VidOut VidOutSDL2 = { Init, Exit, Frame, Paint, vidScale, GetSettings, _T("SDL2 video output") };
368