symbian-qemu-0.9.1-12/libsdl-trunk/src/video/picogui/SDL_pgvideo.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2     SDL - Simple DirectMedia Layer
       
     3     Copyright (C) 1997-2006 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     Micah Dowty
       
    23     micahjd@users.sourceforge.net
       
    24 */
       
    25 #include "SDL_config.h"
       
    26 
       
    27 #include "SDL_video.h"
       
    28 #include "SDL_mouse.h"
       
    29 #include "../SDL_sysvideo.h"
       
    30 #include "../SDL_pixels_c.h"
       
    31 #include "../../events/SDL_events_c.h"
       
    32 
       
    33 #include "SDL_pgvideo.h"
       
    34 #include "SDL_pgevents_c.h"
       
    35 
       
    36 #define PGVID_DRIVER_NAME "picogui"
       
    37 
       
    38 /* Initialization/Query functions */
       
    39 static int PG_VideoInit(_THIS, SDL_PixelFormat *vformat);
       
    40 static SDL_Rect **PG_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
       
    41 static SDL_Surface *PG_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
       
    42 static int PG_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
       
    43 static void PG_VideoQuit(_THIS);
       
    44 
       
    45 /* Hardware surface functions */
       
    46 static int PG_AllocHWSurface(_THIS, SDL_Surface *surface);
       
    47 static int PG_LockHWSurface(_THIS, SDL_Surface *surface);
       
    48 static void PG_UnlockHWSurface(_THIS, SDL_Surface *surface);
       
    49 static void PG_FreeHWSurface(_THIS, SDL_Surface *surface);
       
    50 
       
    51 /* etc. */
       
    52 static void PG_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
       
    53 
       
    54 // The implementation dependent data for the window manager cursor
       
    55 struct WMcursor {
       
    56   /* Our cursor is a PicoGUI theme */
       
    57   pghandle theme;
       
    58 } ;
       
    59 
       
    60 /* WM functions */
       
    61 void PG_SetCaption(_THIS, const char *title, const char *icon);
       
    62 WMcursor * PG_CreateWMCursor (_THIS,Uint8 * data, Uint8 * mask, 
       
    63 			      int w, int h, int hot_x, int hot_y);
       
    64 void PG_FreeWMCursor (_THIS, WMcursor * cursor);
       
    65 void PG_WarpWMCursor(_THIS, Uint16 x, Uint16 y);
       
    66 int PG_ShowWMCursor (_THIS, WMcursor * cursor);
       
    67 
       
    68 /* PicoGUI driver bootstrap functions */
       
    69 
       
    70 static int PG_Available(void)
       
    71 {
       
    72         /* FIXME: The current client lib doesn't give a way to see if the picogui
       
    73 	 *        server is reachable without causing a fatal error if it isn't.
       
    74 	 *        This should be fixed in cli_c2, but until then assume we can
       
    75 	 *        connect. Since more common drivers like X11 are probed first anyway,
       
    76 	 *        this shouldn't be a huge problem.
       
    77 	 */
       
    78 	return(1);
       
    79 }
       
    80 
       
    81 static void PG_DeleteDevice(SDL_VideoDevice *device)
       
    82 {
       
    83 	SDL_free(device->hidden);
       
    84 	SDL_free(device);
       
    85 }
       
    86 
       
    87 static SDL_VideoDevice *PG_CreateDevice(int devindex)
       
    88 {
       
    89 	SDL_VideoDevice *device;
       
    90 
       
    91 	/* Initialize all variables that we clean on shutdown */
       
    92 	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
       
    93 	if ( device ) {
       
    94 		SDL_memset(device, 0, (sizeof *device));
       
    95 		device->hidden = (struct SDL_PrivateVideoData *)
       
    96 				SDL_malloc((sizeof *device->hidden));
       
    97 	}
       
    98 	if ( (device == NULL) || (device->hidden == NULL) ) {
       
    99 		SDL_OutOfMemory();
       
   100 		if ( device ) {
       
   101 			SDL_free(device);
       
   102 		}
       
   103 		return(0);
       
   104 	}
       
   105 	SDL_memset(device->hidden, 0, (sizeof *device->hidden));
       
   106 
       
   107 	/* Set the function pointers */
       
   108 	device->VideoInit = PG_VideoInit;
       
   109 	device->ListModes = PG_ListModes;
       
   110 	device->SetVideoMode = PG_SetVideoMode;
       
   111 	device->CreateYUVOverlay = NULL;
       
   112 	device->SetColors = PG_SetColors;
       
   113 	device->UpdateRects = PG_UpdateRects;
       
   114 	device->VideoQuit = PG_VideoQuit;
       
   115 	device->AllocHWSurface = PG_AllocHWSurface;
       
   116 	device->CheckHWBlit = NULL;
       
   117 	device->FillHWRect = NULL;
       
   118 	device->SetHWColorKey = NULL;
       
   119 	device->SetHWAlpha = NULL;
       
   120 	device->LockHWSurface = PG_LockHWSurface;
       
   121 	device->UnlockHWSurface = PG_UnlockHWSurface;
       
   122 	device->FlipHWSurface = NULL;
       
   123 	device->FreeHWSurface = PG_FreeHWSurface;
       
   124 	device->SetCaption = PG_SetCaption;
       
   125 	device->SetIcon = NULL;
       
   126 	device->IconifyWindow = NULL;
       
   127 	device->GrabInput = NULL;
       
   128 
       
   129 	device->PumpEvents = PG_PumpEvents;
       
   130 	device->InitOSKeymap = PG_InitOSKeymap;
       
   131 
       
   132 	device->ShowWMCursor = PG_ShowWMCursor;
       
   133 	device->CreateWMCursor = PG_CreateWMCursor;
       
   134 	device->FreeWMCursor = PG_FreeWMCursor;
       
   135 	device->WarpWMCursor = PG_WarpWMCursor;
       
   136 
       
   137 	device->free = PG_DeleteDevice;
       
   138 
       
   139 	return device;
       
   140 }
       
   141 
       
   142 VideoBootStrap PG_bootstrap = {
       
   143 	PGVID_DRIVER_NAME, "PicoGUI SDL driver",
       
   144 	PG_Available, PG_CreateDevice
       
   145 };
       
   146 
       
   147 
       
   148 int PG_VideoInit(_THIS, SDL_PixelFormat *vformat)
       
   149 {
       
   150         /* Connect to the PicoGUI server. No way to process command line args yet,
       
   151 	 * but since this is based on SHM it's not important to be able to specify
       
   152 	 * a remote PicoGUI server.
       
   153 	 *
       
   154 	 * FIXME: Another nitpick about the current client lib is there's no
       
   155 	 *        clean way to indicate that command line args are not available.
       
   156 	 */
       
   157         pgInit(0,(char**)"");
       
   158 	this->hidden->mi = *pgGetVideoMode();
       
   159 
       
   160 	/* Create a picogui application and canvas. We'll populate the canvas later. */
       
   161 	this->hidden->wApp = pgRegisterApp(PG_APP_NORMAL,"SDL",0);
       
   162 	this->hidden->wCanvas = pgNewWidget(PG_WIDGET_CANVAS,0,0);
       
   163 	pgSetWidget(PGDEFAULT,
       
   164 		    PG_WP_SIDE, PG_S_ALL,
       
   165 		    0);
       
   166 
       
   167 	PG_InitEvents(this);
       
   168 
       
   169 	/* Determine the current screen size */
       
   170 	this->info.current_w = this->hidden->mi.lxres;
       
   171 	this->info.current_h = this->hidden->mi.lyres;
       
   172 
       
   173 	/* Determine the screen depth.
       
   174 	 * We change this during the SDL_SetVideoMode implementation... 
       
   175 	 * Round up to the nearest Bytes per pixel
       
   176 	 */
       
   177 	vformat->BitsPerPixel = this->hidden->mi.bpp;
       
   178 	vformat->BytesPerPixel = this->hidden->mi.bpp >> 3;
       
   179 	if (this->hidden->mi.bpp & 7)
       
   180 	  vformat->BytesPerPixel++;
       
   181 
       
   182 	/* We're done! */
       
   183 	return(0);
       
   184 }
       
   185 
       
   186 SDL_Rect **PG_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
       
   187 {
       
   188    	 return (SDL_Rect **) -1;
       
   189 }
       
   190 
       
   191 SDL_Surface *PG_SetVideoMode(_THIS, SDL_Surface *current,
       
   192 				int width, int height, int bpp, Uint32 flags)
       
   193 {
       
   194 	if ( this->hidden->bitmap ) {
       
   195 	  /* Free old bitmap */
       
   196 	  if (current->pixels) {
       
   197 	    shmdt(current->pixels);
       
   198 	    current->pixels = NULL;
       
   199 	  }
       
   200 	  pgDelete(this->hidden->bitmap);
       
   201 	}
       
   202 
       
   203 	/* Allocate the new pixel format for the screen */
       
   204 	if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) {
       
   205 		SDL_SetError("Couldn't allocate new pixel format for requested mode");
       
   206 		return(NULL);
       
   207 	}
       
   208 
       
   209 	/* Create a new picogui bitmap */
       
   210 	this->hidden->bitmap = pgCreateBitmap(width,height);
       
   211 	this->hidden->shm = *pgMakeSHMBitmap(this->hidden->bitmap);
       
   212 	current->pixels = shmat(shmget(this->hidden->shm.shm_key,
       
   213 				       this->hidden->shm.shm_length,0),NULL,0);
       
   214 
       
   215 	/* Reset the canvas, and draw persistent and incremental grops.
       
   216 	 * Use mapping and offsets to center it.
       
   217 	 */
       
   218 
       
   219 	pgWriteCmd(this->hidden->wCanvas, PGCANVAS_NUKE, 0);
       
   220 
       
   221 	/* 0. Set the source position during incremental rendering
       
   222 	 */
       
   223 	pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 5, PG_GROP_SETSRC,0,0,0,0);
       
   224 	pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROPFLAGS, 1, PG_GROPF_INCREMENTAL);
       
   225 
       
   226 	/* 1. Incremental bitmap rendering
       
   227 	 */
       
   228 	pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 6, PG_GROP_BITMAP,
       
   229 		   0,0,0,0,this->hidden->bitmap);
       
   230 	pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROPFLAGS, 1, PG_GROPF_INCREMENTAL);
       
   231 
       
   232 	/* 2. Normal bitmap rendering
       
   233 	 */
       
   234 	pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 6, PG_GROP_BITMAP,
       
   235 		   0,0,this->hidden->shm.width,this->hidden->shm.height,this->hidden->bitmap);
       
   236      
       
   237 	/* Set up the new mode framebuffer */
       
   238 	current->flags = 0;
       
   239 	current->w = this->hidden->shm.width;
       
   240 	current->h = this->hidden->shm.height;
       
   241 	current->pitch = this->hidden->shm.pitch;
       
   242 
       
   243 	/* Set up pixel format */
       
   244 	current->format->BitsPerPixel = this->hidden->shm.bpp;
       
   245 	current->format->BytesPerPixel = this->hidden->shm.bpp >> 3;
       
   246 	if (this->hidden->shm.bpp & 7)
       
   247 	  current->format->BytesPerPixel++;
       
   248 	current->format->palette = NULL;
       
   249 	current->format->Rmask = this->hidden->shm.red_mask;
       
   250 	current->format->Gmask = this->hidden->shm.green_mask;
       
   251 	current->format->Bmask = this->hidden->shm.blue_mask;
       
   252 	current->format->Amask = this->hidden->shm.alpha_mask;
       
   253 	current->format->Rshift = this->hidden->shm.red_shift;
       
   254 	current->format->Gshift = this->hidden->shm.green_shift;
       
   255 	current->format->Bshift = this->hidden->shm.blue_shift;
       
   256 	current->format->Ashift = this->hidden->shm.alpha_shift;
       
   257 	current->format->Rloss = 8 - this->hidden->shm.red_length;
       
   258 	current->format->Gloss = 8 - this->hidden->shm.green_length;
       
   259 	current->format->Bloss = 8 - this->hidden->shm.blue_length;
       
   260 	current->format->Aloss = 8 - this->hidden->shm.alpha_length;
       
   261 
       
   262 	/* Draw the app */
       
   263 	pgUpdate();
       
   264 
       
   265 	/* We're done */
       
   266 	return(current);
       
   267 }
       
   268 
       
   269 /* We don't actually allow hardware surfaces other than the main one */
       
   270 static int PG_AllocHWSurface(_THIS, SDL_Surface *surface)
       
   271 {
       
   272 	return(-1);
       
   273 }
       
   274 static void PG_FreeHWSurface(_THIS, SDL_Surface *surface)
       
   275 {
       
   276 	return;
       
   277 }
       
   278 
       
   279 /* We need to wait for vertical retrace on page flipped displays */
       
   280 static int PG_LockHWSurface(_THIS, SDL_Surface *surface)
       
   281 {
       
   282 	return(0);
       
   283 }
       
   284 
       
   285 static void PG_UnlockHWSurface(_THIS, SDL_Surface *surface)
       
   286 {
       
   287 	return;
       
   288 }
       
   289 
       
   290 static void PG_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
       
   291 {
       
   292         int i;
       
   293 	
       
   294 	for (i = 0; i < numrects; i++) {
       
   295 	        if (rects[i].w <= 0 || rects[i].h <= 0)
       
   296 		  continue;
       
   297 
       
   298 		/* Schedule an incremental update for this rectangle, using
       
   299 		 * the canvas gropnodes we've loaded beforehand.
       
   300 		 */
       
   301 		pgWriteCmd(this->hidden->wCanvas, PGCANVAS_FINDGROP, 1, 0);
       
   302 		pgWriteCmd(this->hidden->wCanvas, PGCANVAS_MOVEGROP, 4, 
       
   303 			   rects[i].x, rects[i].y,
       
   304 			   rects[i].w, rects[i].h);
       
   305 		pgWriteCmd(this->hidden->wCanvas, PGCANVAS_FINDGROP, 1, 1);
       
   306 		pgWriteCmd(this->hidden->wCanvas, PGCANVAS_MOVEGROP, 4, 
       
   307 			   rects[i].x, rects[i].y,
       
   308 			   rects[i].w, rects[i].h);
       
   309 		
       
   310 		/* Go perform the update */
       
   311 		pgWriteCmd(this->hidden->wCanvas, PGCANVAS_INCREMENTAL, 0);
       
   312 		pgSubUpdate(this->hidden->wCanvas);
       
   313 	}
       
   314 }
       
   315 
       
   316 int PG_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
       
   317 {
       
   318 	/* do nothing of note. */
       
   319 	return(1);
       
   320 }
       
   321 
       
   322 /* Note:  If we are terminated, this could be called in the middle of
       
   323    another SDL video routine -- notably UpdateRects.
       
   324 */
       
   325 void PG_VideoQuit(_THIS)
       
   326 {
       
   327 	if (this->screen->pixels != NULL)
       
   328 	{
       
   329 		shmdt(this->screen->pixels);
       
   330 		this->screen->pixels = NULL;
       
   331 		pgDelete(this->hidden->bitmap);
       
   332 	}
       
   333 	pgDelete(this->hidden->wCanvas);
       
   334 	pgDelete(this->hidden->wApp);
       
   335 }
       
   336 
       
   337 void PG_SetCaption(_THIS, const char *title, const char *icon)
       
   338 {
       
   339         if (title != NULL)
       
   340 	  pgReplaceText(this->hidden->wApp, title);
       
   341 	pgUpdate();
       
   342 }
       
   343 
       
   344 /* FIXME: The cursor stuff isn't implemented yet! */
       
   345 
       
   346 WMcursor * PG_CreateWMCursor (_THIS,Uint8 * data, Uint8 * mask, 
       
   347 			      int w, int h, int hot_x, int hot_y)
       
   348 {
       
   349         static WMcursor dummy;
       
   350         return &dummy;
       
   351 }
       
   352 
       
   353 void PG_FreeWMCursor (_THIS, WMcursor * cursor)
       
   354 {
       
   355 }
       
   356 
       
   357 void PG_WarpWMCursor(_THIS, Uint16 x, Uint16 y)
       
   358 {
       
   359 }
       
   360 
       
   361 int PG_ShowWMCursor (_THIS, WMcursor * cursor)
       
   362 {
       
   363         return 1;
       
   364 }