1 // OpenGL via SDL2
2 #include "burner.h"
3 #include "vid_support.h"
4 #include "vid_softfx.h"
5
6 #include <SDL.h>
7 #include <SDL_opengl.h>
8
9 extern char videofiltering[3];
10
11 static SDL_GLContext glContext = NULL;
12
13 static int nInitedSubsytems = 0;
14
15 static int nGamesWidth = 0, nGamesHeight = 0; // screen size
16
17 static GLint texture_type = GL_UNSIGNED_BYTE;
18 extern SDL_Window* sdlWindow;
19 static unsigned char* texture = NULL;
20 static unsigned char* gamescreen = NULL;
21
22 static int nTextureWidth = 512;
23 static int nTextureHeight = 512;
24
25 static int nSize;
26 static int nUseBlitter;
27
28 static int nRotateGame = 0;
29 static bool bFlipped = false;
30
31 static char Windowtitle[512];
32
BlitFXExit()33 static int BlitFXExit()
34 {
35 SDL_DestroyWindow(sdlWindow);
36 SDL_GL_DeleteContext(glContext);
37 free(texture);
38 free(gamescreen);
39 nRotateGame = 0;
40
41 return 0;
42 }
GetTextureSize(int Size)43 static int GetTextureSize(int Size)
44 {
45 int nTextureSize = 128;
46
47 while (nTextureSize < Size)
48 {
49 nTextureSize <<= 1;
50 }
51
52 return nTextureSize;
53 }
54
BlitFXInit()55 static int BlitFXInit()
56 {
57 int nMemLen = 0;
58
59 nVidImageDepth = bDrvOkay ? 16 : 32;
60 nVidImageBPP = (nVidImageDepth + 7) >> 3;
61 nBurnBpp = nVidImageBPP;
62
63 SetBurnHighCol(nVidImageDepth);
64
65 if (!nRotateGame)
66 {
67 nVidImageWidth = nGamesWidth;
68 nVidImageHeight = nGamesHeight;
69 }
70 else
71 {
72 nVidImageWidth = nGamesHeight;
73 nVidImageHeight = nGamesWidth;
74 }
75
76 nVidImagePitch = nVidImageWidth * nVidImageBPP;
77 nBurnPitch = nVidImagePitch;
78
79 nMemLen = nVidImageWidth * nVidImageHeight * nVidImageBPP;
80
81 printf("nVidImageWidth=%d nVidImageHeight=%d nVidImagePitch=%d\n", nVidImageWidth, nVidImageHeight, nVidImagePitch);
82 printf("nTextureWidth=%d nTextureHeight=%d TexturePitch=%d\n", nTextureWidth, nTextureHeight, nTextureWidth * nVidImageBPP);
83
84 texture = (unsigned char*)malloc(nTextureWidth * nTextureHeight * nVidImageBPP);
85
86 gamescreen = (unsigned char*)malloc(nMemLen);
87 if (gamescreen)
88 {
89 memset(gamescreen, 0, nMemLen);
90 pVidImage = gamescreen;
91 return 0;
92 }
93 else
94 {
95 pVidImage = NULL;
96 return 1;
97 }
98
99 return 0;
100 }
101
Exit()102 static int Exit()
103 {
104 BlitFXExit();
105
106 if (!(nInitedSubsytems & SDL_INIT_VIDEO))
107 {
108 SDL_QuitSubSystem(SDL_INIT_VIDEO);
109 }
110
111 nInitedSubsytems = 0;
112
113 return 0;
114 }
115
init_gl()116 void init_gl()
117 {
118 printf("opengl config\n");
119
120 if ((BurnDrvGetFlags() & BDF_16BIT_ONLY) || (nVidImageBPP != 3))
121 {
122 texture_type = GL_UNSIGNED_SHORT_5_6_5;
123 }
124 else
125 {
126 texture_type = GL_UNSIGNED_BYTE;
127 }
128
129 glShadeModel(GL_FLAT);
130 glDisable(GL_POLYGON_SMOOTH);
131 glDisable(GL_LINE_SMOOTH);
132 glDisable(GL_POINT_SMOOTH);
133 glDisable(GL_BLEND);
134 glDisable(GL_DEPTH_TEST);
135 glDepthMask(GL_FALSE);
136 glDisable(GL_CULL_FACE);
137 glEnable(GL_TEXTURE_2D);
138 if (strcmp(videofiltering, "1") == 0)
139 {
140 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
141 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
142 }
143 else
144 {
145 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
146 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
147 }
148 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTextureWidth, nTextureHeight, 0, GL_RGB, texture_type, texture);
149
150 glMatrixMode(GL_PROJECTION);
151 glLoadIdentity();
152
153 if (!nRotateGame)
154 {
155 glRotatef((bFlipped ? 180.0 : 0.0), 0.0, 0.0, 1.0);
156 glOrtho(0, nGamesWidth, nGamesHeight, 0, -1, 1);
157 }
158 else
159 {
160 glRotatef((bFlipped ? 270.0 : 90.0), 0.0, 0.0, 1.0);
161 glOrtho(0, nGamesHeight, nGamesWidth, 0, -1, 1);
162 }
163
164 glMatrixMode(GL_MODELVIEW);
165 glLoadIdentity();
166
167 printf("opengl config done . . . \n");
168 }
169
VidSScaleImage(RECT * pRect)170 static int VidSScaleImage(RECT* pRect)
171 {
172 int nScrnWidth, nScrnHeight;
173
174 int nGameAspectX = 4, nGameAspectY = 3;
175 int nWidth = pRect->right - pRect->left;
176 int nHeight = pRect->bottom - pRect->top;
177
178 if (bVidFullStretch)
179 { // Arbitrary stretch
180 return 0;
181 }
182
183 if (bDrvOkay)
184 {
185 if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)
186 {
187 BurnDrvGetAspect(&nGameAspectY, &nGameAspectX);
188 }
189 else
190 {
191 BurnDrvGetAspect(&nGameAspectX, &nGameAspectY);
192 }
193 }
194
195 nScrnWidth = nGameAspectX;
196 nScrnHeight = nGameAspectY;
197
198 int nWidthScratch = nHeight * nVidScrnAspectY * nGameAspectX * nScrnWidth /
199 (nScrnHeight * nVidScrnAspectX * nGameAspectY);
200
201 if (nWidthScratch > nWidth)
202 { // The image is too wide
203 if (nGamesWidth < nGamesHeight)
204 { // Vertical games
205 nHeight = nWidth * nVidScrnAspectY * nGameAspectY * nScrnWidth /
206 (nScrnHeight * nVidScrnAspectX * nGameAspectX);
207 }
208 else
209 { // Horizontal games
210 nHeight = nWidth * nVidScrnAspectX * nGameAspectY * nScrnHeight /
211 (nScrnWidth * nVidScrnAspectY * nGameAspectX);
212 }
213 }
214 else
215 {
216 nWidth = nWidthScratch;
217 }
218
219 pRect->left = (pRect->right + pRect->left) / 2;
220 pRect->left -= nWidth / 2;
221 pRect->right = pRect->left + nWidth;
222
223 pRect->top = (pRect->top + pRect->bottom) / 2;
224 pRect->top -= nHeight / 2;
225 pRect->bottom = pRect->top + nHeight;
226
227 return 0;
228 }
229
Init()230 static int Init()
231 {
232 nInitedSubsytems = SDL_WasInit(SDL_INIT_VIDEO);
233
234 if (!(nInitedSubsytems & SDL_INIT_VIDEO))
235 {
236 SDL_InitSubSystem(SDL_INIT_VIDEO);
237 }
238
239 nGamesWidth = nVidImageWidth;
240 nGamesHeight = nVidImageHeight;
241
242 nRotateGame = 0;
243
244 if (bDrvOkay) {
245 // Get the game screen size
246 BurnDrvGetVisibleSize(&nGamesWidth, &nGamesHeight);
247
248 if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL)
249 {
250 printf("Vertical\n");
251 nRotateGame = 1;
252 }
253
254 if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED)
255 {
256 printf("Flipped\n");
257 bFlipped = true;
258 }
259 }
260
261 if (!nRotateGame)
262 {
263 nTextureWidth = GetTextureSize(nGamesWidth);
264 nTextureHeight = GetTextureSize(nGamesHeight);
265 }
266 else
267 {
268 nTextureWidth = GetTextureSize(nGamesHeight);
269 nTextureHeight = GetTextureSize(nGamesWidth);
270 }
271
272 nSize = 2;
273 bVidScanlines = 0;
274
275 RECT test_rect;
276 test_rect.left = 0;
277 test_rect.right = nGamesWidth;
278 test_rect.top = 0;
279 test_rect.bottom = nGamesHeight;
280
281 printf("correctx before %d, %d\n", test_rect.right, test_rect.bottom);
282 VidSScaleImage(&test_rect);
283 printf("correctx after %d, %d\n", test_rect.right, test_rect.bottom);
284
285 Uint32 screenFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
286
287 if (bAppFullscreen)
288 {
289 screenFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN;
290 }
291
292 sprintf(Windowtitle, "FBNeo - %s - %s", BurnDrvGetTextA(DRV_NAME), BurnDrvGetTextA(DRV_FULLNAME));
293
294 sdlWindow = SDL_CreateWindow(Windowtitle, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, test_rect.right * nSize,
295 test_rect.bottom * nSize, screenFlags);
296 glContext = SDL_GL_CreateContext(sdlWindow);
297 // Initialize the buffer surfaces
298 BlitFXInit();
299
300 // Init opengl
301 init_gl();
302
303 return 0;
304 }
305
306 // Run one frame and render the screen
Frame(bool bRedraw)307 static int Frame(bool bRedraw) // bRedraw = 0
308 {
309 if (pVidImage == NULL)
310 {
311 return 1;
312 }
313
314 VidFrameCallback(bRedraw);
315
316 return 0;
317 }
318
SurfToTex()319 static void SurfToTex()
320 {
321 int nVidPitch = nTextureWidth * nVidImageBPP;
322
323 unsigned char* ps = (unsigned char*)gamescreen;
324 unsigned char* pd = (unsigned char*)texture;
325
326 for (int y = nVidImageHeight; y--;)
327 {
328 memcpy(pd, ps, nVidImagePitch);
329 pd += nVidPitch;
330 ps += nVidImagePitch;
331 }
332
333 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTextureWidth, nTextureHeight, 0,
334 GL_RGB, texture_type, texture);
335 }
336
TexToQuad()337 static void TexToQuad()
338 {
339 glBegin(GL_QUADS);
340 glTexCoord2f(0, 0);
341 glVertex2i(0, 0);
342 glTexCoord2f(0, 1);
343 glVertex2i(0, nTextureHeight);
344 glTexCoord2f(1, 1);
345 glVertex2i(nTextureWidth, nTextureHeight);
346 glTexCoord2f(1, 0);
347 glVertex2i(nTextureWidth, 0);
348 glEnd();
349 glFinish();
350 }
351
352 // Paint the BlitFX surface onto the primary surface
Paint(int bValidate)353 static int Paint(int bValidate)
354 {
355
356 SurfToTex();
357 TexToQuad();
358
359 if (bAppShowFPS && !bAppFullscreen)
360 {
361 sprintf(Windowtitle, "FBNeo - FPS: %s - %s - %s", fpsstring, BurnDrvGetTextA(DRV_NAME), BurnDrvGetTextA(DRV_FULLNAME));
362 SDL_SetWindowTitle(sdlWindow, Windowtitle);
363 }
364 SDL_GL_SwapWindow(sdlWindow);
365
366
367 return 0;
368 }
369
vidScale(RECT *,int,int)370 static int vidScale(RECT*, int, int)
371 {
372 return 0;
373 }
374
375
GetSettings(InterfaceInfo * pInfo)376 static int GetSettings(InterfaceInfo* pInfo)
377 {
378 TCHAR szString[MAX_PATH] = _T("");
379
380 _sntprintf(szString, MAX_PATH, _T("Prescaling using %s (%i� zoom)"), VidSoftFXGetEffect(nUseBlitter), nSize);
381 IntInfoAddStringModule(pInfo, szString);
382
383 if (nRotateGame)
384 {
385 IntInfoAddStringModule(pInfo, _T("Using software rotation"));
386 }
387
388 return 0;
389 }
390
391 // The Video Output plugin:
392 struct VidOut VidOutSDL2Opengl = { Init, Exit, Frame, Paint, vidScale, GetSettings, _T("SDL OpenGL Video output") };
393