|
1 /* |
|
2 SDL - Simple DirectMedia Layer |
|
3 Copyright (C) 1997-2006 Sam Lantinga |
|
4 |
|
5 This library is free software; you can redistribute it and/or |
|
6 modify it under the terms of the GNU Lesser General Public |
|
7 License as published by the Free Software Foundation; either |
|
8 version 2.1 of the License, or (at your option) any later version. |
|
9 |
|
10 This library is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 Lesser General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU Lesser General Public |
|
16 License along with this library; if not, write to the Free Software |
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
|
19 Sam Lantinga |
|
20 slouken@libsdl.org |
|
21 */ |
|
22 #include "SDL_config.h" |
|
23 |
|
24 #include "SDL_video.h" |
|
25 #include "SDL_mouse.h" |
|
26 #include "../SDL_sysvideo.h" |
|
27 #include "../SDL_pixels_c.h" |
|
28 #include "../../events/SDL_events_c.h" |
|
29 |
|
30 #include "SDL_dcvideo.h" |
|
31 #include "SDL_dcevents_c.h" |
|
32 #include "SDL_dcmouse_c.h" |
|
33 |
|
34 #include <dc/video.h> |
|
35 #include <dc/pvr.h> |
|
36 |
|
37 |
|
38 /* Initialization/Query functions */ |
|
39 static int DC_VideoInit(_THIS, SDL_PixelFormat *vformat); |
|
40 static SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); |
|
41 static SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); |
|
42 static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); |
|
43 static void DC_VideoQuit(_THIS); |
|
44 |
|
45 /* Hardware surface functions */ |
|
46 static int DC_AllocHWSurface(_THIS, SDL_Surface *surface); |
|
47 static int DC_LockHWSurface(_THIS, SDL_Surface *surface); |
|
48 static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface); |
|
49 static void DC_FreeHWSurface(_THIS, SDL_Surface *surface); |
|
50 static int DC_FlipHWSurface(_THIS, SDL_Surface *surface); |
|
51 |
|
52 /* etc. */ |
|
53 static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects); |
|
54 |
|
55 /* OpenGL */ |
|
56 #if SDL_VIDEO_OPENGL |
|
57 static void *DC_GL_GetProcAddress(_THIS, const char *proc); |
|
58 static int DC_GL_LoadLibrary(_THIS, const char *path); |
|
59 static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); |
|
60 static void DC_GL_SwapBuffers(_THIS); |
|
61 #endif |
|
62 |
|
63 /* DC driver bootstrap functions */ |
|
64 |
|
65 static int DC_Available(void) |
|
66 { |
|
67 return 1; |
|
68 } |
|
69 |
|
70 static void DC_DeleteDevice(SDL_VideoDevice *device) |
|
71 { |
|
72 SDL_free(device->hidden); |
|
73 SDL_free(device); |
|
74 } |
|
75 |
|
76 static SDL_VideoDevice *DC_CreateDevice(int devindex) |
|
77 { |
|
78 SDL_VideoDevice *device; |
|
79 |
|
80 /* Initialize all variables that we clean on shutdown */ |
|
81 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); |
|
82 if ( device ) { |
|
83 SDL_memset(device, 0, (sizeof *device)); |
|
84 device->hidden = (struct SDL_PrivateVideoData *) |
|
85 SDL_malloc((sizeof *device->hidden)); |
|
86 } |
|
87 if ( (device == NULL) || (device->hidden == NULL) ) { |
|
88 SDL_OutOfMemory(); |
|
89 if ( device ) { |
|
90 SDL_free(device); |
|
91 } |
|
92 return(0); |
|
93 } |
|
94 SDL_memset(device->hidden, 0, (sizeof *device->hidden)); |
|
95 |
|
96 /* Set the function pointers */ |
|
97 device->VideoInit = DC_VideoInit; |
|
98 device->ListModes = DC_ListModes; |
|
99 device->SetVideoMode = DC_SetVideoMode; |
|
100 device->CreateYUVOverlay = NULL; |
|
101 device->SetColors = DC_SetColors; |
|
102 device->UpdateRects = DC_UpdateRects; |
|
103 device->VideoQuit = DC_VideoQuit; |
|
104 device->AllocHWSurface = DC_AllocHWSurface; |
|
105 device->CheckHWBlit = NULL; |
|
106 device->FillHWRect = NULL; |
|
107 device->SetHWColorKey = NULL; |
|
108 device->SetHWAlpha = NULL; |
|
109 device->LockHWSurface = DC_LockHWSurface; |
|
110 device->UnlockHWSurface = DC_UnlockHWSurface; |
|
111 device->FlipHWSurface = DC_FlipHWSurface; |
|
112 device->FreeHWSurface = DC_FreeHWSurface; |
|
113 #if SDL_VIDEO_OPENGL |
|
114 device->GL_LoadLibrary = DC_GL_LoadLibrary; |
|
115 device->GL_GetProcAddress = DC_GL_GetProcAddress; |
|
116 device->GL_GetAttribute = DC_GL_GetAttribute; |
|
117 device->GL_MakeCurrent = NULL; |
|
118 device->GL_SwapBuffers = DC_GL_SwapBuffers; |
|
119 #endif |
|
120 device->SetCaption = NULL; |
|
121 device->SetIcon = NULL; |
|
122 device->IconifyWindow = NULL; |
|
123 device->GrabInput = NULL; |
|
124 device->GetWMInfo = NULL; |
|
125 device->InitOSKeymap = DC_InitOSKeymap; |
|
126 device->PumpEvents = DC_PumpEvents; |
|
127 |
|
128 device->free = DC_DeleteDevice; |
|
129 |
|
130 return device; |
|
131 } |
|
132 |
|
133 VideoBootStrap DC_bootstrap = { |
|
134 "dcvideo", "Dreamcast Video", |
|
135 DC_Available, DC_CreateDevice |
|
136 }; |
|
137 |
|
138 |
|
139 int DC_VideoInit(_THIS, SDL_PixelFormat *vformat) |
|
140 { |
|
141 /* Determine the screen depth (use default 16-bit depth) */ |
|
142 /* we change this during the SDL_SetVideoMode implementation... */ |
|
143 vformat->BitsPerPixel = 16; |
|
144 vformat->Rmask = 0x0000f800; |
|
145 vformat->Gmask = 0x000007e0; |
|
146 vformat->Bmask = 0x0000001f; |
|
147 |
|
148 /* We're done! */ |
|
149 return(0); |
|
150 } |
|
151 |
|
152 const static SDL_Rect |
|
153 RECT_800x600 = {0,0,800,600}, |
|
154 RECT_640x480 = {0,0,640,480}, |
|
155 RECT_320x240 = {0,0,320,240}; |
|
156 const static SDL_Rect *vid_modes[] = { |
|
157 &RECT_800x600, |
|
158 &RECT_640x480, |
|
159 &RECT_320x240, |
|
160 NULL |
|
161 }; |
|
162 |
|
163 SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) |
|
164 { |
|
165 switch(format->BitsPerPixel) { |
|
166 case 15: |
|
167 case 16: |
|
168 return &vid_modes; |
|
169 case 32: |
|
170 if (!(flags & SDL_OPENGL)) |
|
171 return &vid_modes; |
|
172 default: |
|
173 return NULL; |
|
174 } |
|
175 // return (SDL_Rect **) -1; |
|
176 } |
|
177 |
|
178 pvr_init_params_t params = { |
|
179 /* Enable opaque and translucent polygons with size 16 */ |
|
180 { PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16 }, |
|
181 |
|
182 /* Vertex buffer size */ |
|
183 512*1024 |
|
184 }; |
|
185 |
|
186 #if SDL_VIDEO_OPENGL |
|
187 static int pvr_inited; |
|
188 #endif |
|
189 |
|
190 SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, |
|
191 int width, int height, int bpp, Uint32 flags) |
|
192 { |
|
193 int disp_mode,pixel_mode,pitch; |
|
194 Uint32 Rmask, Gmask, Bmask; |
|
195 |
|
196 if (width==320 && height==240) disp_mode=DM_320x240; |
|
197 else if (width==640 && height==480) disp_mode=DM_640x480; |
|
198 else if (width==800 && height==600) disp_mode=DM_800x608; |
|
199 else { |
|
200 SDL_SetError("Couldn't find requested mode in list"); |
|
201 return(NULL); |
|
202 } |
|
203 |
|
204 switch(bpp) { |
|
205 case 15: pixel_mode = PM_RGB555; pitch = width*2; |
|
206 /* 5-5-5 */ |
|
207 Rmask = 0x00007c00; |
|
208 Gmask = 0x000003e0; |
|
209 Bmask = 0x0000001f; |
|
210 break; |
|
211 case 16: pixel_mode = PM_RGB565; pitch = width*2; |
|
212 /* 5-6-5 */ |
|
213 Rmask = 0x0000f800; |
|
214 Gmask = 0x000007e0; |
|
215 Bmask = 0x0000001f; |
|
216 break; |
|
217 case 24: bpp = 32; |
|
218 case 32: pixel_mode = PM_RGB888; pitch = width*4; |
|
219 Rmask = 0x00ff0000; |
|
220 Gmask = 0x0000ff00; |
|
221 Bmask = 0x000000ff; |
|
222 #if SDL_VIDEO_OPENGL |
|
223 if (!(flags & SDL_OPENGL)) |
|
224 #endif |
|
225 break; |
|
226 default: |
|
227 SDL_SetError("Couldn't find requested mode in list"); |
|
228 return(NULL); |
|
229 } |
|
230 |
|
231 // if ( bpp != current->format->BitsPerPixel ) { |
|
232 if ( ! SDL_ReallocFormat(current, bpp, Rmask, Gmask, Bmask, 0) ) { |
|
233 return(NULL); |
|
234 } |
|
235 // } |
|
236 |
|
237 /* Set up the new mode framebuffer */ |
|
238 current->flags = (SDL_FULLSCREEN|SDL_HWSURFACE); |
|
239 current->w = width; |
|
240 current->h = height; |
|
241 current->pitch = pitch; |
|
242 |
|
243 #if SDL_VIDEO_OPENGL |
|
244 if (pvr_inited) { |
|
245 pvr_inited = 0; |
|
246 pvr_shutdown(); |
|
247 } |
|
248 #endif |
|
249 |
|
250 vid_set_mode(disp_mode,pixel_mode); |
|
251 |
|
252 current->pixels = vram_s; |
|
253 |
|
254 #if SDL_VIDEO_OPENGL |
|
255 if (flags & SDL_OPENGL) { |
|
256 this->gl_config.driver_loaded = 1; |
|
257 current->flags = SDL_FULLSCREEN | SDL_OPENGL; |
|
258 current->pixels = NULL; |
|
259 pvr_inited = 1; |
|
260 pvr_init(¶ms); |
|
261 glKosInit(); |
|
262 glKosBeginFrame(); |
|
263 } else |
|
264 #endif |
|
265 if (flags | SDL_DOUBLEBUF) { |
|
266 current->flags |= SDL_DOUBLEBUF; |
|
267 current->pixels = (void*)((int)current->pixels | 0x400000); |
|
268 } |
|
269 |
|
270 /* We're done */ |
|
271 return(current); |
|
272 } |
|
273 |
|
274 /* We don't actually allow hardware surfaces other than the main one */ |
|
275 static int DC_AllocHWSurface(_THIS, SDL_Surface *surface) |
|
276 { |
|
277 return(-1); |
|
278 } |
|
279 static void DC_FreeHWSurface(_THIS, SDL_Surface *surface) |
|
280 { |
|
281 return; |
|
282 } |
|
283 |
|
284 /* We need to wait for vertical retrace on page flipped displays */ |
|
285 static int DC_LockHWSurface(_THIS, SDL_Surface *surface) |
|
286 { |
|
287 return(0); |
|
288 } |
|
289 |
|
290 static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface) |
|
291 { |
|
292 return; |
|
293 } |
|
294 |
|
295 static int DC_FlipHWSurface(_THIS, SDL_Surface *surface) |
|
296 { |
|
297 if (surface->flags & SDL_DOUBLEBUF) { |
|
298 vid_set_start((int)surface->pixels & 0xffffff); |
|
299 surface->pixels = (void*)((int)surface->pixels ^ 0x400000); |
|
300 } |
|
301 return(0); |
|
302 } |
|
303 |
|
304 static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects) |
|
305 { |
|
306 /* do nothing. */ |
|
307 } |
|
308 |
|
309 static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) |
|
310 { |
|
311 /* do nothing of note. */ |
|
312 return(1); |
|
313 } |
|
314 |
|
315 /* Note: If we are terminated, this could be called in the middle of |
|
316 another SDL video routine -- notably UpdateRects. |
|
317 */ |
|
318 static void DC_VideoQuit(_THIS) |
|
319 { |
|
320 #if SDL_VIDEO_OPENGL |
|
321 if (pvr_inited) { |
|
322 pvr_inited = 0; |
|
323 pvr_shutdown(); |
|
324 } |
|
325 #endif |
|
326 } |
|
327 |
|
328 #if SDL_VIDEO_OPENGL |
|
329 |
|
330 void dmyfunc(void) {} |
|
331 |
|
332 typedef void (*funcptr)(); |
|
333 const static struct { |
|
334 char *name; |
|
335 funcptr addr; |
|
336 } glfuncs[] = { |
|
337 #define DEF(func) {#func,&func} |
|
338 DEF(glBegin), |
|
339 DEF(glBindTexture), |
|
340 DEF(glBlendFunc), |
|
341 DEF(glColor4f), |
|
342 // DEF(glCopyImageID), |
|
343 DEF(glDisable), |
|
344 DEF(glEnable), |
|
345 DEF(glEnd), |
|
346 DEF(glFlush), |
|
347 DEF(glGenTextures), |
|
348 DEF(glGetString), |
|
349 DEF(glLoadIdentity), |
|
350 DEF(glMatrixMode), |
|
351 DEF(glOrtho), |
|
352 DEF(glPixelStorei), |
|
353 // DEF(glPopAttrib), |
|
354 // DEF(glPopClientAttrib), |
|
355 {"glPopAttrib",&dmyfunc}, |
|
356 {"glPopClientAttrib",&dmyfunc}, |
|
357 DEF(glPopMatrix), |
|
358 // DEF(glPushAttrib), |
|
359 // DEF(glPushClientAttrib), |
|
360 {"glPushAttrib",&dmyfunc}, |
|
361 {"glPushClientAttrib",&dmyfunc}, |
|
362 DEF(glPushMatrix), |
|
363 DEF(glTexCoord2f), |
|
364 DEF(glTexEnvf), |
|
365 DEF(glTexImage2D), |
|
366 DEF(glTexParameteri), |
|
367 DEF(glTexSubImage2D), |
|
368 DEF(glVertex2i), |
|
369 DEF(glViewport), |
|
370 #undef DEF |
|
371 }; |
|
372 |
|
373 static void *DC_GL_GetProcAddress(_THIS, const char *proc) |
|
374 { |
|
375 void *ret; |
|
376 int i; |
|
377 |
|
378 ret = glKosGetProcAddress(proc); |
|
379 if (ret) return ret; |
|
380 |
|
381 for(i=0;i<sizeof(glfuncs)/sizeof(glfuncs[0]);i++) { |
|
382 if (SDL_strcmp(proc,glfuncs[i].name)==0) return glfuncs[i].addr; |
|
383 } |
|
384 |
|
385 return NULL; |
|
386 } |
|
387 |
|
388 static int DC_GL_LoadLibrary(_THIS, const char *path) |
|
389 { |
|
390 this->gl_config.driver_loaded = 1; |
|
391 |
|
392 return 0; |
|
393 } |
|
394 |
|
395 static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) |
|
396 { |
|
397 GLenum mesa_attrib; |
|
398 int val; |
|
399 |
|
400 switch(attrib) { |
|
401 case SDL_GL_RED_SIZE: |
|
402 val = 5; |
|
403 break; |
|
404 case SDL_GL_GREEN_SIZE: |
|
405 val = 6; |
|
406 break; |
|
407 case SDL_GL_BLUE_SIZE: |
|
408 val = 5; |
|
409 break; |
|
410 case SDL_GL_ALPHA_SIZE: |
|
411 val = 0; |
|
412 break; |
|
413 case SDL_GL_DOUBLEBUFFER: |
|
414 val = 1; |
|
415 break; |
|
416 case SDL_GL_DEPTH_SIZE: |
|
417 val = 16; /* or 32? */ |
|
418 break; |
|
419 case SDL_GL_STENCIL_SIZE: |
|
420 val = 0; |
|
421 break; |
|
422 case SDL_GL_ACCUM_RED_SIZE: |
|
423 val = 0; |
|
424 break; |
|
425 case SDL_GL_ACCUM_GREEN_SIZE: |
|
426 val = 0; |
|
427 case SDL_GL_ACCUM_BLUE_SIZE: |
|
428 val = 0; |
|
429 break; |
|
430 case SDL_GL_ACCUM_ALPHA_SIZE: |
|
431 val = 0; |
|
432 break; |
|
433 default : |
|
434 return -1; |
|
435 } |
|
436 *value = val; |
|
437 return 0; |
|
438 } |
|
439 |
|
440 static void DC_GL_SwapBuffers(_THIS) |
|
441 { |
|
442 glKosFinishFrame(); |
|
443 glKosBeginFrame(); |
|
444 } |
|
445 #endif |