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 (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 /* GGI-based SDL video driver implementation. 25 */ 26 27 #include <fcntl.h> 28 #include <unistd.h> 29 #include <sys/mman.h> 30 31 #include <ggi/ggi.h> 32 #include <ggi/gii.h> 33 34 #include "SDL_video.h" 35 #include "SDL_mouse.h" 36 #include "../SDL_sysvideo.h" 37 #include "../SDL_pixels_c.h" 38 #include "../../events/SDL_events_c.h" 39 #include "SDL_ggivideo.h" 40 #include "SDL_ggimouse_c.h" 41 #include "SDL_ggievents_c.h" 42 43 44 struct private_hwdata 45 { 46 ggi_visual_t vis; 47 }; 48 49 ggi_visual_t VIS; 50 51 /* Initialization/Query functions */ 52 static int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat); 53 static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 54 static SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 55 static int GGI_SetColors(_THIS, int firstcolor, int ncolors, 56 SDL_Color *colors); 57 static void GGI_VideoQuit(_THIS); 58 59 /* Hardware surface functions */ 60 static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface); 61 static int GGI_LockHWSurface(_THIS, SDL_Surface *surface); 62 static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface); 63 static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface); 64 65 /* GGI driver bootstrap functions */ 66 67 static int GGI_Available(void) 68 { 69 ggi_visual_t *vis; 70 71 vis = NULL; 72 if (ggiInit() == 0) { 73 vis = ggiOpen(NULL); 74 if (vis != NULL) { 75 ggiClose(vis); 76 } 77 } 78 return (vis != NULL); 79 } 80 81 static void GGI_DeleteDevice(SDL_VideoDevice *device) 82 { 83 SDL_free(device->hidden); 84 SDL_free(device); 85 } 86 87 static SDL_VideoDevice *GGI_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 = GGI_VideoInit; 109 device->ListModes = GGI_ListModes; 110 device->SetVideoMode = GGI_SetVideoMode; 111 device->SetColors = GGI_SetColors; 112 device->UpdateRects = NULL; 113 device->VideoQuit = GGI_VideoQuit; 114 device->AllocHWSurface = GGI_AllocHWSurface; 115 device->CheckHWBlit = NULL; 116 device->FillHWRect = NULL; 117 device->SetHWColorKey = NULL; 118 device->SetHWAlpha = NULL; 119 device->LockHWSurface = GGI_LockHWSurface; 120 device->UnlockHWSurface = GGI_UnlockHWSurface; 121 device->FlipHWSurface = NULL; 122 device->FreeHWSurface = GGI_FreeHWSurface; 123 device->SetCaption = NULL; 124 device->SetIcon = NULL; 125 device->IconifyWindow = NULL; 126 device->GrabInput = NULL; 127 device->GetWMInfo = NULL; 128 device->InitOSKeymap = GGI_InitOSKeymap; 129 device->PumpEvents = GGI_PumpEvents; 130 131 device->free = GGI_DeleteDevice; 132 133 return device; 134 } 135 136 VideoBootStrap GGI_bootstrap = { 137 "ggi", "General Graphics Interface (GGI)", 138 GGI_Available, GGI_CreateDevice 139 }; 140 141 142 static SDL_Rect video_mode; 143 static SDL_Rect *SDL_modelist[4] = { NULL, NULL, NULL, NULL }; 144 145 int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat) 146 { 147 ggi_mode mode = 148 { 149 1, 150 { GGI_AUTO, GGI_AUTO }, 151 { GGI_AUTO, GGI_AUTO }, 152 { 0, 0 }, 153 GT_AUTO, 154 { GGI_AUTO, GGI_AUTO } 155 }; 156 struct private_hwdata *priv; 157 ggi_color pal[256], map[256]; 158 const ggi_directbuffer *db; 159 int err, num_bufs; 160 ggi_pixel white, black; 161 162 priv = SDL_malloc(sizeof(struct private_hwdata)); 163 if (priv == NULL) 164 { 165 SDL_SetError("Unhandled GGI mode type!\n"); 166 GGI_VideoQuit(NULL); 167 } 168 169 if (ggiInit() != 0) 170 { 171 SDL_SetError("Unable to initialize GGI!\n"); 172 GGI_VideoQuit(NULL); 173 } 174 175 VIS = ggiOpen(NULL); 176 if (VIS == NULL) 177 { 178 SDL_SetError("Unable to open default GGI visual!\n"); 179 ggiExit(); 180 GGI_VideoQuit(NULL); 181 } 182 183 ggiSetFlags(VIS, GGIFLAG_ASYNC); 184 185 /* Validate mode, autodetecting any GGI_AUTO or GT_AUTO fields */ 186 ggiCheckMode(VIS, &mode); 187 188 /* At this point we should have a valid mode - try to set it */ 189 err = ggiSetMode(VIS, &mode); 190 191 /* If we couldn't set _any_ modes, something is very wrong */ 192 if (err) 193 { 194 SDL_SetError("Can't set a mode!\n"); 195 ggiClose(VIS); 196 ggiExit(); 197 GGI_VideoQuit(NULL); 198 } 199 200 /* Determine the current screen size */ 201 this->info.current_w = mode.virt.x; 202 this->info.current_h = mode.virt.y; 203 204 /* Set a palette for palletized modes */ 205 if (GT_SCHEME(mode.graphtype) == GT_PALETTE) 206 { 207 ggiSetColorfulPalette(VIS); 208 ggiGetPalette(VIS, 0, 1 << vformat->BitsPerPixel, pal); 209 } 210 211 /* Now we try to get the DirectBuffer info, which determines whether 212 * SDL can access hardware surfaces directly. */ 213 214 num_bufs = ggiDBGetNumBuffers(VIS); 215 216 if (num_bufs > 0) 217 { 218 db = ggiDBGetBuffer(VIS, 0); /* Only handle one DB for now */ 219 220 vformat->BitsPerPixel = db->buffer.plb.pixelformat->depth; 221 222 vformat->Rmask = db->buffer.plb.pixelformat->red_mask; 223 vformat->Gmask = db->buffer.plb.pixelformat->green_mask; 224 vformat->Bmask = db->buffer.plb.pixelformat->blue_mask; 225 226 /* Fill in our hardware acceleration capabilities */ 227 228 this->info.wm_available = 0; 229 this->info.hw_available = 1; 230 this->info.video_mem = db->buffer.plb.stride * mode.virt.y; 231 } 232 233 video_mode.x = 0; 234 video_mode.y = 0; 235 video_mode.w = mode.virt.x; 236 video_mode.h = mode.virt.y; 237 SDL_modelist[((vformat->BitsPerPixel + 7) / 8) - 1] = &video_mode; 238 239 /* We're done! */ 240 return(0); 241 } 242 243 static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) 244 { 245 return(&SDL_modelist[((format->BitsPerPixel + 7) / 8) - 1]); 246 } 247 248 /* Various screen update functions available */ 249 static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); 250 251 SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) 252 { 253 ggi_mode mode = 254 { 255 1, 256 { GGI_AUTO, GGI_AUTO }, 257 { GGI_AUTO, GGI_AUTO }, 258 { 0, 0 }, 259 GT_AUTO, 260 { GGI_AUTO, GGI_AUTO } 261 }; 262 const ggi_directbuffer *db; 263 ggi_color pal[256]; 264 int err; 265 266 fprintf(stderr, "GGI_SetVideoMode()\n"); 267 268 mode.visible.x = mode.virt.x = width; 269 mode.visible.y = mode.virt.y = height; 270 271 /* Translate requested SDL bit depth into a GGI mode */ 272 switch (bpp) 273 { 274 case 1: mode.graphtype = GT_1BIT; break; 275 case 2: mode.graphtype = GT_2BIT; break; 276 case 4: mode.graphtype = GT_4BIT; break; 277 case 8: mode.graphtype = GT_8BIT; break; 278 case 15: mode.graphtype = GT_15BIT; break; 279 case 16: mode.graphtype = GT_16BIT; break; 280 case 24: mode.graphtype = GT_24BIT; break; 281 case 32: mode.graphtype = GT_32BIT; break; 282 default: 283 SDL_SetError("Unknown SDL bit depth, using GT_AUTO....\n"); 284 mode.graphtype = GT_AUTO; 285 } 286 287 /* Validate mode, autodetecting any GGI_AUTO or GT_AUTO fields */ 288 ggiCheckMode(VIS, &mode); 289 290 /* At this point we should have a valid mode - try to set it */ 291 err = ggiSetMode(VIS, &mode); 292 293 /* If we couldn't set _any_ modes, something is very wrong */ 294 if (err) 295 { 296 SDL_SetError("Can't set a mode!\n"); 297 ggiClose(VIS); 298 ggiExit(); 299 GGI_VideoQuit(NULL); 300 } 301 302 /* Set a palette for palletized modes */ 303 if (GT_SCHEME(mode.graphtype) == GT_PALETTE) 304 { 305 ggiSetColorfulPalette(VIS); 306 ggiGetPalette(VIS, 0, 1 << bpp, pal); 307 } 308 309 db = ggiDBGetBuffer(VIS, 0); 310 311 /* Set up the new mode framebuffer */ 312 current->flags = (SDL_FULLSCREEN | SDL_HWSURFACE); 313 current->w = mode.virt.x; 314 current->h = mode.virt.y; 315 current->pitch = db->buffer.plb.stride; 316 current->pixels = db->read; 317 318 /* Set the blit function */ 319 this->UpdateRects = GGI_DirectUpdate; 320 321 /* We're done */ 322 return(current); 323 } 324 325 static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface) 326 { 327 return(-1); 328 } 329 static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface) 330 { 331 return; 332 } 333 static int GGI_LockHWSurface(_THIS, SDL_Surface *surface) 334 { 335 return(0); 336 } 337 static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface) 338 { 339 return; 340 } 341 342 static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) 343 { 344 int i; 345 346 /* ggiFlush(VIS); */ 347 348 for (i = 0; i < numrects; i++) 349 { 350 ggiFlushRegion(VIS, rects[i].x, rects[i].y, rects[i].w, rects[i].h); 351 } 352 return; 353 } 354 355 int GGI_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 356 { 357 int i; 358 ggi_color pal[256]; 359 360 /* Set up the colormap */ 361 for (i = 0; i < ncolors; i++) 362 { 363 pal[i].r = (colors[i].r << 8) | colors[i].r; 364 pal[i].g = (colors[i].g << 8) | colors[i].g; 365 pal[i].b = (colors[i].b << 8) | colors[i].b; 366 } 367 368 ggiSetPalette(VIS, firstcolor, ncolors, pal); 369 370 return 1; 371 } 372 373 void GGI_VideoQuit(_THIS) 374 { 375 } 376 void GGI_FinalQuit(void) 377 { 378 } 379