e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 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 |