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 /* BWindow based framebuffer implementation */ 25 26 #include <unistd.h> 27 28 #include "SDL_BWin.h" 29 #include "SDL_timer.h" 30 31 extern "C" { 32 33 #include "../SDL_sysvideo.h" 34 #include "../../events/SDL_events_c.h" 35 #include "SDL_sysevents_c.h" 36 #include "SDL_sysmouse_c.h" 37 #include "SDL_syswm_c.h" 38 #include "SDL_lowvideo.h" 39 #include "../SDL_yuvfuncs.h" 40 #include "SDL_sysyuv.h" 41 #include "../blank_cursor.h" 42 43 #define BEOS_HIDDEN_SIZE 32 /* starting hidden window size */ 44 45 /* Initialization/Query functions */ 46 static int BE_VideoInit(_THIS, SDL_PixelFormat *vformat); 47 static SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 48 static SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 49 static void BE_UpdateMouse(_THIS); 50 static int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); 51 static void BE_VideoQuit(_THIS); 52 53 /* Hardware surface functions */ 54 static int BE_AllocHWSurface(_THIS, SDL_Surface *surface); 55 static int BE_LockHWSurface(_THIS, SDL_Surface *surface); 56 static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface); 57 static void BE_FreeHWSurface(_THIS, SDL_Surface *surface); 58 59 static int BE_ToggleFullScreen(_THIS, int fullscreen); 60 61 /* OpenGL functions */ 62 #if SDL_VIDEO_OPENGL 63 static int BE_GL_LoadLibrary(_THIS, const char *path); 64 static void* BE_GL_GetProcAddress(_THIS, const char *proc); 65 static int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value); 66 static int BE_GL_MakeCurrent(_THIS); 67 static void BE_GL_SwapBuffers(_THIS); 68 #endif 69 70 /* FB driver bootstrap functions */ 71 72 static int BE_Available(void) 73 { 74 return(1); 75 } 76 77 static void BE_DeleteDevice(SDL_VideoDevice *device) 78 { 79 SDL_free(device->hidden); 80 SDL_free(device); 81 } 82 83 static SDL_VideoDevice *BE_CreateDevice(int devindex) 84 { 85 SDL_VideoDevice *device; 86 87 /* Initialize all variables that we clean on shutdown */ 88 device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); 89 if ( device ) { 90 SDL_memset(device, 0, (sizeof *device)); 91 device->hidden = (struct SDL_PrivateVideoData *) 92 SDL_malloc((sizeof *device->hidden)); 93 } 94 if ( (device == NULL) || (device->hidden == NULL) ) { 95 SDL_OutOfMemory(); 96 if ( device ) { 97 SDL_free(device); 98 } 99 return(0); 100 } 101 SDL_memset(device->hidden, 0, (sizeof *device->hidden)); 102 103 /* Set the function pointers */ 104 /* Initialization/Query functions */ 105 device->VideoInit = BE_VideoInit; 106 device->ListModes = BE_ListModes; 107 device->SetVideoMode = BE_SetVideoMode; 108 device->ToggleFullScreen = BE_ToggleFullScreen; 109 device->UpdateMouse = BE_UpdateMouse; 110 device->CreateYUVOverlay = BE_CreateYUVOverlay; 111 device->SetColors = BE_SetColors; 112 device->UpdateRects = NULL; 113 device->VideoQuit = BE_VideoQuit; 114 /* Hardware acceleration functions */ 115 device->AllocHWSurface = BE_AllocHWSurface; 116 device->CheckHWBlit = NULL; 117 device->FillHWRect = NULL; 118 device->SetHWColorKey = NULL; 119 device->SetHWAlpha = NULL; 120 device->LockHWSurface = BE_LockHWSurface; 121 device->UnlockHWSurface = BE_UnlockHWSurface; 122 device->FlipHWSurface = NULL; 123 device->FreeHWSurface = BE_FreeHWSurface; 124 /* Gamma support */ 125 #if SDL_VIDEO_OPENGL 126 /* OpenGL support */ 127 device->GL_LoadLibrary = BE_GL_LoadLibrary; 128 device->GL_GetProcAddress = BE_GL_GetProcAddress; 129 device->GL_GetAttribute = BE_GL_GetAttribute; 130 device->GL_MakeCurrent = BE_GL_MakeCurrent; 131 device->GL_SwapBuffers = BE_GL_SwapBuffers; 132 #endif 133 /* Window manager functions */ 134 device->SetCaption = BE_SetWMCaption; 135 device->SetIcon = NULL; 136 device->IconifyWindow = BE_IconifyWindow; 137 device->GrabInput = BE_GrabInput; 138 device->GetWMInfo = BE_GetWMInfo; 139 /* Cursor manager functions */ 140 device->FreeWMCursor = BE_FreeWMCursor; 141 device->CreateWMCursor = BE_CreateWMCursor; 142 device->ShowWMCursor = BE_ShowWMCursor; 143 device->WarpWMCursor = BE_WarpWMCursor; 144 device->MoveWMCursor = NULL; 145 device->CheckMouseMode = BE_CheckMouseMode; 146 /* Event manager functions */ 147 device->InitOSKeymap = BE_InitOSKeymap; 148 device->PumpEvents = BE_PumpEvents; 149 150 device->free = BE_DeleteDevice; 151 152 /* Set the driver flags */ 153 device->handles_any_size = 1; 154 155 return device; 156 } 157 158 VideoBootStrap BWINDOW_bootstrap = { 159 "bwindow", "BDirectWindow graphics", 160 BE_Available, BE_CreateDevice 161 }; 162 163 static inline int ColorSpaceToBitsPerPixel(uint32 colorspace) 164 { 165 int bitsperpixel; 166 167 bitsperpixel = 0; 168 switch (colorspace) { 169 case B_CMAP8: 170 bitsperpixel = 8; 171 break; 172 case B_RGB15: 173 case B_RGBA15: 174 case B_RGB15_BIG: 175 case B_RGBA15_BIG: 176 bitsperpixel = 15; 177 break; 178 case B_RGB16: 179 case B_RGB16_BIG: 180 bitsperpixel = 16; 181 break; 182 case B_RGB32: 183 case B_RGBA32: 184 case B_RGB32_BIG: 185 case B_RGBA32_BIG: 186 bitsperpixel = 32; 187 break; 188 default: 189 break; 190 } 191 return(bitsperpixel); 192 } 193 194 /* Function to sort the display_list in bscreen */ 195 static int CompareModes(const void *A, const void *B) 196 { 197 const display_mode *a = (display_mode *)A; 198 const display_mode *b = (display_mode *)B; 199 200 if ( a->space == b->space ) { 201 return((b->virtual_width*b->virtual_height)- 202 (a->virtual_width*a->virtual_height)); 203 } else { 204 return(ColorSpaceToBitsPerPixel(b->space)- 205 ColorSpaceToBitsPerPixel(a->space)); 206 } 207 } 208 209 /* Yes, this isn't the fastest it could be, but it works nicely */ 210 static int BE_AddMode(_THIS, int index, unsigned int w, unsigned int h) 211 { 212 SDL_Rect *mode; 213 int i; 214 int next_mode; 215 216 /* Check to see if we already have this mode */ 217 if ( SDL_nummodes[index] > 0 ) { 218 for ( i=SDL_nummodes[index]-1; i >= 0; --i ) { 219 mode = SDL_modelist[index][i]; 220 if ( (mode->w == w) && (mode->h == h) ) { 221 #ifdef BWINDOW_DEBUG 222 fprintf(stderr, "We already have mode %dx%d at %d bytes per pixel\n", w, h, index+1); 223 #endif 224 return(0); 225 } 226 } 227 } 228 229 /* Set up the new video mode rectangle */ 230 mode = (SDL_Rect *)SDL_malloc(sizeof *mode); 231 if ( mode == NULL ) { 232 SDL_OutOfMemory(); 233 return(-1); 234 } 235 mode->x = 0; 236 mode->y = 0; 237 mode->w = w; 238 mode->h = h; 239 #ifdef BWINDOW_DEBUG 240 fprintf(stderr, "Adding mode %dx%d at %d bytes per pixel\n", w, h, index+1); 241 #endif 242 243 /* Allocate the new list of modes, and fill in the new mode */ 244 next_mode = SDL_nummodes[index]; 245 SDL_modelist[index] = (SDL_Rect **) 246 SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *)); 247 if ( SDL_modelist[index] == NULL ) { 248 SDL_OutOfMemory(); 249 SDL_nummodes[index] = 0; 250 SDL_free(mode); 251 return(-1); 252 } 253 SDL_modelist[index][next_mode] = mode; 254 SDL_modelist[index][next_mode+1] = NULL; 255 SDL_nummodes[index]++; 256 257 return(0); 258 } 259 260 int BE_VideoInit(_THIS, SDL_PixelFormat *vformat) 261 { 262 display_mode *modes; 263 uint32 i, nmodes; 264 int bpp; 265 BRect bounds; 266 267 /* Initialize the Be Application for appserver interaction */ 268 if ( SDL_InitBeApp() < 0 ) { 269 return(-1); 270 } 271 272 /* It is important that this be created after SDL_InitBeApp() */ 273 BScreen bscreen; 274 275 /* Save the current display mode */ 276 bscreen.GetMode(&saved_mode); 277 _this->info.current_w = saved_mode.virtual_width; 278 _this->info.current_h = saved_mode.virtual_height; 279 280 /* Determine the screen depth */ 281 vformat->BitsPerPixel = ColorSpaceToBitsPerPixel(bscreen.ColorSpace()); 282 if ( vformat->BitsPerPixel == 0 ) { 283 SDL_SetError("Unknown BScreen colorspace: 0x%x", 284 bscreen.ColorSpace()); 285 return(-1); 286 } 287 288 /* Get the video modes we can switch to in fullscreen mode */ 289 bscreen.GetModeList(&modes, &nmodes); 290 SDL_qsort(modes, nmodes, sizeof *modes, CompareModes); 291 for ( i=0; i<nmodes; ++i ) { 292 bpp = ColorSpaceToBitsPerPixel(modes[i].space); 293 //if ( bpp != 0 ) { // There are bugs in changing colorspace 294 if ( modes[i].space == saved_mode.space ) { 295 BE_AddMode(_this, ((bpp+7)/8)-1, 296 modes[i].virtual_width, 297 modes[i].virtual_height); 298 } 299 } 300 301 /* Create the window and view */ 302 bounds.top = 0; bounds.left = 0; 303 bounds.right = BEOS_HIDDEN_SIZE; 304 bounds.bottom = BEOS_HIDDEN_SIZE; 305 SDL_Win = new SDL_BWin(bounds); 306 307 #if SDL_VIDEO_OPENGL 308 /* testgl application doesn't load library, just tries to load symbols */ 309 /* is it correct? if so we have to load library here */ 310 BE_GL_LoadLibrary(_this, NULL); 311 #endif 312 313 /* Create the clear cursor */ 314 SDL_BlankCursor = BE_CreateWMCursor(_this, blank_cdata, blank_cmask, 315 BLANK_CWIDTH, BLANK_CHEIGHT, BLANK_CHOTX, BLANK_CHOTY); 316 317 /* Fill in some window manager capabilities */ 318 _this->info.wm_available = 1; 319 320 /* We're done! */ 321 return(0); 322 } 323 324 /* We support any dimension at our bit-depth */ 325 SDL_Rect **BE_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) 326 { 327 SDL_Rect **modes; 328 329 modes = ((SDL_Rect **)0); 330 if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) { 331 modes = SDL_modelist[((format->BitsPerPixel+7)/8)-1]; 332 } else { 333 if ( format->BitsPerPixel == 334 _this->screen->format->BitsPerPixel ) { 335 modes = ((SDL_Rect **)-1); 336 } 337 } 338 return(modes); 339 } 340 341 /* Various screen update functions available */ 342 static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); 343 344 345 /* Find the closest display mode for fullscreen */ 346 static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp, 347 display_mode *mode) 348 { 349 BScreen bscreen; 350 uint32 i, nmodes; 351 SDL_Rect **modes; 352 display_mode *dmodes; 353 display_mode current; 354 float current_refresh; 355 bscreen.GetMode(¤t); 356 current_refresh = (1000 * current.timing.pixel_clock) / 357 (current.timing.h_total * current.timing.v_total); 358 359 modes = SDL_modelist[((bpp+7)/8)-1]; 360 361 // find end of list (lowest-resolution mode; modes are ordered 362 // highest-to-lowest). 363 i = 0; while(modes[i]) i++; 364 if (!i) return false; // what? no modes at all? 365 366 // find first mode with resolution >= requested in both dimensions 367 for (--i; i >= 0; --i) 368 { 369 if (modes[i]->w >= width && modes[i]->h >= height) 370 break; 371 } 372 373 // unable to find any mode with that high a resolution! 374 if (i < 0) 375 return false; 376 377 width = modes[i]->w; 378 height = modes[i]->h; 379 380 bscreen.GetModeList(&dmodes, &nmodes); 381 for ( i = 0; i < nmodes; ++i ) { 382 if ( (bpp == ColorSpaceToBitsPerPixel(dmodes[i].space)) && 383 (width == dmodes[i].virtual_width) && 384 (height == dmodes[i].virtual_height) ) { 385 break; 386 } 387 } 388 if ( i != nmodes ) { 389 *mode = dmodes[i]; 390 if ((mode->virtual_width <= current.virtual_width) && 391 (mode->virtual_height <= current.virtual_height)) { 392 float new_refresh = (1000 * mode->timing.pixel_clock) / 393 (mode->timing.h_total * mode->timing.v_total); 394 if (new_refresh < current_refresh) { 395 mode->timing.pixel_clock = (uint32)((mode->timing.h_total * mode->timing.v_total) 396 * current_refresh / 1000); 397 } 398 } 399 return true; 400 } else { 401 return false; 402 } 403 } 404 405 static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen) 406 { 407 // printf("SetFullScreen(%d)\n", fullscreen); 408 BScreen bscreen; 409 410 // SetFullSscreen() does not work as expected if called in a window 411 // that was never shown. This is probably a bug in the Haiku Game Kit that needs 412 // to be investigated. 413 if (SDL_Win->Lock()) { 414 // Show our window. 415 SDL_Win->Show(); 416 } 417 418 if (SDL_Win->IsLocked()) { 419 // Unlock the window if it was locked. This is needed as only the 420 // first call to Show() unlocks the looper. All other calls to it 421 // will not. 422 SDL_Win->Unlock(); 423 } 424 425 int width = screen->w; 426 int height = screen->h; 427 428 if (fullscreen) { 429 // Set resolution to the closest available one that matches the 430 // current SDL resolution. 431 display_mode mode; 432 bscreen.GetMode(&mode); 433 434 int bpp = screen->format->BitsPerPixel; 435 if (bpp != ColorSpaceToBitsPerPixel(mode.space) || 436 width != mode.virtual_width || height != mode.virtual_height) { 437 if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) { 438 bscreen.SetMode(&mode); 439 } else { 440 // printf("Could not set new mode.\n"); 441 return(0); 442 } 443 } 444 } else { 445 // Reset to the previous known resolution as we are now in window 446 // mode. 447 bscreen.SetMode(&saved_mode); 448 } 449 450 // Effectivelly set/reset full screen mode. If we are already in 451 // full screen mode, we reset back to windowed mode first so the 452 // window can resize when going fullscreen. 453 // if (fullscreen) 454 // printf("Going fullscreen\n"); 455 // else 456 // printf("Going windowed\n"); 457 SDL_Win->SetFullScreen(fullscreen); 458 459 // Calculate offsets for centering the window (in window mode) and for 460 // dentering the bitmap (in full screen mode). 461 BRect bounds = bscreen.Frame(); 462 bounds.PrintToStream(); 463 int32 cx = (bounds.IntegerWidth() - width)/2; 464 int32 cy = (bounds.IntegerHeight() - height)/2; 465 466 // printf ("cx = %d, cy = %d\n", cx, cy); 467 if (!SDL_Win->IsFullScreen()) { 468 // printf("Doing not fullscreen stuff.\n"); 469 // We are not in full screen mode, so we want to change the window 470 // size to match the resolution in SDL. 471 SDL_Win->ResizeTo(width, height); 472 473 // And also center the window and reset the drawing offset. 474 SDL_Win->MoveTo(cx, cy); 475 SDL_Win->SetXYOffset(0, 0); 476 } else { 477 // printf("Doing fullscreen stuff."); 478 // Center the bitmap whenever we are in full screen mode. 479 SDL_Win->SetXYOffset(cx, cy); 480 } 481 482 // Set relevant internal SDL screen flags. 483 if (SDL_Win->IsFullScreen()) { 484 screen->flags |= SDL_FULLSCREEN; 485 } else { 486 screen->flags &= ~SDL_FULLSCREEN; 487 } 488 489 return(1); 490 } 491 492 static int BE_ToggleFullScreen(_THIS, int fullscreen) 493 { 494 return BE_SetFullScreen(_this, _this->screen, fullscreen); 495 } 496 497 /* FIXME: check return values and cleanup here */ 498 SDL_Surface *BE_SetVideoMode(_THIS, SDL_Surface *current, 499 int width, int height, int bpp, Uint32 flags) 500 { 501 BScreen bscreen; 502 BBitmap *bbitmap; 503 BRect bounds; 504 Uint32 gl_flags = 0; 505 506 /* Only RGB works on r5 currently */ 507 gl_flags = BGL_RGB; 508 if (_this->gl_config.double_buffer) 509 gl_flags |= BGL_DOUBLE; 510 else 511 gl_flags |= BGL_SINGLE; 512 if (_this->gl_config.alpha_size > 0 || bpp == 32) 513 gl_flags |= BGL_ALPHA; 514 if (_this->gl_config.depth_size > 0) 515 gl_flags |= BGL_DEPTH; 516 if (_this->gl_config.stencil_size > 0) 517 gl_flags |= BGL_STENCIL; 518 if (_this->gl_config.accum_red_size > 0 519 || _this->gl_config.accum_green_size > 0 520 || _this->gl_config.accum_blue_size > 0 521 || _this->gl_config.accum_alpha_size > 0) 522 gl_flags |= BGL_ACCUM; 523 524 /* Create the view for this window, using found flags */ 525 if ( SDL_Win->CreateView(flags, gl_flags) < 0 ) { 526 return(NULL); 527 } 528 529 current->flags = 0; /* Clear flags */ 530 current->w = width; 531 current->h = height; 532 SDL_Win->SetType(B_TITLED_WINDOW); 533 if ( flags & SDL_NOFRAME ) { 534 current->flags |= SDL_NOFRAME; 535 SDL_Win->SetLook(B_NO_BORDER_WINDOW_LOOK); 536 } else { 537 if ( (flags & SDL_RESIZABLE) && !(flags & SDL_OPENGL) ) { 538 current->flags |= SDL_RESIZABLE; 539 /* We don't want opaque resizing (TM). :-) */ 540 SDL_Win->SetFlags(B_OUTLINE_RESIZE); 541 } else { 542 SDL_Win->SetFlags(B_NOT_RESIZABLE|B_NOT_ZOOMABLE); 543 } 544 } 545 546 if ( flags & SDL_OPENGL ) { 547 current->flags |= SDL_OPENGL; 548 current->pitch = 0; 549 current->pixels = NULL; 550 _this->UpdateRects = NULL; 551 } else { 552 /* Create the BBitmap framebuffer */ 553 bounds.top = 0; bounds.left = 0; 554 bounds.right = width-1; 555 bounds.bottom = height-1; 556 bbitmap = new BBitmap(bounds, bscreen.ColorSpace()); 557 if ( ! bbitmap->IsValid() ) { 558 SDL_SetError("Couldn't create screen bitmap"); 559 delete bbitmap; 560 return(NULL); 561 } 562 current->pitch = bbitmap->BytesPerRow(); 563 current->pixels = (void *)bbitmap->Bits(); 564 SDL_Win->SetBitmap(bbitmap); 565 _this->UpdateRects = BE_NormalUpdate; 566 } 567 568 /* Set the correct fullscreen mode */ 569 BE_SetFullScreen(_this, current, flags & SDL_FULLSCREEN ? 1 : 0); 570 571 /* We're done */ 572 return(current); 573 } 574 575 /* Update the current mouse state and position */ 576 void BE_UpdateMouse(_THIS) 577 { 578 BPoint point; 579 uint32 buttons; 580 581 if ( SDL_Win->Lock() ) { 582 /* Get new input state, if still active */ 583 if ( SDL_Win->IsActive() ) { 584 (SDL_Win->View())->GetMouse(&point, &buttons, true); 585 } else { 586 point.x = -1; 587 point.y = -1; 588 } 589 SDL_Win->Unlock(); 590 591 if ( (point.x >= 0) && (point.x < SDL_VideoSurface->w) && 592 (point.y >= 0) && (point.y < SDL_VideoSurface->h) ) { 593 SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); 594 SDL_PrivateMouseMotion(0, 0, 595 (Sint16)point.x, (Sint16)point.y); 596 } else { 597 SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); 598 } 599 } 600 } 601 602 /* We don't actually allow hardware surfaces other than the main one */ 603 static int BE_AllocHWSurface(_THIS, SDL_Surface *surface) 604 { 605 return(-1); 606 } 607 static void BE_FreeHWSurface(_THIS, SDL_Surface *surface) 608 { 609 return; 610 } 611 static int BE_LockHWSurface(_THIS, SDL_Surface *surface) 612 { 613 return(0); 614 } 615 static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface) 616 { 617 return; 618 } 619 620 static void BE_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) 621 { 622 if ( SDL_Win->BeginDraw() ) { 623 int i; 624 625 for ( i=0; i<numrects; ++i ) { 626 BRect rect; 627 628 rect.top = rects[i].y; 629 rect.left = rects[i].x; 630 rect.bottom = rect.top+rects[i].h-1; 631 rect.right = rect.left+rects[i].w-1; 632 SDL_Win->DrawAsync(rect); 633 } 634 SDL_Win->EndDraw(); 635 } 636 } 637 638 #if SDL_VIDEO_OPENGL 639 /* Passing a NULL path means load pointers from the application */ 640 int BE_GL_LoadLibrary(_THIS, const char *path) 641 { 642 if (path == NULL) { 643 if (_this->gl_config.dll_handle == NULL) { 644 image_info info; 645 int32 cookie = 0; 646 while (get_next_image_info(0,&cookie,&info) == B_OK) { 647 void *location = NULL; 648 #ifdef __HAIKU__ 649 if (get_image_symbol(info.id,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // This is how it actually works in Haiku 650 #else 651 if (get_image_symbol((image_id)cookie,"glBegin",B_SYMBOL_TYPE_ANY,&location) == B_OK) { // I don't know if that *did* work in BeOS 652 #endif 653 _this->gl_config.dll_handle = (void*)info.id; 654 _this->gl_config.driver_loaded = 1; 655 SDL_strlcpy(_this->gl_config.driver_path, "libGL.so", SDL_arraysize(_this->gl_config.driver_path)); 656 } 657 } 658 } 659 } else { 660 /* 661 FIXME None of BeOS libGL.so implementations have exported functions 662 to load BGLView, which should be reloaded from new lib. 663 So for now just "load" linked libGL.so :( 664 */ 665 if (_this->gl_config.dll_handle == NULL) { 666 return BE_GL_LoadLibrary(_this, NULL); 667 } 668 669 /* Unload old first */ 670 /*if (_this->gl_config.dll_handle != NULL) {*/ 671 /* Do not try to unload application itself (if LoadLibrary was called before with NULL ;) */ 672 /* image_info info; 673 if (get_image_info((image_id)_this->gl_config.dll_handle, &info) == B_OK) { 674 if (info.type != B_APP_IMAGE) { 675 unload_add_on((image_id)_this->gl_config.dll_handle); 676 } 677 } 678 679 } 680 681 if ((_this->gl_config.dll_handle = (void*)load_add_on(path)) != (void*)B_ERROR) { 682 _this->gl_config.driver_loaded = 1; 683 SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path)); 684 }*/ 685 } 686 687 if (_this->gl_config.dll_handle != NULL) { 688 return 0; 689 } else { 690 _this->gl_config.dll_handle = NULL; 691 _this->gl_config.driver_loaded = 0; 692 *_this->gl_config.driver_path = '\0'; 693 return -1; 694 } 695 } 696 697 void* BE_GL_GetProcAddress(_THIS, const char *proc) 698 { 699 if (_this->gl_config.dll_handle != NULL) { 700 void *location = NULL; 701 status_t err; 702 if ((err = get_image_symbol((image_id)_this->gl_config.dll_handle, proc, B_SYMBOL_TYPE_ANY, &location)) == B_OK) { 703 return location; 704 } else { 705 SDL_SetError("Couldn't find OpenGL symbol"); 706 return NULL; 707 } 708 } else { 709 SDL_SetError("OpenGL library not loaded"); 710 return NULL; 711 } 712 } 713 714 int BE_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) 715 { 716 /* 717 FIXME? Right now BE_GL_GetAttribute shouldn't be called between glBegin() and glEnd() - it doesn't use "cached" values 718 */ 719 switch (attrib) 720 { 721 case SDL_GL_RED_SIZE: 722 glGetIntegerv(GL_RED_BITS, (GLint*)value); 723 break; 724 case SDL_GL_GREEN_SIZE: 725 glGetIntegerv(GL_GREEN_BITS, (GLint*)value); 726 break; 727 case SDL_GL_BLUE_SIZE: 728 glGetIntegerv(GL_BLUE_BITS, (GLint*)value); 729 break; 730 case SDL_GL_ALPHA_SIZE: 731 glGetIntegerv(GL_ALPHA_BITS, (GLint*)value); 732 break; 733 case SDL_GL_DOUBLEBUFFER: 734 glGetBooleanv(GL_DOUBLEBUFFER, (GLboolean*)value); 735 break; 736 case SDL_GL_BUFFER_SIZE: 737 int v; 738 glGetIntegerv(GL_RED_BITS, (GLint*)&v); 739 *value = v; 740 glGetIntegerv(GL_GREEN_BITS, (GLint*)&v); 741 *value += v; 742 glGetIntegerv(GL_BLUE_BITS, (GLint*)&v); 743 *value += v; 744 glGetIntegerv(GL_ALPHA_BITS, (GLint*)&v); 745 *value += v; 746 break; 747 case SDL_GL_DEPTH_SIZE: 748 glGetIntegerv(GL_DEPTH_BITS, (GLint*)value); /* Mesa creates 16 only? r5 always 32 */ 749 break; 750 case SDL_GL_STENCIL_SIZE: 751 glGetIntegerv(GL_STENCIL_BITS, (GLint*)value); 752 break; 753 case SDL_GL_ACCUM_RED_SIZE: 754 glGetIntegerv(GL_ACCUM_RED_BITS, (GLint*)value); 755 break; 756 case SDL_GL_ACCUM_GREEN_SIZE: 757 glGetIntegerv(GL_ACCUM_GREEN_BITS, (GLint*)value); 758 break; 759 case SDL_GL_ACCUM_BLUE_SIZE: 760 glGetIntegerv(GL_ACCUM_BLUE_BITS, (GLint*)value); 761 break; 762 case SDL_GL_ACCUM_ALPHA_SIZE: 763 glGetIntegerv(GL_ACCUM_ALPHA_BITS, (GLint*)value); 764 break; 765 case SDL_GL_STEREO: 766 case SDL_GL_MULTISAMPLEBUFFERS: 767 case SDL_GL_MULTISAMPLESAMPLES: 768 default: 769 *value=0; 770 return(-1); 771 } 772 return 0; 773 } 774 775 int BE_GL_MakeCurrent(_THIS) 776 { 777 /* FIXME: should we glview->unlock and then glview->lock()? */ 778 return 0; 779 } 780 781 void BE_GL_SwapBuffers(_THIS) 782 { 783 SDL_Win->SwapBuffers(); 784 } 785 #endif 786 787 /* Is the system palette settable? */ 788 int BE_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) 789 { 790 int i; 791 SDL_Palette *palette; 792 const color_map *cmap = BScreen().ColorMap(); 793 794 /* Get the screen colormap */ 795 palette = _this->screen->format->palette; 796 for ( i=0; i<256; ++i ) { 797 palette->colors[i].r = cmap->color_list[i].red; 798 palette->colors[i].g = cmap->color_list[i].green; 799 palette->colors[i].b = cmap->color_list[i].blue; 800 } 801 return(0); 802 } 803 804 void BE_VideoQuit(_THIS) 805 { 806 int i, j; 807 808 SDL_Win->Quit(); 809 SDL_Win = NULL; 810 811 if ( SDL_BlankCursor != NULL ) { 812 BE_FreeWMCursor(_this, SDL_BlankCursor); 813 SDL_BlankCursor = NULL; 814 } 815 for ( i=0; i<NUM_MODELISTS; ++i ) { 816 if ( SDL_modelist[i] ) { 817 for ( j=0; SDL_modelist[i][j]; ++j ) { 818 SDL_free(SDL_modelist[i][j]); 819 } 820 SDL_free(SDL_modelist[i]); 821 SDL_modelist[i] = NULL; 822 } 823 } 824 /* Restore the original video mode */ 825 if ( _this->screen ) { 826 if ( (_this->screen->flags&SDL_FULLSCREEN) == SDL_FULLSCREEN ) { 827 BScreen bscreen; 828 bscreen.SetMode(&saved_mode); 829 } 830 _this->screen->pixels = NULL; 831 } 832 833 #if SDL_VIDEO_OPENGL 834 if (_this->gl_config.dll_handle != NULL) 835 unload_add_on((image_id)_this->gl_config.dll_handle); 836 #endif 837 838 SDL_QuitBeApp(); 839 } 840 841 }; /* Extern C */ 842