1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 Copyright (C) 2001 Hsieh-Fu Tsai 5 Copyright (C) 2002 Greg Haerr <greg (at) censoft.com> 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Library General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Library General Public License for more details. 16 17 You should have received a copy of the GNU Library General Public 18 License along with this library; if not, write to the Free 19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 21 Sam Lantinga 22 slouken (at) libsdl.org 23 24 Hsieh-Fu Tsai 25 clare (at) setabox.com 26 */ 27 #include "SDL_config.h" 28 29 #include "SDL_thread.h" 30 #include "SDL_video.h" 31 #include "../SDL_pixels_c.h" 32 #include "../../events/SDL_events_c.h" 33 34 #define MWINCLUDECOLORS 35 #include "SDL_nxvideo.h" 36 #include "SDL_nxmodes_c.h" 37 #include "SDL_nxwm_c.h" 38 #include "SDL_nxmouse_c.h" 39 #include "SDL_nximage_c.h" 40 #include "SDL_nxevents_c.h" 41 42 // Initialization/Query functions 43 static int NX_VideoInit (_THIS, SDL_PixelFormat * vformat) ; 44 static SDL_Surface * NX_SetVideoMode (_THIS, SDL_Surface * current, int width, int height, int bpp, Uint32 flags) ; 45 static int NX_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color * colors) ; 46 static void NX_VideoQuit (_THIS) ; 47 static void NX_DestroyWindow (_THIS, SDL_Surface * screen) ; 48 static int NX_ToggleFullScreen (_THIS, int on) ; 49 static void NX_UpdateMouse (_THIS) ; 50 static int NX_SetGammaRamp (_THIS, Uint16 * ramp) ; 51 static int NX_GetGammaRamp (_THIS, Uint16 * ramp) ; 52 53 // Microwin driver bootstrap functions 54 static int NX_Available () 55 { 56 Dprintf ("enter NX_Available\n") ; 57 58 if (GrOpen () < 0) return 0 ; 59 GrClose () ; 60 61 Dprintf ("leave NX_Available\n") ; 62 return 1 ; 63 } 64 65 static void NX_DeleteDevice (SDL_VideoDevice * device) 66 { 67 Dprintf ("enter NX_DeleteDevice\n") ; 68 69 if (device) { 70 if (device -> hidden) SDL_free (device -> hidden) ; 71 if (device -> gl_data) SDL_free (device -> gl_data) ; 72 SDL_free (device) ; 73 } 74 75 Dprintf ("leave NX_DeleteDevice\n") ; 76 } 77 78 static SDL_VideoDevice * NX_CreateDevice (int devindex) 79 { 80 SDL_VideoDevice * device ; 81 82 Dprintf ("enter NX_CreateDevice\n") ; 83 84 // Initialize all variables that we clean on shutdown 85 device = (SDL_VideoDevice *) SDL_malloc (sizeof (SDL_VideoDevice)) ; 86 if (device) { 87 SDL_memset (device, 0, (sizeof * device)) ; 88 device -> hidden = (struct SDL_PrivateVideoData *) 89 SDL_malloc ((sizeof * device -> hidden)) ; 90 device -> gl_data = NULL ; 91 } 92 if ((device == NULL) || (device -> hidden == NULL)) { 93 SDL_OutOfMemory () ; 94 NX_DeleteDevice (device) ; 95 return 0 ; 96 } 97 SDL_memset (device -> hidden, 0, (sizeof * device -> hidden)) ; 98 99 // Set the function pointers 100 device -> VideoInit = NX_VideoInit ; 101 device -> ListModes = NX_ListModes ; 102 device -> SetVideoMode = NX_SetVideoMode ; 103 device -> ToggleFullScreen = NX_ToggleFullScreen ; 104 device -> UpdateMouse = NX_UpdateMouse ; 105 device -> CreateYUVOverlay = NULL ; 106 device -> SetColors = NX_SetColors ; 107 device -> UpdateRects = NULL ; 108 device -> VideoQuit = NX_VideoQuit; 109 device -> AllocHWSurface = NULL ; 110 device -> CheckHWBlit = NULL ; 111 device -> FillHWRect = NULL ; 112 device -> SetHWColorKey = NULL ; 113 device -> SetHWAlpha = NULL ; 114 device -> LockHWSurface = NULL ; 115 device -> UnlockHWSurface = NULL ; 116 device -> FlipHWSurface = NULL ; 117 device -> FreeHWSurface = NULL ; 118 device -> SetGamma = NULL ; 119 device -> GetGamma = NULL ; 120 device -> SetGammaRamp = NX_SetGammaRamp ; 121 device -> GetGammaRamp = NX_GetGammaRamp ; 122 123 #if SDL_VIDEO_OPENGL 124 device -> GL_LoadLibrary = NULL ; 125 device -> GL_GetProcAddress = NULL ; 126 device -> GL_GetAttribute = NULL ; 127 device -> GL_MakeCurrent = NULL ; 128 device -> GL_SwapBuffers = NULL ; 129 #endif 130 131 device -> SetIcon = NULL ; 132 device -> SetCaption = NX_SetCaption; 133 device -> IconifyWindow = NULL ; 134 device -> GrabInput = NULL ; 135 device -> GetWMInfo = NX_GetWMInfo ; 136 device -> FreeWMCursor = NX_FreeWMCursor ; 137 device -> CreateWMCursor = NX_CreateWMCursor ; 138 device -> ShowWMCursor = NX_ShowWMCursor ; 139 device -> WarpWMCursor = NX_WarpWMCursor ; 140 device -> CheckMouseMode = NULL ; 141 device -> InitOSKeymap = NX_InitOSKeymap ; 142 device -> PumpEvents = NX_PumpEvents ; 143 144 device -> free = NX_DeleteDevice ; 145 146 Dprintf ("leave NX_CreateDevice\n") ; 147 return device ; 148 } 149 150 VideoBootStrap NX_bootstrap = { 151 "nanox", "nanox", NX_Available, NX_CreateDevice 152 } ; 153 154 static void create_aux_windows (_THIS) 155 { 156 GR_WM_PROPERTIES props ; 157 158 Dprintf ("enter create_aux_windows\n") ; 159 160 // Don't create any extra windows if we are being managed 161 if (SDL_windowid) { 162 FSwindow = 0 ; 163 return ; 164 } 165 166 if (FSwindow && FSwindow != GR_ROOT_WINDOW_ID) { 167 GrDestroyWindow (FSwindow) ; 168 } 169 170 FSwindow = GrNewWindow (GR_ROOT_WINDOW_ID, 0, 0, 1, 1, 0, BLACK, BLACK) ; 171 props.flags = GR_WM_FLAGS_PROPS ; 172 props.props = GR_WM_PROPS_NODECORATE ; 173 GrSetWMProperties (FSwindow, & props) ; 174 175 GrSelectEvents (FSwindow, (GR_EVENT_MASK_EXPOSURE | 176 GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP | 177 GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT | 178 GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP | 179 GR_EVENT_MASK_MOUSE_ENTER | GR_EVENT_MASK_MOUSE_EXIT | 180 GR_EVENT_MASK_MOUSE_MOTION | GR_EVENT_MASK_UPDATE | 181 GR_EVENT_MASK_CLOSE_REQ)) ; 182 183 Dprintf ("leave create_aux_windows\n") ; 184 } 185 186 int NX_VideoInit (_THIS, SDL_PixelFormat * vformat) 187 { 188 GR_SCREEN_INFO si ; 189 190 Dprintf ("enter NX_VideoInit\n") ; 191 192 if (GrOpen () < 0) { 193 SDL_SetError ("GrOpen() fail") ; 194 return -1 ; 195 } 196 197 // use share memory to speed up 198 #ifdef NANOX_SHARE_MEMORY 199 GrReqShmCmds (0xFFFF); 200 #endif 201 202 SDL_Window = 0 ; 203 FSwindow = 0 ; 204 205 GammaRamp_R = NULL ; 206 GammaRamp_G = NULL ; 207 GammaRamp_B = NULL ; 208 209 GrGetScreenInfo (& si) ; 210 SDL_Visual.bpp = si.bpp ; 211 212 /* Determine the current screen size */ 213 this->info.current_w = si.cols ; 214 this->info.current_h = si.rows ; 215 216 // GetVideoMode 217 SDL_modelist = (SDL_Rect **) SDL_malloc (sizeof (SDL_Rect *) * 2) ; 218 if (SDL_modelist) { 219 SDL_modelist [0] = (SDL_Rect *) SDL_malloc (sizeof(SDL_Rect)) ; 220 if (SDL_modelist [0]) { 221 SDL_modelist [0] -> x = 0 ; 222 SDL_modelist [0] -> y = 0 ; 223 SDL_modelist [0] -> w = si.cols ; 224 SDL_modelist [0] -> h = si.rows ; 225 } 226 SDL_modelist [1] = NULL ; 227 } 228 229 pixel_type = si.pixtype; 230 SDL_Visual.red_mask = si.rmask; 231 SDL_Visual.green_mask = si.gmask; 232 SDL_Visual.blue_mask = si.bmask; 233 234 vformat -> BitsPerPixel = SDL_Visual.bpp ; 235 if (vformat -> BitsPerPixel > 8) { 236 vformat -> Rmask = SDL_Visual.red_mask ; 237 vformat -> Gmask = SDL_Visual.green_mask ; 238 vformat -> Bmask = SDL_Visual.blue_mask ; 239 } 240 241 // See if we have been passed a window to use 242 SDL_windowid = getenv ("SDL_WINDOWID") ; 243 244 // Create the fullscreen (and managed windows : no implement) 245 create_aux_windows (this) ; 246 247 Dprintf ("leave NX_VideoInit\n") ; 248 return 0 ; 249 } 250 251 void NX_VideoQuit (_THIS) 252 { 253 Dprintf ("enter NX_VideoQuit\n") ; 254 255 // Start shutting down the windows 256 NX_DestroyImage (this, this -> screen) ; 257 NX_DestroyWindow (this, this -> screen) ; 258 if (FSwindow && FSwindow != GR_ROOT_WINDOW_ID) { 259 GrDestroyWindow (FSwindow) ; 260 } 261 NX_FreeVideoModes (this) ; 262 SDL_free (GammaRamp_R) ; 263 SDL_free (GammaRamp_G) ; 264 SDL_free (GammaRamp_B) ; 265 266 #ifdef ENABLE_NANOX_DIRECT_FB 267 if (Clientfb) 268 GrCloseClientFramebuffer(); 269 #endif 270 GrClose () ; 271 272 Dprintf ("leave NX_VideoQuit\n") ; 273 } 274 275 static void NX_DestroyWindow (_THIS, SDL_Surface * screen) 276 { 277 Dprintf ("enter NX_DestroyWindow\n") ; 278 279 if (! SDL_windowid) { 280 if (screen && (screen -> flags & SDL_FULLSCREEN)) { 281 screen -> flags &= ~ SDL_FULLSCREEN ; 282 NX_LeaveFullScreen (this) ; 283 } 284 285 // Destroy the output window 286 if (SDL_Window && SDL_Window != GR_ROOT_WINDOW_ID) { 287 GrDestroyWindow (SDL_Window) ; 288 } 289 } 290 291 // Free the graphics context 292 if (! SDL_GC) { 293 GrDestroyGC (SDL_GC) ; 294 SDL_GC = 0; 295 } 296 297 Dprintf ("leave NX_DestroyWindow\n") ; 298 } 299 300 static int NX_CreateWindow (_THIS, SDL_Surface * screen, 301 int w, int h, int bpp, Uint32 flags) 302 { 303 Dprintf ("enter NX_CreateWindow\n") ; 304 305 // If a window is already present, destroy it and start fresh 306 if (SDL_Window && SDL_Window != GR_ROOT_WINDOW_ID) { 307 NX_DestroyWindow (this, screen) ; 308 } 309 310 // See if we have been given a window id 311 if (SDL_windowid) { 312 SDL_Window = SDL_strtol (SDL_windowid, NULL, 0) ; 313 } else { 314 SDL_Window = 0 ; 315 } 316 317 if ( ! SDL_ReallocFormat (screen, bpp, SDL_Visual.red_mask, 318 SDL_Visual.green_mask, SDL_Visual.blue_mask, 0)) 319 return -1; 320 321 // Create (or use) the nanox display window 322 if (! SDL_windowid) { 323 324 SDL_Window = GrNewWindow (GR_ROOT_WINDOW_ID, 0, 0, w, h, 0, BLACK, WHITE) ; 325 326 GrSelectEvents (SDL_Window, (GR_EVENT_MASK_EXPOSURE | 327 GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP | 328 GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT | 329 GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP | 330 GR_EVENT_MASK_MOUSE_ENTER | GR_EVENT_MASK_MOUSE_EXIT | 331 GR_EVENT_MASK_MOUSE_MOTION | GR_EVENT_MASK_UPDATE | 332 GR_EVENT_MASK_CLOSE_REQ)) ; 333 } 334 335 /* Create the graphics context here, once we have a window */ 336 SDL_GC = GrNewGC () ; 337 if (SDL_GC == 0) { 338 SDL_SetError("Couldn't create graphics context"); 339 return(-1); 340 } 341 342 // Map them both and go fullscreen, if requested 343 if (! SDL_windowid) { 344 GrMapWindow (SDL_Window) ; 345 if (flags & SDL_FULLSCREEN) { 346 screen -> flags |= SDL_FULLSCREEN ; 347 NX_EnterFullScreen (this) ; 348 } else { 349 screen -> flags &= ~ SDL_FULLSCREEN ; 350 } 351 } 352 353 #ifdef ENABLE_NANOX_DIRECT_FB 354 /* attempt allocating the client side framebuffer */ 355 Clientfb = GrOpenClientFramebuffer(); 356 /* NULL return will default to using GrArea()*/ 357 #endif 358 359 Dprintf ("leave NX_CreateWindow\n") ; 360 return 0 ; 361 } 362 363 SDL_Surface * NX_SetVideoMode (_THIS, SDL_Surface * current, 364 int width, int height, int bpp, Uint32 flags) 365 { 366 Dprintf ("enter NX_SetVideoMode\n") ; 367 368 // Lock the event thread, in multi-threading environments 369 SDL_Lock_EventThread () ; 370 371 bpp = SDL_Visual.bpp ; 372 if (NX_CreateWindow (this, current, width, height, bpp, flags) < 0) { 373 current = NULL; 374 goto done; 375 } 376 377 if (current -> w != width || current -> h != height) { 378 current -> w = width ; 379 current -> h = height ; 380 current -> pitch = SDL_CalculatePitch (current) ; 381 NX_ResizeImage (this, current, flags) ; 382 } 383 384 /* Clear these flags and set them only if they are in the new set. */ 385 current -> flags &= ~(SDL_RESIZABLE|SDL_NOFRAME); 386 current -> flags |= (flags & (SDL_RESIZABLE | SDL_NOFRAME)) ; 387 388 done: 389 SDL_Unlock_EventThread () ; 390 391 Dprintf ("leave NX_SetVideoMode\n") ; 392 393 // We're done! 394 return current ; 395 } 396 397 // ncolors <= 256 398 int NX_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color * colors) 399 { 400 int i ; 401 GR_PALETTE pal ; 402 403 Dprintf ("enter NX_SetColors\n") ; 404 405 if (ncolors > 256) return 0 ; 406 407 pal.count = ncolors ; 408 for (i = 0; i < ncolors; ++ i) { 409 pal.palette [i].r = colors [i].r ; 410 pal.palette [i].g = colors [i].g ; 411 pal.palette [i].b = colors [i].b ; 412 } 413 GrSetSystemPalette (firstcolor, & pal) ; 414 415 Dprintf ("leave NX_SetColors\n") ; 416 return 1 ; 417 } 418 419 static int NX_ToggleFullScreen (_THIS, int on) 420 { 421 SDL_Rect rect ; 422 Uint32 event_thread ; 423 424 Dprintf ("enter NX_ToggleFullScreen\n") ; 425 426 // Don't switch if we don't own the window 427 if (SDL_windowid) return 0 ; 428 429 // Don't lock if we are the event thread 430 event_thread = SDL_EventThreadID () ; 431 if (event_thread && (SDL_ThreadID () == event_thread)) { 432 event_thread = 0 ; 433 } 434 if (event_thread) { 435 SDL_Lock_EventThread() ; 436 } 437 438 if (on) { 439 NX_EnterFullScreen (this) ; 440 } else { 441 this -> screen -> flags &= ~ SDL_FULLSCREEN ; 442 NX_LeaveFullScreen (this) ; 443 } 444 445 rect.x = rect.y = 0 ; 446 rect.w = this -> screen -> w, rect.h = this -> screen -> h ; 447 NX_NormalUpdate (this, 1, & rect) ; 448 449 if (event_thread) { 450 SDL_Unlock_EventThread () ; 451 } 452 453 Dprintf ("leave NX_ToggleFullScreen\n") ; 454 return 1 ; 455 } 456 457 // Update the current mouse state and position 458 static void NX_UpdateMouse (_THIS) 459 { 460 int x, y ; 461 GR_WINDOW_INFO info ; 462 GR_SCREEN_INFO si ; 463 464 465 Dprintf ("enter NX_UpdateMouse\n") ; 466 467 // Lock the event thread, in multi-threading environments 468 SDL_Lock_EventThread () ; 469 470 GrGetScreenInfo (& si) ; 471 GrGetWindowInfo (SDL_Window, & info) ; 472 x = si.xpos - info.x ; 473 y = si.ypos - info.y ; 474 if (x >= 0 && x <= info.width && y >= 0 && y <= info.height) { 475 SDL_PrivateAppActive (1, SDL_APPMOUSEFOCUS) ; 476 SDL_PrivateMouseMotion (0, 0, x, y); 477 } else { 478 SDL_PrivateAppActive (0, SDL_APPMOUSEFOCUS) ; 479 } 480 481 SDL_Unlock_EventThread () ; 482 Dprintf ("leave NX_UpdateMouse\n") ; 483 } 484 485 static int NX_SetGammaRamp (_THIS, Uint16 * ramp) 486 { 487 int i ; 488 Uint16 * red, * green, * blue ; 489 490 Dprintf ("enter NX_SetGammaRamp\n") ; 491 492 if (SDL_Visual.bpp != 32 && SDL_Visual.bpp != 24) return -1 ; 493 494 if (! GammaRamp_R) GammaRamp_R = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; 495 if (! GammaRamp_G) GammaRamp_G = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; 496 if (! GammaRamp_B) GammaRamp_B = (Uint16 *) SDL_malloc (sizeof (Uint16) * CI_SIZE) ; 497 if ((! GammaRamp_R) || (! GammaRamp_G) || (! GammaRamp_B)) { 498 SDL_OutOfMemory () ; 499 return -1 ; 500 } 501 502 for (i = 0; i < CI_SIZE; ++ i) 503 GammaRamp_R [i] = GammaRamp_G [i] = GammaRamp_B [i] = i ; 504 505 red = ramp ; 506 green = ramp + CI_SIZE ; 507 blue = green + CI_SIZE ; 508 509 for (i = 0; i < CI_SIZE; ++ i) { 510 GammaRamp_R [i] = red [i] ; 511 GammaRamp_G [i] = green [i] ; 512 GammaRamp_B [i] = blue [i] ; 513 } 514 SDL_UpdateRect(this->screen, 0, 0, 0, 0); 515 516 Dprintf ("leave NX_SetGammaRamp\n") ; 517 return 0 ; 518 } 519 520 static int NX_GetGammaRamp (_THIS, Uint16 * ramp) 521 { 522 int i ; 523 Uint16 * red, * green, * blue ; 524 525 Dprintf ("enter NX_GetGammaRamp\n") ; 526 527 if (SDL_Visual.bpp != 32 && SDL_Visual.bpp != 24) return -1 ; 528 red = ramp ; 529 green = ramp + CI_SIZE ; 530 blue = green + CI_SIZE ; 531 if (GammaRamp_R && GammaRamp_G && GammaRamp_B) { 532 for (i = 0; i < CI_SIZE; ++ i) { 533 red [i] = GammaRamp_R [i] ; 534 green [i] = GammaRamp_G [i] ; 535 blue [i] = GammaRamp_B [i] ; 536 } 537 } else { 538 for (i = 0; i < CI_SIZE; ++ i) 539 red [i] = green [i] = blue [i] = i ; 540 } 541 542 Dprintf ("leave NX_GetGammaRamp\n") ; 543 return 0 ; 544 } 545