Home | History | Annotate | Download | only in dc
      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(&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
    446