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