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