]> Shamusworld >> Repos - apple2/blob - src/video.cpp
Beginnings of new GUI
[apple2] / src / video.cpp
1 //
2 // VIDEO.CPP: SDL/local hardware specific video routines
3 //
4 // by James L. Hammons
5 //
6 // JLH = James L. Hammons <jlhamm@acm.org>
7 //
8 // WHO  WHEN        WHAT
9 // ---  ----------  ------------------------------------------------------------
10 // JLH  01/04/2006  Added changelog ;-)
11 // JLH  01/20/2006  Cut out unnecessary buffering
12 //
13
14 #include "video.h"
15
16 //#include <SDL.h>
17 #include <string.h>     // Why??? (for memset, etc... Lazy!) Dunno why, but this just strikes me as wrong...
18 #include <malloc.h>
19 #include "sdlemu_opengl.h"
20 #include "log.h"
21 #include "settings.h"
22 #include "icon.h"
23
24 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
25 #define MASK_R 0xFF000000
26 #define MASK_G 0x00FF0000
27 #define MASK_B 0x0000FF00
28 #define MASK_A 0x000000FF
29 #else
30 #define MASK_R 0x000000FF
31 #define MASK_G 0x0000FF00
32 #define MASK_B 0x00FF0000
33 #define MASK_A 0xFF000000
34 #endif
35
36 //#define TEST_ALPHA_BLENDING
37
38 // Exported global variables (actually, these are LOCAL global variables, EXPORTED...)
39
40 SDL_Surface * surface, * mainSurface, * someAlphaSurface;
41 Uint32 mainSurfaceFlags;
42 //uint32 scrBuffer[VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT];
43 uint32 * scrBuffer = NULL, * mainScrBuffer = NULL;
44 SDL_Joystick * joystick;
45
46 //
47 // Prime SDL and create surfaces
48 //
49 bool InitVideo(void)
50 {
51         // Set up SDL library
52         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
53         {
54                 WriteLog("Video: Could not initialize the SDL library: %s\n", SDL_GetError());
55                 return false;
56         }
57
58         //Set icon (mainly for Win32 target--though seems to work under KDE as well...!)
59         SDL_Surface * iconSurf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 128,
60                 MASK_R, MASK_G, MASK_B, MASK_A);
61         SDL_WM_SetIcon(iconSurf, NULL);
62         SDL_FreeSurface(iconSurf);
63
64         // Get proper info about the platform we're running on...
65         const SDL_VideoInfo * info = SDL_GetVideoInfo();
66
67         if (!info)
68         {
69                 WriteLog("Video: SDL is unable to get the video info: %s\n", SDL_GetError());
70                 return false;
71         }
72
73         if (settings.useOpenGL)
74         {
75                 mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
76                 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
77         }
78         else
79         {
80                 mainSurfaceFlags = SDL_DOUBLEBUF;
81
82                 if (info->hw_available)
83                 {
84                         mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE;
85                         WriteLog("Video: Hardware available...\n");
86                 }
87
88                 if (info->blit_hw)
89                 {
90                         mainSurfaceFlags |= SDL_HWACCEL;
91                         WriteLog("Video: Hardware blit available...\n");
92                 }
93         }
94
95         if (settings.fullscreen)
96                 mainSurfaceFlags |= SDL_FULLSCREEN;
97
98         // Create the primary SDL display (32 BPP)
99         if (!settings.useOpenGL)
100                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
101         else
102 //              mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
103 //              mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
104                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
105
106         if (mainSurface == NULL)
107         {
108                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
109                 return false;
110         }
111
112         SDL_WM_SetCaption("Apple 2 SDL", "Apple 2 SDL");
113
114         // Create the secondary SDL display (32 BPP) that we use directly
115         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32,
116                 MASK_R, MASK_G, MASK_B, MASK_A);
117 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
118 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
119 WriteLog("\t        Pitch: %u\n", surface->pitch);
120 WriteLog("\t      Palette: %08X\n", surface->format->palette);
121 WriteLog("\t          BPP: %u\n", surface->format->BitsPerPixel);
122 WriteLog("\t      BytesPP: %u\n", surface->format->BytesPerPixel);
123 WriteLog("\t        RMask: %08X\n", surface->format->Rmask);
124 WriteLog("\t        GMask: %08X\n", surface->format->Gmask);
125 WriteLog("\t        BMask: %08X\n", surface->format->Bmask);
126 WriteLog("\t        AMask: %08X\n", surface->format->Amask);
127 WriteLog("\n");//*/
128
129         if (surface == NULL)
130         {
131                 WriteLog("Video: Could not create secondary SDL surface: %s\n", SDL_GetError());
132                 return false;
133         }
134
135         if (settings.useOpenGL)
136                 sdlemu_init_opengl(surface, mainSurface, 1 /*method*/, settings.glFilter /*texture type (linear, nearest)*/,
137                 0 /* Automatic bpp selection based upon src */);
138
139         // Initialize Joystick support under SDL
140 /*      if (settings.useJoystick)
141         {
142                 if (SDL_NumJoysticks() <= 0)
143                 {
144                         settings.useJoystick = false;
145                         WriteLog("Video: No joystick(s) or joypad(s) detected on your system. Using keyboard...\n");
146                 }
147                 else
148                 {
149                         if ((joystick = SDL_JoystickOpen(settings.joyport)) == 0)
150                         {
151                                 settings.useJoystick = false;
152                                 WriteLog("Video: Unable to open a Joystick on port: %d\n", (int)settings.joyport);
153                         }
154                         else
155                                 WriteLog("Video: Using: %s\n", SDL_JoystickName(settings.joyport));
156                 }
157         }//*/
158
159         // Set up the scrBuffer
160         scrBuffer = (uint32 *)surface->pixels;  // Kludge--And shouldn't have to lock since it's a software surface...
161 //needed? Dunno. Mebbe an SDL function instead?
162 //      memset(scrBuffer, 0x00, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
163         // Set up the mainScrBuffer
164         mainScrBuffer = (uint32 *)mainSurface->pixels;  // May need to lock...
165
166 #ifdef TEST_ALPHA_BLENDING
167 //Here's some code to test alpha blending...
168 //Well whaddya know, it works. :-)
169         someAlphaSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 30, 30, 32,
170                 MASK_R, MASK_G, MASK_B, MASK_A);
171
172         for(int i=0; i<30; i++)
173         {
174                 for(int j=0; j<30; j++)
175                 {
176                         uint32 color = (uint32)(((double)(i * j) / (29.0 * 29.0)) * 255.0);
177                         color = (color << 24) | 0x00FF00FF;
178                         ((uint32 *)someAlphaSurface->pixels)[(j * 30) + i] = color;
179                 }
180         }
181 //End test code
182 #endif
183
184         WriteLog("Video: Successfully initialized.\n");
185         return true;
186 }
187
188 //
189 // Free various SDL components
190 //
191 void VideoDone(void)
192 {
193         if (settings.useOpenGL)
194                 sdlemu_close_opengl();
195
196         SDL_JoystickClose(joystick);
197         SDL_FreeSurface(surface);
198         SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER);
199         SDL_Quit();
200 }
201
202 //
203 // Render the screen buffer to the primary screen surface
204 //
205 //void RenderBackbuffer(void)
206 void RenderScreenBuffer(void)
207 {
208 //WriteLog("Video: Blitting a %u x %u surface to the main surface...\n", surface->w, surface->h);
209 //Don't need this crapola--why have a separate buffer just to copy it to THIS
210 //buffer in order to copy it to the main screen? That's what *I* thought!
211 /*      if (SDL_MUSTLOCK(surface))
212                 while (SDL_LockSurface(surface) < 0)
213                         SDL_Delay(10);
214
215         memcpy(surface->pixels, scrBuffer, VIRTUAL_SCREEN_WIDTH * VIRTUAL_SCREEN_HEIGHT * sizeof(uint32));
216
217         if (SDL_MUSTLOCK(surface))
218                 SDL_UnlockSurface(surface);//*/
219 #ifdef TEST_ALPHA_BLENDING
220 SDL_Rect dstRect = { 100, 100, 30, 30 };
221 SDL_BlitSurface(someAlphaSurface, NULL, surface, &dstRect);
222 #endif
223
224         if (settings.useOpenGL)
225                 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
226         else
227         {
228 //              SDL_Rect rect = { 0, 0, surface->w, surface->h };
229 //              SDL_BlitSurface(surface, &rect, mainSurface, &rect);
230                 SDL_BlitSurface(surface, NULL, mainSurface, NULL);
231                 SDL_Flip(mainSurface);
232     }
233 }
234
235 // Is this even necessary? (Could call SDL_Flip directly...)
236 void FlipMainScreen(void)
237 {
238 #ifdef TEST_ALPHA_BLENDING
239 SDL_Rect dstRect = { 100, 100, 30, 30 };
240 SDL_BlitSurface(someAlphaSurface, NULL, mainSurface, &dstRect);
241 #endif
242
243         if (settings.useOpenGL)
244                 sdlemu_draw_texture(mainSurface, surface, 1/*1=GL_QUADS*/);
245         else
246                 SDL_Flip(mainSurface);
247 }
248
249 /*
250 //
251 // Resize the main SDL screen & scrBuffer
252 //
253 void ResizeScreen(uint32 width, uint32 height)
254 {
255         char window_title[256];
256
257         SDL_FreeSurface(surface);
258         surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16,
259                 0x7C00, 0x03E0, 0x001F, 0);
260
261         if (surface == NULL)
262         {
263                 WriteLog("Video: Could not create primary SDL surface: %s", SDL_GetError());
264                 exit(1);
265         }
266
267         if (settings.useOpenGL)
268                 // This seems to work well for resizing (i.e., changes in the pixel width)...
269                 sdlemu_resize_texture(surface, mainSurface, settings.glFilter);
270         else
271         {
272                 mainSurface = SDL_SetVideoMode(width, height, 16, mainSurfaceFlags);
273
274                 if (mainSurface == NULL)
275                 {
276                         WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
277                         exit(1);
278                 }
279         }
280
281         sWriteLog(window_title, "Virtual Jaguar (%i x %i)", (int)width, (int)height);
282         SDL_WM_SetCaption(window_title, window_title);
283
284         // This seems to work well for resizing (i.e., changes in the pixel width)...
285 //      if (settings.useOpenGL)
286 //              sdlemu_resize_texture(surface, mainSurface);
287 }*/
288
289 /*
290 //
291 // Fullscreen <-> window switching
292 //
293 //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!!
294 void ToggleFullscreen(void)
295 {
296         settings.fullscreen = !settings.fullscreen;
297         mainSurfaceFlags &= ~SDL_FULLSCREEN;
298
299         if (settings.fullscreen)
300                 mainSurfaceFlags |= SDL_FULLSCREEN;
301
302         if (!settings.useOpenGL)
303                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
304         else
305 //              mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
306 //              mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT * 2, 32, mainSurfaceFlags);
307                 mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, mainSurfaceFlags);
308 //      mainSurface = SDL_SetVideoMode(tom_width, tom_height, 16, mainSurfaceFlags);
309
310         if (mainSurface == NULL)
311         {
312                 WriteLog("Video: SDL is unable to set the video mode: %s\n", SDL_GetError());
313                 exit(1);
314         }
315
316         SDL_WM_SetCaption("Apple 2 SDL", "Apple 2 SDL");
317 }
318 //*/