]> Shamusworld >> Repos - stargem2/blob - src/video.cpp
fe552b9fc7692801276ae78c7591140165c60718
[stargem2] / src / video.cpp
1 //
2 // VIDEO.CPP: SDL/local hardware specific video routines
3 //
4 // by James L. Hammons
5 //
6
7 #include "video.h"
8
9 //#include "SDL.h"
10 #include <string.h>     // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
11 #include <malloc.h>
12 #include "sdlemu_opengl.h"
13 #include "log.h"
14 #include "settings.h"
15 #include "icon.h"
16
17 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
18 #define MASK_R 0xFF000000
19 #define MASK_G 0x00FF0000
20 #define MASK_B 0x0000FF00
21 #define MASK_A 0x000000FF
22 #else
23 #define MASK_R 0x000000FF
24 #define MASK_G 0x0000FF00
25 #define MASK_B 0x00FF0000
26 #define MASK_A 0xFF000000
27 #endif
28
29 //#define TEST_ALPHA_BLENDING
30
31 // Exported global variables (actually, these are LOCAL global variables, EXPORTED...)
32
33 SDL_Surface * surface, * mainSurface, * someAlphaSurface;
34 Uint32 mainSurfaceFlags;
35 uint32 * scrBuffer = NULL;
36 SDL_Joystick * joystick;
37
38 //
39 // Prime SDL and create surfaces
40 //
41 bool InitVideo(void)
42 {
43         // Set up SDL library
44         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
45         {
46                 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
47                 return false;
48         }
49
50         // Get proper info about the platform we're running on...
51         const SDL_VideoInfo * info = SDL_GetVideoInfo();
52
53         if (!info)
54         {
55                 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
56                 return false;
57         }
58
59         WriteLog("Video: Hardware is%s available...\n", (info->hw_available ? "" : " NOT"));
60         WriteLog("Video: Hardware blit is%s available...\n", (info->blit_hw ? "" : " NOT"));
61
62         if (settings.useOpenGL)
63         {
64                 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_OPENGL;
65                 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
66 //We want 32BPP, so force the issue...
67                 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
68                 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
69                 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
70         }
71         else
72         {
73                 mainSurfaceFlags = SDL_DOUBLEBUF;
74
75                 if (info->hw_available)
76                         mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE;
77
78                 if (info->blit_hw)
79                         mainSurfaceFlags |= SDL_HWACCEL;
80         }
81
82         if (settings.fullscreen)
83                 mainSurfaceFlags |= SDL_FULLSCREEN;
84
85         // Create the primary SDL display (32 BPP)
86         if (settings.useOpenGL)
87                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
88         else
89                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
90
91         if (mainSurface == NULL)
92         {
93                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
94                 return false;
95         }
96
97         // Set icon (mainly for Win32 target--though seems to work under KDE as well...!)
98         SDL_Surface * iconSurf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 128, 
99                 MASK_R, MASK_G, MASK_B, MASK_A);
100         SDL_WM_SetIcon(iconSurf, NULL);
101         SDL_FreeSurface(iconSurf);
102
103         SDL_WM_SetCaption("StarGem2", "StarGem2");
104
105         // Create the secondary SDL display (32 BPP) that we use directly
106         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32,
107                 MASK_R, MASK_G, MASK_B, MASK_A);
108 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
109 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
110 WriteLog("\t        Pitch: %u\n", surface->pitch);
111 WriteLog("\t      Palette: %08X\n", surface->format->palette);
112 WriteLog("\t          BPP: %u\n", surface->format->BitsPerPixel);
113 WriteLog("\t      BytesPP: %u\n", surface->format->BytesPerPixel);
114 WriteLog("\t        RMask: %08X\n", surface->format->Rmask);
115 WriteLog("\t        GMask: %08X\n", surface->format->Gmask);
116 WriteLog("\t        BMask: %08X\n", surface->format->Bmask);
117 WriteLog("\t        AMask: %08X\n", surface->format->Amask);
118 WriteLog("\n");//*/
119
120         if (surface == NULL)
121         {
122                 WriteLog("Video: Could not create secondary SDL surface: %s\n", SDL_GetError());
123                 return false;
124         }
125
126         if (settings.useOpenGL)
127                 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/,
128                         settings.glFilter /*texture type (linear, nearest)*/,
129                         0 /* Automatic bpp selection based upon src */);
130
131         // Initialize Joystick support under SDL
132 /*      if (settings.useJoystick)
133         {
134                 if (SDL_NumJoysticks() <= 0)
135                 {
136                         settings.useJoystick = false;
137                         WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
138                 }
139                 else
140                 {
141                         if ((joystick = SDL_JoystickOpen(settings.joyport)) == 0)
142                         {
143                                 settings.useJoystick = false;
144                                 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)settings.joyport);
145                         }
146                         else
147                                 WriteLog("Video: Using: %s\n", SDL_JoystickName(settings.joyport));
148                 }
149         }//*/
150
151         // Set up the scrBuffer
152         scrBuffer = (uint32 *)surface->pixels;  // Kludge--And shouldn't have to lock since it's a software surface...
153 //needed? Dunno. Mebbe an SDL function instead?
154 //      memset(scrBuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
155
156 #ifdef TEST_ALPHA_BLENDING
157 //Here's some code to test alpha blending...
158 //Well whaddya know, it works. :-)
159         someAlphaSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 30, 30, 32,
160                 MASK_R, MASK_G, MASK_B, MASK_A);
161
162         for(int i=0; i<30; i++)
163         {
164                 for(int j=0; j<30; j++)
165                 {
166                         uint32 color = (uint32)(((double)(i * j) / (29.0 * 29.0)) * 255.0);
167                         color = (color << 24) | 0x00FF00FF;
168                         ((uint32 *)someAlphaSurface->pixels)[(j * 30) + i] = color;
169                 }
170         }
171 //End test code
172 #endif
173
174         WriteLog("Video: Successfully initialized.\n");
175         return true;
176 }
177
178 //
179 // Free various SDL components
180 //
181 void VideoDone(void)
182 {
183         if (settings.useOpenGL)
184                 sdlemu_close_opengl();
185
186         SDL_JoystickClose(joystick);
187         SDL_FreeSurface(surface);
188         SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER);
189         SDL_Quit();
190 }
191
192
193
194 #if 0
195 ///
196
197 #include "SDL.h"
198 #include <string.h>     // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
199 #include <malloc.h>
200 #include "sdlemu_opengl.h"
201 #include "types.h"
202 #include "log.h"
203 #include "settings.h"
204 #include "video.h"
205
206 // External global variables
207
208 SDL_Surface * surface, * mainSurface;
209 Uint32 mainSurfaceFlags;
210 uint8 * backbuffer;
211 SDL_Joystick * joystick;
212 uint8 color[16];
213 uint32 palette[256];
214
215 //
216 // Prime SDL and create surfaces
217 //
218 bool InitVideo(void)
219 {
220         // Set up SDL library
221         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
222         {
223                 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
224                 return false;
225         }
226
227         // Get proper info about the platform we're running on...
228         const SDL_VideoInfo * info = SDL_GetVideoInfo();
229
230         if (!info)
231         {
232                 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
233                 return false;
234         }
235
236         if (1)//(vjs.useOpenGL)
237         {
238                 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
239                 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
240         }
241         else
242         {
243                 if (info->hw_available)
244                 {
245                         mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
246                         WriteLog("Video: Hardware available...\n");
247                 }
248
249                 if (info->blit_hw)
250                 {
251                         mainSurfaceFlags |= SDL_HWACCEL;
252                         WriteLog("Video: Hardware blit available...\n");
253                 }
254         }
255
256 //      if (vjs.fullscreen)
257 //              mainSurfaceFlags |= SDL_FULLSCREEN;
258
259         if (0)//(!vjs.useOpenGL)
260                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
261         else
262                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
263
264         if (mainSurface == NULL)
265         {
266                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
267                 return false;
268         }
269
270         SDL_WM_SetCaption("StarGem2", "StarGem2");
271
272         // Create the primary SDL display (8 BPP, palettized)
273 //      surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT,
274 //              8, 0, 0, 0, 0);
275         // Create the primary SDL display (32 BPP)
276         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32,
277 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
278                 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF
279 #else
280                 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000
281 #endif
282                 );
283 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
284 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
285 WriteLog("\t        Pitch: %u\n", surface->pitch);
286 WriteLog("\t      Palette: %08X\n", surface->format->palette);
287 WriteLog("\t          BPP: %u\n", surface->format->BitsPerPixel);
288 WriteLog("\t      BytesPP: %u\n", surface->format->BytesPerPixel);
289 WriteLog("\t        RMask: %08X\n", surface->format->Rmask);
290 WriteLog("\t        GMask: %08X\n", surface->format->Gmask);
291 WriteLog("\t        BMask: %08X\n", surface->format->Bmask);
292 WriteLog("\t        AMask: %08X\n", surface->format->Amask);
293 WriteLog("\n");//*/
294
295         if (surface == NULL)
296         {
297                 WriteLog("Video: Could not create primary SDL surface: %s\n", SDL_GetError());
298                 return false;
299         }
300
301         // Initialize Williams' palette (RGB coded as: 3 bits red, 3 bits green, 2 bits blue)
302         for(uint32 i=0; i<256; i++)
303 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
304                 palette[i] = (((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151) << 24)
305                         | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 16)
306                         | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 8) | 0xFF;//*/
307 #else
308                 palette[i] = ((i & 0x01) * 33 + ((i & 0x02) >> 1) * 71 + ((i & 0x04) >> 2) * 151)
309                         | ((((i & 0x08) >> 3) * 33 + ((i & 0x10) >> 4) * 71 + ((i & 0x20) >> 5) * 151) << 8)
310                         | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 16) | 0xFF000000;//*/
311 #endif
312
313 //      if (vjs.useOpenGL)
314         if (1)
315 //Should make another setting here, for either linear or nearest (instead of just picking one)
316 //And we have! ;-) Not... ;-(
317 //              sdlemu_init_opengl(surface, 1/*method*/, 2/*size*/, 0);//vjs.glFilter/*texture type (linear, nearest)*/);
318                 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/,
319                         0 /*vjs.glFilter /texture type (linear, nearest)*/,
320                         0 /* Automatic bpp selection based upon src */);
321
322         // Initialize Joystick support under SDL
323 /*      if (1)//(vjs.useJoystick)
324         {
325                 if (SDL_NumJoysticks() <= 0)
326                 {
327                         vjs.useJoystick = false;
328                         WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
329                 }
330                 else
331                 {
332                         if ((joystick = SDL_JoystickOpen(vjs.joyport)) == 0)
333                         {
334                                 vjs.useJoystick = false;
335                                 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)vjs.joyport);
336                         }
337                         else
338                                 WriteLog("Video: Using: %s\n", SDL_JoystickName(vjs.joyport));
339                 }
340         }*/
341
342         // Set up the backbuffer
343         backbuffer = (uint8 *)malloc(320 * 240 * sizeof(uint8));
344         memset(backbuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint8));
345
346         WriteLog("Video: Successfully initialized.\n");
347         return true;
348 }
349
350 #endif
351
352
353
354 //
355 // Render the backbuffer to the primary screen surface
356 //
357 void RenderScreenBuffer(void)
358 {
359 //WriteLog("Video: Blitting a %u x %u surface to the main surface...\n", surface->w, surface->h);
360 //Don't need this crapola--why have a separate buffer just to copy it to THIS
361 //buffer in order to copy it to the main screen? That's what *I* thought!
362 /*      if (SDL_MUSTLOCK(surface))
363                 while (SDL_LockSurface(surface) < 0)
364                         SDL_Delay(10);
365
366         memcpy(surface->pixels, scrBuffer, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
367
368         if (SDL_MUSTLOCK(surface))
369                 SDL_UnlockSurface(surface);//*/
370 #ifdef TEST_ALPHA_BLENDING
371 SDL_Rect dstRect = { 100, 100, 30, 30 };
372 SDL_BlitSurface(someAlphaSurface, NULL, surface, &dstRect);
373 #endif
374
375         if (settings.useOpenGL)
376                 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
377         else
378         {
379                 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
380                 SDL_Flip(mainSurface);
381     }
382 }
383
384 //
385 // Render the backbuffer to the primary screen surface
386 //
387 void RenderScreenBuffer2(void)
388 {
389 #if 0
390 //WriteLog("Video: Blitting a %u x %u surface to the main surface...", surface->w, surface->h);
391         if (SDL_MUSTLOCK(surface))
392                 while (SDL_LockSurface(surface) < 0)
393                         SDL_Delay(10);
394
395 //This *does* ignore the screen's actual pitch... !!! FIX !!!
396         uint32 * screen = (uint32 *)surface->pixels;
397         for(int i=0; i<320*240; i++)
398                 screen[i] = palette[color[scrBuffer[i]]];
399 //WriteLog("[blitted backbuffer]...");
400
401         if (SDL_MUSTLOCK(surface))
402                 SDL_UnlockSurface(surface);
403 #endif
404
405         if (settings.useOpenGL)
406                 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
407         else
408         {
409                 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
410                 SDL_Flip(mainSurface);
411     }
412 //WriteLog("done.\n");
413 }
414
415 /*
416 //
417 // Resize the main SDL screen & backbuffer
418 //
419 void ResizeScreen(uint32 width, uint32 height)
420 {
421         char window_title[256];
422
423         SDL_FreeSurface(surface);
424         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
425                 0x7C00, 0x03E0, 0x001F, 0);
426
427         if (surface == NULL)
428         {
429                 WriteLog("Video: Could not create primary SDL surface: %s", SDL_GetError());
430                 exit(1);
431         }
432
433         if (vjs.useOpenGL)
434                 // This seems to work well for resizing (i.e., changes in the pixel width)...
435                 sdlemu_resize_texture(surface, mainSurface, vjs.glFilter);
436         else
437         {
438                 mainSurface = SDL_SetVideoMode(width, height, 16, mainSurfaceFlags);
439
440                 if (mainSurface == NULL)
441                 {
442                         WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
443                         exit(1);
444                 }
445         }
446
447         sWriteLog(window_title, "Virtual Jaguar (%i x %i)", (int)width, (int)height);
448         SDL_WM_SetCaption(window_title, window_title);
449
450         // This seems to work well for resizing (i.e., changes in the pixel width)...
451 //      if (vjs.useOpenGL)
452 //              sdlemu_resize_texture(surface, mainSurface);
453 }
454
455 //
456 // Fullscreen <-> window switching
457 //
458 //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!!
459 void ToggleFullscreen(void)
460 {
461         vjs.fullscreen = !vjs.fullscreen;
462         mainSurfaceFlags &= ~SDL_FULLSCREEN;
463
464         if (vjs.fullscreen)
465                 mainSurfaceFlags |= SDL_FULLSCREEN;
466
467         mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
468
469         if (mainSurface == NULL)
470         {
471                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
472                 exit(1);
473         }
474
475         SDL_WM_SetCaption("Virtual Jaguar", "Virtual Jaguar");
476 }
477 */