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@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 44struct private_hwdata 45{ 46 ggi_visual_t vis; 47}; 48 49ggi_visual_t VIS; 50 51/* Initialization/Query functions */ 52static int GGI_VideoInit(_THIS, SDL_PixelFormat *vformat); 53static SDL_Rect **GGI_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 54static SDL_Surface *GGI_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 55static int GGI_SetColors(_THIS, int firstcolor, int ncolors, 56 SDL_Color *colors); 57static void GGI_VideoQuit(_THIS); 58 59/* Hardware surface functions */ 60static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface); 61static int GGI_LockHWSurface(_THIS, SDL_Surface *surface); 62static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface); 63static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface); 64 65/* GGI driver bootstrap functions */ 66 67static 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 81static void GGI_DeleteDevice(SDL_VideoDevice *device) 82{ 83 SDL_free(device->hidden); 84 SDL_free(device); 85} 86 87static 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 136VideoBootStrap GGI_bootstrap = { 137 "ggi", "General Graphics Interface (GGI)", 138 GGI_Available, GGI_CreateDevice 139}; 140 141 142static SDL_Rect video_mode; 143static SDL_Rect *SDL_modelist[4] = { NULL, NULL, NULL, NULL }; 144 145int 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 243static 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 */ 249static void GGI_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); 250 251SDL_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 325static int GGI_AllocHWSurface(_THIS, SDL_Surface *surface) 326{ 327 return(-1); 328} 329static void GGI_FreeHWSurface(_THIS, SDL_Surface *surface) 330{ 331 return; 332} 333static int GGI_LockHWSurface(_THIS, SDL_Surface *surface) 334{ 335 return(0); 336} 337static void GGI_UnlockHWSurface(_THIS, SDL_Surface *surface) 338{ 339 return; 340} 341 342static 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 355int 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 373void GGI_VideoQuit(_THIS) 374{ 375} 376void GGI_FinalQuit(void) 377{ 378} 379