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