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 MGA CRTC2 support by Thomas Jarosch - tomj (at) simonv.com 23 CRTC2 support is inspired by mplayer's dfbmga driver 24 written by Ville Syrj<syrjala (at) sci.fi> 25 */ 26 #include "SDL_config.h" 27 28 /* DirectFB video driver implementation. 29 */ 30 31 #include <fcntl.h> 32 #include <unistd.h> 33 #include <sys/mman.h> 34 35 #include <directfb.h> 36 #include <directfb_version.h> 37 38 #include "SDL_video.h" 39 #include "SDL_mouse.h" 40 #include "../SDL_sysvideo.h" 41 #include "../SDL_pixels_c.h" 42 #include "../../events/SDL_events_c.h" 43 #include "SDL_DirectFB_video.h" 44 #include "SDL_DirectFB_events.h" 45 #include "SDL_DirectFB_yuv.h" 46 47 /* The implementation dependent data for the window manager cursor */ 48 struct WMcursor { 49 int unused; 50 }; 51 52 53 /* Initialization/Query functions */ 54 static int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat); 55 static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 56 static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 57 static int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, 58 SDL_Color *colors); 59 static void DirectFB_VideoQuit(_THIS); 60 61 /* Hardware surface functions */ 62 static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface); 63 static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); 64 static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface); 65 static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface); 66 static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface); 67 static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst); 68 static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, 69 SDL_Surface *dst, SDL_Rect *dstrect); 70 static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key); 71 static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha); 72 static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface); 73 static int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor); 74 75 /* Various screen update functions available */ 76 static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects); 77 static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects); 78 79 /* This is the rect EnumModes2 uses */ 80 struct DirectFBEnumRect { 81 SDL_Rect r; 82 struct DirectFBEnumRect* next; 83 }; 84 85 static struct DirectFBEnumRect *enumlist = NULL; 86 87 88 /* DirectFB driver bootstrap functions */ 89 90 static int DirectFB_Available(void) 91 { 92 return 1; 93 } 94 95 static void DirectFB_DeleteDevice(SDL_VideoDevice *device) 96 { 97 SDL_free(device->hidden); 98 SDL_free(device); 99 } 100 101 static SDL_VideoDevice *DirectFB_CreateDevice(int devindex) 102 { 103 SDL_VideoDevice *device; 104 105 /* Initialize all variables that we clean on shutdown */ 106 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); 107 if (device) 108 { 109 SDL_memset (device, 0, (sizeof *device)); 110 device->hidden = (struct SDL_PrivateVideoData *) malloc (sizeof (*device->hidden)); 111 } 112 if (device == NULL || device->hidden == NULL) 113 { 114 SDL_OutOfMemory(); 115 if (device) 116 { 117 free (device); 118 } 119 return(0); 120 } 121 SDL_memset (device->hidden, 0, sizeof (*device->hidden)); 122 123 /* Set the function pointers */ 124 device->VideoInit = DirectFB_VideoInit; 125 device->ListModes = DirectFB_ListModes; 126 device->SetVideoMode = DirectFB_SetVideoMode; 127 device->SetColors = DirectFB_SetColors; 128 device->UpdateRects = NULL; 129 device->CreateYUVOverlay = DirectFB_CreateYUVOverlay; 130 device->VideoQuit = DirectFB_VideoQuit; 131 device->AllocHWSurface = DirectFB_AllocHWSurface; 132 device->CheckHWBlit = DirectFB_CheckHWBlit; 133 device->FillHWRect = DirectFB_FillHWRect; 134 device->SetHWColorKey = DirectFB_SetHWColorKey; 135 device->SetHWAlpha = DirectFB_SetHWAlpha; 136 device->LockHWSurface = DirectFB_LockHWSurface; 137 device->UnlockHWSurface = DirectFB_UnlockHWSurface; 138 device->FlipHWSurface = DirectFB_FlipHWSurface; 139 device->FreeHWSurface = DirectFB_FreeHWSurface; 140 device->ShowWMCursor = DirectFB_ShowWMCursor; 141 device->SetCaption = NULL; 142 device->SetIcon = NULL; 143 device->IconifyWindow = NULL; 144 device->GrabInput = NULL; 145 device->GetWMInfo = NULL; 146 device->InitOSKeymap = DirectFB_InitOSKeymap; 147 device->PumpEvents = DirectFB_PumpEvents; 148 149 device->free = DirectFB_DeleteDevice; 150 151 return device; 152 } 153 154 VideoBootStrap DirectFB_bootstrap = { 155 "directfb", "DirectFB", 156 DirectFB_Available, DirectFB_CreateDevice 157 }; 158 159 static DFBSurfacePixelFormat GetFormatForBpp (int bpp, IDirectFBDisplayLayer *layer) 160 { 161 DFBDisplayLayerConfig dlc; 162 int bytes = (bpp + 7) / 8; 163 164 layer->GetConfiguration (layer, &dlc); 165 166 if (bytes == DFB_BYTES_PER_PIXEL(dlc.pixelformat) && bytes > 1) 167 return dlc.pixelformat; 168 169 switch (bytes) 170 { 171 case 1: 172 return DSPF_LUT8; 173 case 2: 174 return DSPF_RGB16; 175 case 3: 176 return DSPF_RGB24; 177 case 4: 178 return DSPF_RGB32; 179 } 180 181 return DSPF_UNKNOWN; 182 } 183 184 static DFBEnumerationResult EnumModesCallback (int width, 185 int height, 186 int bpp, 187 void *data) 188 { 189 SDL_VideoDevice *this = (SDL_VideoDevice *)data; 190 struct DirectFBEnumRect *enumrect; 191 192 HIDDEN->nummodes++; 193 194 if (enumlist && enumlist->r.w == width && enumlist->r.h == height) 195 return DFENUM_OK; 196 197 enumrect = SDL_calloc(1, sizeof(struct DirectFBEnumRect)); 198 if (!enumrect) 199 { 200 SDL_OutOfMemory(); 201 return DFENUM_CANCEL; 202 } 203 204 enumrect->r.w = (Uint16)width; 205 enumrect->r.h = (Uint16)height; 206 enumrect->next = enumlist; 207 208 enumlist = enumrect; 209 210 return DFENUM_OK; 211 } 212 213 struct private_hwdata { 214 IDirectFBSurface *surface; 215 IDirectFBPalette *palette; 216 }; 217 218 void SetDirectFBerror (const char *function, DFBResult code) 219 { 220 const char *error = DirectFBErrorString (code); 221 222 if (error) 223 SDL_SetError("%s: %s", function, error); 224 else 225 SDL_SetError("Unknown error code from %s", function); 226 } 227 228 static DFBSurfacePixelFormat SDLToDFBPixelFormat (SDL_PixelFormat *format) 229 { 230 if (format->Rmask && format->Gmask && format->Bmask) 231 { 232 switch (format->BitsPerPixel) 233 { 234 case 8: 235 return DSPF_LUT8; 236 237 case 16: 238 if (format->Rmask == 0xF800 && 239 format->Gmask == 0x07E0 && 240 format->Bmask == 0x001F) 241 return DSPF_RGB16; 242 /* fall through */ 243 244 case 15: 245 if (format->Rmask == 0x7C00 && 246 format->Gmask == 0x03E0 && 247 format->Bmask == 0x001F) 248 return DSPF_ARGB1555; 249 break; 250 251 case 24: 252 if (format->Rmask == 0xFF0000 && 253 format->Gmask == 0x00FF00 && 254 format->Bmask == 0x0000FF) 255 return DSPF_RGB24; 256 break; 257 258 case 32: 259 if (format->Rmask == 0xFF0000 && 260 format->Gmask == 0x00FF00 && 261 format->Bmask == 0x0000FF) 262 { 263 if (format->Amask == 0xFF000000) 264 return DSPF_ARGB; 265 else 266 return DSPF_RGB32; 267 } 268 break; 269 } 270 } 271 else 272 { 273 switch (format->BitsPerPixel) 274 { 275 case 8: 276 return DSPF_LUT8; 277 case 15: 278 return DSPF_ARGB1555; 279 case 16: 280 return DSPF_RGB16; 281 case 24: 282 return DSPF_RGB24; 283 case 32: 284 return DSPF_RGB32; 285 } 286 } 287 288 return DSPF_UNKNOWN; 289 } 290 291 static SDL_Palette *AllocatePalette(int size) 292 { 293 SDL_Palette *palette; 294 SDL_Color *colors; 295 296 palette = SDL_calloc (1, sizeof(SDL_Palette)); 297 if (!palette) 298 { 299 SDL_OutOfMemory(); 300 return NULL; 301 } 302 303 colors = SDL_calloc (size, sizeof(SDL_Color)); 304 if (!colors) 305 { 306 SDL_OutOfMemory(); 307 return NULL; 308 } 309 310 palette->ncolors = size; 311 palette->colors = colors; 312 313 return palette; 314 } 315 316 static int DFBToSDLPixelFormat (DFBSurfacePixelFormat pixelformat, SDL_PixelFormat *format) 317 { 318 format->Amask = format->Rmask = format->Gmask = format->Bmask = 0; 319 format->BitsPerPixel = format->BytesPerPixel = 0; 320 321 switch (pixelformat) 322 { 323 case DSPF_A8: 324 format->Amask = 0x000000FF; 325 break; 326 327 case DSPF_ARGB1555: 328 format->Rmask = 0x00007C00; 329 format->Gmask = 0x000003E0; 330 format->Bmask = 0x0000001F; 331 break; 332 333 case DSPF_RGB16: 334 format->Rmask = 0x0000F800; 335 format->Gmask = 0x000007E0; 336 format->Bmask = 0x0000001F; 337 break; 338 339 case DSPF_ARGB: 340 format->Amask = 0; /* apps don't seem to like that: 0xFF000000; */ 341 /* fall through */ 342 case DSPF_RGB24: 343 case DSPF_RGB32: 344 format->Rmask = 0x00FF0000; 345 format->Gmask = 0x0000FF00; 346 format->Bmask = 0x000000FF; 347 break; 348 349 case DSPF_LUT8: 350 format->Rmask = 0x000000FF; 351 format->Gmask = 0x000000FF; 352 format->Bmask = 0x000000FF; 353 354 if (!format->palette) 355 format->palette = AllocatePalette(256); 356 break; 357 358 default: 359 fprintf (stderr, "SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n", pixelformat); 360 return -1; 361 } 362 363 format->BitsPerPixel = DFB_BYTES_PER_PIXEL(pixelformat) * 8; 364 format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat); 365 366 return 0; 367 } 368 369 370 int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat) 371 { 372 int i; 373 DFBResult ret; 374 #if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) 375 DFBCardCapabilities caps; 376 #else 377 DFBGraphicsDeviceDescription caps; 378 #endif 379 DFBDisplayLayerConfig dlc; 380 struct DirectFBEnumRect *rect; 381 IDirectFB *dfb = NULL; 382 IDirectFBDisplayLayer *layer = NULL; 383 IDirectFBEventBuffer *events = NULL; 384 385 HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL; 386 HIDDEN->enable_mga_crtc2 = 0; 387 HIDDEN->mga_crtc2_stretch_overscan = 1; 388 389 ret = DirectFBInit (NULL, NULL); 390 if (ret) 391 { 392 SetDirectFBerror ("DirectFBInit", ret); 393 goto error; 394 } 395 396 ret = DirectFBCreate (&dfb); 397 if (ret) 398 { 399 SetDirectFBerror ("DirectFBCreate", ret); 400 goto error; 401 } 402 403 ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer); 404 if (ret) 405 { 406 SetDirectFBerror ("dfb->GetDisplayLayer", ret); 407 goto error; 408 } 409 410 ret = dfb->CreateInputEventBuffer (dfb, DICAPS_ALL, DFB_FALSE, &events); 411 if (ret) 412 { 413 SetDirectFBerror ("dfb->CreateEventBuffer", ret); 414 goto error; 415 } 416 417 layer->EnableCursor (layer, 1); 418 419 /* Query layer configuration to determine the current mode and pixelformat */ 420 layer->GetConfiguration (layer, &dlc); 421 422 /* If current format is not supported use LUT8 as the default */ 423 if (DFBToSDLPixelFormat (dlc.pixelformat, vformat)) 424 DFBToSDLPixelFormat (DSPF_LUT8, vformat); 425 426 /* Enumerate the available fullscreen modes */ 427 ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this); 428 if (ret) 429 { 430 SetDirectFBerror ("dfb->EnumVideoModes", ret); 431 goto error; 432 } 433 434 HIDDEN->modelist = SDL_calloc (HIDDEN->nummodes + 1, sizeof(SDL_Rect *)); 435 if (!HIDDEN->modelist) 436 { 437 SDL_OutOfMemory(); 438 goto error; 439 } 440 441 for (i = 0, rect = enumlist; rect; ++i, rect = rect->next ) 442 { 443 HIDDEN->modelist[i] = &rect->r; 444 } 445 446 HIDDEN->modelist[i] = NULL; 447 448 449 /* Query card capabilities to get the video memory size */ 450 #if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) 451 dfb->GetCardCapabilities (dfb, &caps); 452 #else 453 dfb->GetDeviceDescription (dfb, &caps); 454 #endif 455 456 this->info.wm_available = 1; 457 this->info.hw_available = 1; 458 this->info.blit_hw = 1; 459 this->info.blit_hw_CC = 1; 460 this->info.blit_hw_A = 1; 461 this->info.blit_fill = 1; 462 this->info.video_mem = caps.video_memory / 1024; 463 this->info.current_w = dlc.width; 464 this->info.current_h = dlc.height; 465 466 HIDDEN->initialized = 1; 467 HIDDEN->dfb = dfb; 468 HIDDEN->layer = layer; 469 HIDDEN->eventbuffer = events; 470 471 if (SDL_getenv("SDL_DIRECTFB_MGA_CRTC2") != NULL) 472 HIDDEN->enable_mga_crtc2 = 1; 473 474 if (HIDDEN->enable_mga_crtc2) 475 { 476 DFBDisplayLayerConfig dlc; 477 DFBDisplayLayerConfigFlags failed; 478 479 ret = dfb->GetDisplayLayer (dfb, 2, &HIDDEN->c2layer); 480 if (ret) 481 { 482 SetDirectFBerror ("dfb->GetDisplayLayer(CRTC2)", ret); 483 goto error; 484 } 485 486 ret = HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer, DLSCL_EXCLUSIVE); 487 if (ret) 488 { 489 SetDirectFBerror ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret); 490 goto error; 491 } 492 493 ret = HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer, DLSCL_EXCLUSIVE); 494 if (ret) 495 { 496 SetDirectFBerror ("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret); 497 goto error; 498 } 499 500 HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0); 501 502 /* Init the surface here as it got a fixed size */ 503 dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; 504 dlc.buffermode = DLBM_BACKVIDEO; 505 dlc.pixelformat = DSPF_RGB32; 506 507 ret = HIDDEN->c2layer->TestConfiguration( HIDDEN->c2layer, &dlc, &failed ); 508 if (ret) 509 { 510 SetDirectFBerror ("c2layer->TestConfiguration", ret); 511 goto error; 512 } 513 514 ret = HIDDEN->c2layer->SetConfiguration( HIDDEN->c2layer, &dlc ); 515 if (ret) 516 { 517 SetDirectFBerror ("c2layer->SetConfiguration", ret); 518 goto error; 519 } 520 521 ret = HIDDEN->c2layer->GetSurface( HIDDEN->c2layer, &HIDDEN->c2frame ); 522 if (ret) 523 { 524 SetDirectFBerror ("c2layer->GetSurface", ret); 525 goto error; 526 } 527 528 HIDDEN->c2framesize.x = 0; 529 HIDDEN->c2framesize.y = 0; 530 HIDDEN->c2frame->GetSize( HIDDEN->c2frame, &HIDDEN->c2framesize.w, &HIDDEN->c2framesize.h); 531 532 HIDDEN->c2frame->SetBlittingFlags( HIDDEN->c2frame, DSBLIT_NOFX ); 533 HIDDEN->c2frame->SetColor( HIDDEN->c2frame, 0, 0, 0, 0xff ); 534 535 /* Clear CRTC2 */ 536 HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); 537 HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 ); 538 HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); 539 HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 ); 540 HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff ); 541 542 HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF ); 543 544 /* Check if overscan is possibly set */ 545 if (SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN") != NULL) 546 { 547 float overscan = 0; 548 if (SDL_sscanf(SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN"), "%f", &overscan) == 1) 549 if (overscan > 0 && overscan < 2) 550 HIDDEN->mga_crtc2_stretch_overscan = overscan; 551 } 552 553 #ifdef DIRECTFB_CRTC2_DEBUG 554 printf("CRTC2 overscan: %f\n", HIDDEN->mga_crtc2_stretch_overscan); 555 #endif 556 } 557 558 return 0; 559 560 error: 561 if (events) 562 events->Release (events); 563 564 if (HIDDEN->c2frame) 565 HIDDEN->c2frame->Release (HIDDEN->c2frame); 566 567 if (HIDDEN->c2layer) 568 HIDDEN->c2layer->Release (HIDDEN->c2layer); 569 570 if (layer) 571 layer->Release (layer); 572 573 if (dfb) 574 dfb->Release (dfb); 575 576 return -1; 577 } 578 579 static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) 580 { 581 if (flags & SDL_FULLSCREEN) 582 return HIDDEN->modelist; 583 else 584 if (SDLToDFBPixelFormat (format) != DSPF_UNKNOWN) 585 return (SDL_Rect**) -1; 586 587 return NULL; 588 } 589 590 static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) 591 { 592 DFBResult ret; 593 DFBSurfaceDescription dsc; 594 DFBSurfacePixelFormat pixelformat; 595 IDirectFBSurface *surface; 596 597 fprintf (stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n", 598 width, height, bpp, flags); 599 600 flags |= SDL_FULLSCREEN; 601 602 /* Release previous primary surface */ 603 if (current->hwdata && current->hwdata->surface) 604 { 605 current->hwdata->surface->Release (current->hwdata->surface); 606 current->hwdata->surface = NULL; 607 608 /* And its palette if present */ 609 if (current->hwdata->palette) 610 { 611 current->hwdata->palette->Release (current->hwdata->palette); 612 current->hwdata->palette = NULL; 613 } 614 } 615 else if (!current->hwdata) 616 { 617 /* Allocate the hardware acceleration data */ 618 current->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*current->hwdata)); 619 if (!current->hwdata) 620 { 621 SDL_OutOfMemory(); 622 return NULL; 623 } 624 } 625 626 /* Set cooperative level depending on flag SDL_FULLSCREEN */ 627 if (flags & SDL_FULLSCREEN) 628 { 629 ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN); 630 if (ret && !HIDDEN->enable_mga_crtc2) 631 { 632 DirectFBError ("dfb->SetCooperativeLevel", ret); 633 flags &= ~SDL_FULLSCREEN; 634 } 635 } 636 else 637 HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL); 638 639 /* Set video mode */ 640 ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp); 641 if (ret) 642 { 643 if (flags & SDL_FULLSCREEN) 644 { 645 flags &= ~SDL_FULLSCREEN; 646 HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL); 647 ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp); 648 } 649 650 if (ret) 651 { 652 SetDirectFBerror ("dfb->SetVideoMode", ret); 653 return NULL; 654 } 655 } 656 657 /* Create primary surface */ 658 dsc.flags = DSDESC_CAPS | DSDESC_PIXELFORMAT; 659 dsc.caps = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0); 660 dsc.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer); 661 662 ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface); 663 if (ret && (flags & SDL_DOUBLEBUF)) 664 { 665 /* Try without double buffering */ 666 dsc.caps &= ~DSCAPS_FLIPPING; 667 ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface); 668 } 669 if (ret) 670 { 671 SetDirectFBerror ("dfb->CreateSurface", ret); 672 return NULL; 673 } 674 675 current->w = width; 676 current->h = height; 677 current->flags = SDL_HWSURFACE | SDL_PREALLOC; 678 679 if (flags & SDL_FULLSCREEN) 680 { 681 current->flags |= SDL_FULLSCREEN; 682 this->UpdateRects = DirectFB_DirectUpdate; 683 } 684 else 685 this->UpdateRects = DirectFB_WindowedUpdate; 686 687 if (dsc.caps & DSCAPS_FLIPPING) 688 current->flags |= SDL_DOUBLEBUF; 689 690 surface->GetPixelFormat (surface, &pixelformat); 691 692 DFBToSDLPixelFormat (pixelformat, current->format); 693 694 /* Get the surface palette (if supported) */ 695 if (DFB_PIXELFORMAT_IS_INDEXED( pixelformat )) 696 { 697 surface->GetPalette (surface, ¤t->hwdata->palette); 698 699 current->flags |= SDL_HWPALETTE; 700 } 701 702 current->hwdata->surface = surface; 703 704 /* MGA CRTC2 stuff */ 705 if (HIDDEN->enable_mga_crtc2) 706 { 707 /* no stretching if c2ssize == c2framesize */ 708 HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0; 709 HIDDEN->c2ssize.w = width; 710 HIDDEN->c2ssize.h = height; 711 712 HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0; 713 HIDDEN->c2dsize.w = width; 714 HIDDEN->c2dsize.h = height; 715 716 HIDDEN->mga_crtc2_stretch = 0; 717 718 if (SDL_getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL) 719 { 720 /* Normally assume a picture aspect ratio of 4:3 */ 721 int zoom_aspect_x = 4, zoom_aspect_y = 3, i, j; 722 723 for (i = 1; i < 20; i++) 724 { 725 for (j = 1; j < 10; j++) 726 { 727 if ((float)width/(float)i*(float)j == height) 728 { 729 zoom_aspect_x = i; 730 zoom_aspect_y = j; 731 732 /* break the loop */ 733 i = 21; 734 break; 735 } 736 } 737 } 738 739 #ifdef DIRECTFB_CRTC2_DEBUG 740 printf("Source resolution: X: %d, Y: %d, Aspect ratio: %d:%d\n", width, height, zoom_aspect_x, zoom_aspect_y); 741 printf("CRTC2 resolution: X: %d, Y: %d\n", HIDDEN->c2framesize.w, HIDDEN->c2framesize.h); 742 #endif 743 744 /* don't stretch only slightly smaller/larger images */ 745 if ((float)width < (float)HIDDEN->c2framesize.w*0.95 || (float)height < (float)HIDDEN->c2framesize.h*0.95) 746 { 747 while ((float)HIDDEN->c2dsize.w < (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan && (float)HIDDEN->c2dsize.h < (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan) 748 { 749 HIDDEN->c2dsize.w+=zoom_aspect_x; 750 HIDDEN->c2dsize.h+=zoom_aspect_y; 751 } 752 753 /* one step down */ 754 HIDDEN->c2dsize.w-=zoom_aspect_x; 755 HIDDEN->c2dsize.h-=zoom_aspect_y; 756 757 #ifdef DIRECTFB_CRTC2_DEBUG 758 printf("Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h); 759 #endif 760 761 HIDDEN->mga_crtc2_stretch = 1; 762 } 763 else if ((float)width > (float)HIDDEN->c2framesize.w*0.95 || (float)height > (float)HIDDEN->c2framesize.h*0.95) 764 { 765 while ((float)HIDDEN->c2dsize.w > (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan || (float)HIDDEN->c2dsize.h > (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan) 766 { 767 HIDDEN->c2dsize.w-=zoom_aspect_x; 768 HIDDEN->c2dsize.h-=zoom_aspect_y; 769 } 770 771 #ifdef DIRECTFB_CRTC2_DEBUG 772 printf("Down-Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h); 773 #endif 774 775 HIDDEN->mga_crtc2_stretch = 1; 776 } else { 777 #ifdef DIRECTFB_CRTC2_DEBUG 778 printf("Not stretching image\n"); 779 #endif 780 } 781 782 /* Panning */ 783 if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w) 784 HIDDEN->c2dsize.x = (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w) / 2; 785 else 786 HIDDEN->c2dsize.x = (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w) / 2; 787 788 if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h) 789 HIDDEN->c2dsize.y = (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h) / 2; 790 else 791 HIDDEN->c2dsize.y = (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h) / 2; 792 793 #ifdef DIRECTFB_CRTC2_DEBUG 794 printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 795 #endif 796 } 797 } 798 799 return current; 800 } 801 802 static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface) 803 { 804 DFBResult ret; 805 DFBSurfaceDescription dsc; 806 807 /* fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n", 808 surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/ 809 810 if (surface->w < 8 || surface->h < 8) 811 return -1; 812 813 /* fill surface description */ 814 dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS; 815 dsc.width = surface->w; 816 dsc.height = surface->h; 817 dsc.caps = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0; 818 819 /* find the right pixelformat */ 820 dsc.pixelformat = SDLToDFBPixelFormat (surface->format); 821 if (dsc.pixelformat == DSPF_UNKNOWN) 822 return -1; 823 824 /* Allocate the hardware acceleration data */ 825 surface->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*surface->hwdata)); 826 if (surface->hwdata == NULL) 827 { 828 SDL_OutOfMemory(); 829 return -1; 830 } 831 832 /* Create the surface */ 833 ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface); 834 if (ret) 835 { 836 SetDirectFBerror ("dfb->CreateSurface", ret); 837 free (surface->hwdata); 838 surface->hwdata = NULL; 839 return -1; 840 } 841 842 surface->flags |= SDL_HWSURFACE | SDL_PREALLOC; 843 844 return 0; 845 } 846 847 static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface) 848 { 849 if (surface->hwdata && HIDDEN->initialized) 850 { 851 surface->hwdata->surface->Release (surface->hwdata->surface); 852 free (surface->hwdata); 853 surface->hwdata = NULL; 854 } 855 } 856 857 static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) 858 { 859 /* fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n", 860 src->hwdata, dst->hwdata);*/ 861 862 if (!src->hwdata || !dst->hwdata) 863 return 0; 864 865 src->flags |= SDL_HWACCEL; 866 src->map->hw_blit = DirectFB_HWAccelBlit; 867 868 return 1; 869 } 870 871 static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, 872 SDL_Surface *dst, SDL_Rect *dstrect) 873 { 874 DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; 875 876 DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h }; 877 DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h }; 878 879 IDirectFBSurface *surface = dst->hwdata->surface; 880 881 if (src->flags & SDL_SRCCOLORKEY) 882 { 883 flags |= DSBLIT_SRC_COLORKEY; 884 DirectFB_SetHWColorKey (NULL, src, src->format->colorkey); 885 } 886 887 if (src->flags & SDL_SRCALPHA) 888 { 889 flags |= DSBLIT_BLEND_COLORALPHA; 890 surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha); 891 } 892 893 surface->SetBlittingFlags (surface, flags); 894 895 if (sr.w == dr.w && sr.h == dr.h) 896 surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y); 897 else 898 surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr); 899 900 return 0; 901 } 902 903 static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) 904 { 905 SDL_PixelFormat *fmt = dst->format; 906 IDirectFBSurface *surface = dst->hwdata->surface; 907 908 /* ugly */ 909 surface->SetColor (surface, 910 (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss), 911 (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss), 912 (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift), 0xFF); 913 surface->FillRectangle (surface, dstrect->x, dstrect->y, dstrect->w, dstrect->h); 914 915 return 0; 916 } 917 918 static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key) 919 { 920 SDL_PixelFormat *fmt = src->format; 921 IDirectFBSurface *surface = src->hwdata->surface; 922 923 if (fmt->BitsPerPixel == 8) 924 surface->SetSrcColorKeyIndex (surface, key); 925 else 926 /* ugly */ 927 surface->SetSrcColorKey (surface, 928 (key & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss), 929 (key & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss), 930 (key & fmt->Bmask) << (fmt->Bloss - fmt->Bshift)); 931 932 return 0; 933 } 934 935 static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha) 936 { 937 return 0; 938 } 939 940 static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface) 941 { 942 if (HIDDEN->enable_mga_crtc2) 943 { 944 int rtn = surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, 0); 945 if (HIDDEN->mga_crtc2_stretch) 946 HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); 947 else 948 HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 949 950 HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); 951 return rtn; 952 } 953 else 954 return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC); 955 } 956 957 static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface) 958 { 959 DFBResult ret; 960 void *data; 961 int pitch; 962 963 ret = surface->hwdata->surface->Lock (surface->hwdata->surface, 964 DSLF_WRITE, &data, &pitch); 965 if (ret) 966 { 967 SetDirectFBerror ("surface->Lock", ret); 968 return -1; 969 } 970 971 surface->pixels = data; 972 surface->pitch = pitch; 973 974 return 0; 975 } 976 977 static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface) 978 { 979 surface->hwdata->surface->Unlock (surface->hwdata->surface); 980 surface->pixels = NULL; 981 } 982 983 static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) 984 { 985 if (HIDDEN->enable_mga_crtc2) 986 { 987 if (HIDDEN->mga_crtc2_stretch) 988 HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, this->screen->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); 989 else 990 HIDDEN->c2frame->Blit(HIDDEN->c2frame, this->screen->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 991 992 HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); 993 } 994 } 995 996 static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects) 997 { 998 DFBRegion region; 999 int i; 1000 int region_valid = 0; 1001 IDirectFBSurface *surface = this->screen->hwdata->surface; 1002 1003 for (i=0; i<numrects; ++i) 1004 { 1005 int x2, y2; 1006 1007 if ( ! rects[i].w ) /* Clipped? */ 1008 continue; 1009 1010 x2 = rects[i].x + rects[i].w - 1; 1011 y2 = rects[i].y + rects[i].h - 1; 1012 1013 if (region_valid) 1014 { 1015 if (rects[i].x < region.x1) 1016 region.x1 = rects[i].x; 1017 1018 if (rects[i].y < region.y1) 1019 region.y1 = rects[i].y; 1020 1021 if (x2 > region.x2) 1022 region.x2 = x2; 1023 1024 if (y2 > region.y2) 1025 region.y2 = y2; 1026 } 1027 else 1028 { 1029 region.x1 = rects[i].x; 1030 region.y1 = rects[i].y; 1031 region.x2 = x2; 1032 region.y2 = y2; 1033 1034 region_valid = 1; 1035 } 1036 } 1037 1038 if (region_valid) 1039 { 1040 if (HIDDEN->enable_mga_crtc2) 1041 { 1042 if (HIDDEN->mga_crtc2_stretch) 1043 HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); 1044 else 1045 HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 1046 1047 HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); 1048 } 1049 else 1050 surface->Flip (surface, ®ion, DSFLIP_WAITFORSYNC); 1051 } 1052 } 1053 1054 int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 1055 { 1056 IDirectFBPalette *palette = this->screen->hwdata->palette; 1057 1058 if (!palette) 1059 return 0; 1060 1061 if (firstcolor > 255) 1062 return 0; 1063 1064 if (firstcolor + ncolors > 256) 1065 ncolors = 256 - firstcolor; 1066 1067 if (ncolors > 0) 1068 { 1069 int i; 1070 DFBColor entries[ncolors]; 1071 1072 for (i=0; i<ncolors; i++) 1073 { 1074 entries[i].a = 0xff; 1075 entries[i].r = colors[i].r; 1076 entries[i].g = colors[i].g; 1077 entries[i].b = colors[i].b; 1078 } 1079 1080 palette->SetEntries (palette, entries, ncolors, firstcolor); 1081 } 1082 1083 return 1; 1084 } 1085 1086 void DirectFB_VideoQuit(_THIS) 1087 { 1088 struct DirectFBEnumRect *rect = enumlist; 1089 1090 if (this->screen && this->screen->hwdata) 1091 { 1092 IDirectFBSurface *surface = this->screen->hwdata->surface; 1093 IDirectFBPalette *palette = this->screen->hwdata->palette; 1094 1095 if (palette) 1096 palette->Release (palette); 1097 1098 if (surface) 1099 surface->Release (surface); 1100 1101 this->screen->hwdata->surface = NULL; 1102 this->screen->hwdata->palette = NULL; 1103 } 1104 1105 if (HIDDEN->c2frame) 1106 { 1107 HIDDEN->c2frame->Release (HIDDEN->c2frame); 1108 HIDDEN->c2frame = NULL; 1109 } 1110 1111 if (HIDDEN->eventbuffer) 1112 { 1113 HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer); 1114 HIDDEN->eventbuffer = NULL; 1115 } 1116 1117 if (HIDDEN->c2layer) 1118 { 1119 HIDDEN->c2layer->Release (HIDDEN->c2layer); 1120 HIDDEN->c2layer = NULL; 1121 } 1122 1123 if (HIDDEN->layer) 1124 { 1125 HIDDEN->layer->Release (HIDDEN->layer); 1126 HIDDEN->layer = NULL; 1127 } 1128 1129 if (HIDDEN->dfb) 1130 { 1131 HIDDEN->dfb->Release (HIDDEN->dfb); 1132 HIDDEN->dfb = NULL; 1133 } 1134 1135 /* Free video mode list */ 1136 if (HIDDEN->modelist) 1137 { 1138 free (HIDDEN->modelist); 1139 HIDDEN->modelist = NULL; 1140 } 1141 1142 /* Free mode enumeration list */ 1143 while (rect) 1144 { 1145 struct DirectFBEnumRect *next = rect->next; 1146 free (rect); 1147 rect = next; 1148 } 1149 enumlist = NULL; 1150 1151 HIDDEN->initialized = 0; 1152 } 1153 1154 1155 int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor) 1156 { 1157 /* We can only hide or show the default cursor */ 1158 if ( cursor == NULL ) 1159 { 1160 HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0x00); 1161 } 1162 else 1163 { 1164 HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0xFF); 1165 } 1166 return 1; 1167 } 1168 1169 void DirectFB_FinalQuit(void) 1170 { 1171 } 1172