Mercurial > sdl-ios-xcode
comparison src/video/picogui/SDL_pgvideo.c @ 433:706de3956894
Added initial support for PicoGUI (thanks Micah!)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 01 Aug 2002 23:24:13 +0000 |
parents | |
children | b8d311d90021 |
comparison
equal
deleted
inserted
replaced
432:80a35d43a58f | 433:706de3956894 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 | |
22 Micah Dowty | |
23 micahjd@users.sourceforge.net | |
24 */ | |
25 | |
26 #ifdef SAVE_RCSID | |
27 static char rcsid = | |
28 "@(#) $Id$"; | |
29 #endif | |
30 | |
31 #include <stdio.h> | |
32 #include <stdlib.h> | |
33 #include <string.h> | |
34 | |
35 #include "SDL.h" | |
36 #include "SDL_error.h" | |
37 #include "SDL_video.h" | |
38 #include "SDL_mouse.h" | |
39 #include "SDL_sysvideo.h" | |
40 #include "SDL_pixels_c.h" | |
41 #include "SDL_events_c.h" | |
42 | |
43 #include "SDL_pgvideo.h" | |
44 #include "SDL_pgevents_c.h" | |
45 | |
46 #define PGVID_DRIVER_NAME "picogui" | |
47 | |
48 /* Initialization/Query functions */ | |
49 static int PG_VideoInit(_THIS, SDL_PixelFormat *vformat); | |
50 static SDL_Rect **PG_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); | |
51 static SDL_Surface *PG_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); | |
52 static int PG_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); | |
53 static void PG_VideoQuit(_THIS); | |
54 | |
55 /* Hardware surface functions */ | |
56 static int PG_AllocHWSurface(_THIS, SDL_Surface *surface); | |
57 static int PG_LockHWSurface(_THIS, SDL_Surface *surface); | |
58 static void PG_UnlockHWSurface(_THIS, SDL_Surface *surface); | |
59 static void PG_FreeHWSurface(_THIS, SDL_Surface *surface); | |
60 | |
61 /* etc. */ | |
62 static void PG_UpdateRects(_THIS, int numrects, SDL_Rect *rects); | |
63 | |
64 // The implementation dependent data for the window manager cursor | |
65 struct WMcursor { | |
66 /* Our cursor is a PicoGUI theme */ | |
67 pghandle theme; | |
68 } ; | |
69 | |
70 /* WM functions */ | |
71 void PG_SetCaption(_THIS, const char *title, const char *icon); | |
72 WMcursor * PG_CreateWMCursor (_THIS,Uint8 * data, Uint8 * mask, | |
73 int w, int h, int hot_x, int hot_y); | |
74 void PG_FreeWMCursor (_THIS, WMcursor * cursor); | |
75 void PG_WarpWMCursor(_THIS, Uint16 x, Uint16 y); | |
76 int PG_ShowWMCursor (_THIS, WMcursor * cursor); | |
77 | |
78 /* PicoGUI driver bootstrap functions */ | |
79 | |
80 static int PG_Available(void) | |
81 { | |
82 /* FIXME: The current client lib doesn't give a way to see if the picogui | |
83 * server is reachable without causing a fatal error if it isn't. | |
84 * This should be fixed in cli_c2, but until then assume we can | |
85 * connect. Since more common drivers like X11 are probed first anyway, | |
86 * this shouldn't be a huge problem. | |
87 */ | |
88 return(1); | |
89 } | |
90 | |
91 static void PG_DeleteDevice(SDL_VideoDevice *device) | |
92 { | |
93 free(device->hidden); | |
94 free(device); | |
95 } | |
96 | |
97 static SDL_VideoDevice *PG_CreateDevice(int devindex) | |
98 { | |
99 SDL_VideoDevice *device; | |
100 | |
101 /* Initialize all variables that we clean on shutdown */ | |
102 device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); | |
103 if ( device ) { | |
104 memset(device, 0, (sizeof *device)); | |
105 device->hidden = (struct SDL_PrivateVideoData *) | |
106 malloc((sizeof *device->hidden)); | |
107 } | |
108 if ( (device == NULL) || (device->hidden == NULL) ) { | |
109 SDL_OutOfMemory(); | |
110 if ( device ) { | |
111 free(device); | |
112 } | |
113 return(0); | |
114 } | |
115 memset(device->hidden, 0, (sizeof *device->hidden)); | |
116 | |
117 /* Set the function pointers */ | |
118 device->VideoInit = PG_VideoInit; | |
119 device->ListModes = PG_ListModes; | |
120 device->SetVideoMode = PG_SetVideoMode; | |
121 device->CreateYUVOverlay = NULL; | |
122 device->SetColors = PG_SetColors; | |
123 device->UpdateRects = PG_UpdateRects; | |
124 device->VideoQuit = PG_VideoQuit; | |
125 device->AllocHWSurface = PG_AllocHWSurface; | |
126 device->CheckHWBlit = NULL; | |
127 device->FillHWRect = NULL; | |
128 device->SetHWColorKey = NULL; | |
129 device->SetHWAlpha = NULL; | |
130 device->LockHWSurface = PG_LockHWSurface; | |
131 device->UnlockHWSurface = PG_UnlockHWSurface; | |
132 device->FlipHWSurface = NULL; | |
133 device->FreeHWSurface = PG_FreeHWSurface; | |
134 device->SetCaption = PG_SetCaption; | |
135 device->SetIcon = NULL; | |
136 device->IconifyWindow = NULL; | |
137 device->GrabInput = NULL; | |
138 | |
139 device->PumpEvents = PG_PumpEvents; | |
140 device->InitOSKeymap = PG_InitOSKeymap; | |
141 | |
142 device->ShowWMCursor = PG_ShowWMCursor; | |
143 device->CreateWMCursor = PG_CreateWMCursor; | |
144 device->FreeWMCursor = PG_FreeWMCursor; | |
145 device->WarpWMCursor = PG_WarpWMCursor; | |
146 | |
147 device->free = PG_DeleteDevice; | |
148 | |
149 return device; | |
150 } | |
151 | |
152 VideoBootStrap PG_bootstrap = { | |
153 PGVID_DRIVER_NAME, "PicoGUI SDL driver", | |
154 PG_Available, PG_CreateDevice | |
155 }; | |
156 | |
157 | |
158 int PG_VideoInit(_THIS, SDL_PixelFormat *vformat) | |
159 { | |
160 /* Connect to the PicoGUI server. No way to process command line args yet, | |
161 * but since this is based on SHM it's not important to be able to specify | |
162 * a remote PicoGUI server. | |
163 * | |
164 * FIXME: Another nitpick about the current client lib is there's no | |
165 * clean way to indicate that command line args are not available. | |
166 */ | |
167 pgInit(0,(char**)""); | |
168 this->hidden->mi = *pgGetVideoMode(); | |
169 | |
170 /* Create a picogui application and canvas. We'll populate the canvas later. */ | |
171 this->hidden->wApp = pgRegisterApp(PG_APP_NORMAL,"SDL",0); | |
172 this->hidden->wCanvas = pgNewWidget(PG_WIDGET_CANVAS,0,0); | |
173 pgSetWidget(PGDEFAULT, | |
174 PG_WP_SIDE, PG_S_ALL, | |
175 0); | |
176 | |
177 PG_InitEvents(this); | |
178 | |
179 /* Determine the screen depth. | |
180 * We change this during the SDL_SetVideoMode implementation... | |
181 * Round up to the nearest Bytes per pixel | |
182 */ | |
183 vformat->BitsPerPixel = this->hidden->mi.bpp; | |
184 vformat->BytesPerPixel = this->hidden->mi.bpp >> 3; | |
185 if (this->hidden->mi.bpp & 7) | |
186 vformat->BytesPerPixel++; | |
187 | |
188 /* We're done! */ | |
189 return(0); | |
190 } | |
191 | |
192 SDL_Rect **PG_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) | |
193 { | |
194 return (SDL_Rect **) -1; | |
195 } | |
196 | |
197 SDL_Surface *PG_SetVideoMode(_THIS, SDL_Surface *current, | |
198 int width, int height, int bpp, Uint32 flags) | |
199 { | |
200 if ( this->hidden->bitmap ) { | |
201 /* Free old bitmap */ | |
202 if (current->pixels) { | |
203 shmdt(current->pixels); | |
204 current->pixels = NULL; | |
205 } | |
206 pgDelete(this->hidden->bitmap); | |
207 } | |
208 | |
209 /* Allocate the new pixel format for the screen */ | |
210 if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) { | |
211 SDL_SetError("Couldn't allocate new pixel format for requested mode"); | |
212 return(NULL); | |
213 } | |
214 | |
215 /* Create a new picogui bitmap */ | |
216 this->hidden->bitmap = pgCreateBitmap(width,height); | |
217 this->hidden->shm = *pgMakeSHMBitmap(this->hidden->bitmap); | |
218 current->pixels = shmat(shmget(this->hidden->shm.shm_key, | |
219 this->hidden->shm.shm_length,0),NULL,0); | |
220 | |
221 /* Reset the canvas, and draw persistent and incremental grops. | |
222 * Use mapping and offsets to center it. | |
223 */ | |
224 | |
225 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_NUKE, 0); | |
226 | |
227 /* 0. Set the source position during incremental rendering | |
228 */ | |
229 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 5, PG_GROP_SETSRC,0,0,0,0); | |
230 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROPFLAGS, 1, PG_GROPF_INCREMENTAL); | |
231 | |
232 /* 1. Incremental bitmap rendering | |
233 */ | |
234 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 6, PG_GROP_BITMAP, | |
235 0,0,0,0,this->hidden->bitmap); | |
236 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROPFLAGS, 1, PG_GROPF_INCREMENTAL); | |
237 | |
238 /* 2. Normal bitmap rendering | |
239 */ | |
240 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_GROP, 6, PG_GROP_BITMAP, | |
241 0,0,this->hidden->shm.width,this->hidden->shm.height,this->hidden->bitmap); | |
242 | |
243 /* Set up the new mode framebuffer */ | |
244 current->flags = 0; | |
245 current->w = this->hidden->shm.width; | |
246 current->h = this->hidden->shm.height; | |
247 current->pitch = this->hidden->shm.pitch; | |
248 | |
249 /* Set up pixel format */ | |
250 current->format->BitsPerPixel = this->hidden->shm.bpp; | |
251 current->format->BytesPerPixel = this->hidden->shm.bpp >> 3; | |
252 if (this->hidden->shm.bpp & 7) | |
253 current->format->BytesPerPixel++; | |
254 current->format->palette = NULL; | |
255 current->format->Rmask = this->hidden->shm.red_mask; | |
256 current->format->Gmask = this->hidden->shm.green_mask; | |
257 current->format->Bmask = this->hidden->shm.blue_mask; | |
258 current->format->Amask = this->hidden->shm.alpha_mask; | |
259 current->format->Rshift = this->hidden->shm.red_shift; | |
260 current->format->Gshift = this->hidden->shm.green_shift; | |
261 current->format->Bshift = this->hidden->shm.blue_shift; | |
262 current->format->Ashift = this->hidden->shm.alpha_shift; | |
263 current->format->Rloss = 8 - this->hidden->shm.red_length; | |
264 current->format->Gloss = 8 - this->hidden->shm.green_length; | |
265 current->format->Bloss = 8 - this->hidden->shm.blue_length; | |
266 current->format->Aloss = 8 - this->hidden->shm.alpha_length; | |
267 | |
268 /* Draw the app */ | |
269 pgUpdate(); | |
270 | |
271 /* We're done */ | |
272 return(current); | |
273 } | |
274 | |
275 /* We don't actually allow hardware surfaces other than the main one */ | |
276 static int PG_AllocHWSurface(_THIS, SDL_Surface *surface) | |
277 { | |
278 return(-1); | |
279 } | |
280 static void PG_FreeHWSurface(_THIS, SDL_Surface *surface) | |
281 { | |
282 return; | |
283 } | |
284 | |
285 /* We need to wait for vertical retrace on page flipped displays */ | |
286 static int PG_LockHWSurface(_THIS, SDL_Surface *surface) | |
287 { | |
288 return(0); | |
289 } | |
290 | |
291 static void PG_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
292 { | |
293 return; | |
294 } | |
295 | |
296 static void PG_UpdateRects(_THIS, int numrects, SDL_Rect *rects) | |
297 { | |
298 int i; | |
299 | |
300 for (i = 0; i < numrects; i++) { | |
301 if (rects[i].w <= 0 || rects[i].h <= 0) | |
302 continue; | |
303 | |
304 /* Schedule an incremental update for this rectangle, using | |
305 * the canvas gropnodes we've loaded beforehand. | |
306 */ | |
307 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_FINDGROP, 1, 0); | |
308 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_MOVEGROP, 4, | |
309 rects[i].x, rects[i].y, | |
310 rects[i].w, rects[i].h); | |
311 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_FINDGROP, 1, 1); | |
312 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_MOVEGROP, 4, | |
313 rects[i].x, rects[i].y, | |
314 rects[i].w, rects[i].h); | |
315 | |
316 /* Go perform the update */ | |
317 pgWriteCmd(this->hidden->wCanvas, PGCANVAS_INCREMENTAL, 0); | |
318 pgSubUpdate(this->hidden->wCanvas); | |
319 } | |
320 } | |
321 | |
322 int PG_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) | |
323 { | |
324 /* do nothing of note. */ | |
325 return(1); | |
326 } | |
327 | |
328 /* Note: If we are terminated, this could be called in the middle of | |
329 another SDL video routine -- notably UpdateRects. | |
330 */ | |
331 void PG_VideoQuit(_THIS) | |
332 { | |
333 if (this->screen->pixels != NULL) | |
334 { | |
335 shmdt(this->screen->pixels); | |
336 this->screen->pixels = NULL; | |
337 pgDelete(this->hidden->bitmap); | |
338 } | |
339 pgDelete(this->hidden->wCanvas); | |
340 pgDelete(this->hidden->wApp); | |
341 } | |
342 | |
343 void PG_SetCaption(_THIS, const char *title, const char *icon) | |
344 { | |
345 if (title != NULL) | |
346 pgReplaceText(this->hidden->wApp, title); | |
347 pgUpdate(); | |
348 } | |
349 | |
350 /* FIXME: The cursor stuff isn't implemented yet! */ | |
351 | |
352 WMcursor * PG_CreateWMCursor (_THIS,Uint8 * data, Uint8 * mask, | |
353 int w, int h, int hot_x, int hot_y) | |
354 { | |
355 static WMcursor dummy; | |
356 return &dummy; | |
357 } | |
358 | |
359 void PG_FreeWMCursor (_THIS, WMcursor * cursor) | |
360 { | |
361 } | |
362 | |
363 void PG_WarpWMCursor(_THIS, Uint16 x, Uint16 y) | |
364 { | |
365 } | |
366 | |
367 int PG_ShowWMCursor (_THIS, WMcursor * cursor) | |
368 { | |
369 return 1; | |
370 } |