SDL-1.2.14
[sdl_omap.git] / src / video / nanox / SDL_nxvideo.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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 #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 }