handle src buffer underflow corner cases
[sdl_omap.git] / src / video / dc / SDL_dcvideo.c
CommitLineData
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 */
39static int DC_VideoInit(_THIS, SDL_PixelFormat *vformat);
40static SDL_Rect **DC_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
41static SDL_Surface *DC_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
42static int DC_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
43static void DC_VideoQuit(_THIS);
44
45/* Hardware surface functions */
46static int DC_AllocHWSurface(_THIS, SDL_Surface *surface);
47static int DC_LockHWSurface(_THIS, SDL_Surface *surface);
48static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface);
49static void DC_FreeHWSurface(_THIS, SDL_Surface *surface);
50static int DC_FlipHWSurface(_THIS, SDL_Surface *surface);
51
52/* etc. */
53static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
54
55/* OpenGL */
56#if SDL_VIDEO_OPENGL
57static void *DC_GL_GetProcAddress(_THIS, const char *proc);
58static int DC_GL_LoadLibrary(_THIS, const char *path);
59static int DC_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value);
60static void DC_GL_SwapBuffers(_THIS);
61#endif
62
63/* DC driver bootstrap functions */
64
65static int DC_Available(void)
66{
67 return 1;
68}
69
70static void DC_DeleteDevice(SDL_VideoDevice *device)
71{
72 SDL_free(device->hidden);
73 SDL_free(device);
74}
75
76static 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
133VideoBootStrap DC_bootstrap = {
134 "dcvideo", "Dreamcast Video",
135 DC_Available, DC_CreateDevice
136};
137
138
139int 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
152const static SDL_Rect
153 RECT_800x600 = {0,0,800,600},
154 RECT_640x480 = {0,0,640,480},
155 RECT_320x240 = {0,0,320,240};
156const static SDL_Rect *vid_modes[] = {
157 &RECT_800x600,
158 &RECT_640x480,
159 &RECT_320x240,
160 NULL
161};
162
163SDL_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
178pvr_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
187static int pvr_inited;
188#endif
189
190SDL_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 */
275static int DC_AllocHWSurface(_THIS, SDL_Surface *surface)
276{
277 return(-1);
278}
279static void DC_FreeHWSurface(_THIS, SDL_Surface *surface)
280{
281 return;
282}
283
284/* We need to wait for vertical retrace on page flipped displays */
285static int DC_LockHWSurface(_THIS, SDL_Surface *surface)
286{
287 return(0);
288}
289
290static void DC_UnlockHWSurface(_THIS, SDL_Surface *surface)
291{
292 return;
293}
294
295static 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
304static void DC_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
305{
306 /* do nothing. */
307}
308
309static 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*/
318static 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
330void dmyfunc(void) {}
331
332typedef void (*funcptr)();
333const 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
373static 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
388static int DC_GL_LoadLibrary(_THIS, const char *path)
389{
390 this->gl_config.driver_loaded = 1;
391
392 return 0;
393}
394
395static 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
440static void DC_GL_SwapBuffers(_THIS)
441{
442 glKosFinishFrame();
443 glKosBeginFrame();
444}
445#endif