SDL-1.2.14
[sdl_omap.git] / src / video / dc / SDL_dcvideo.c
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(&params);
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