Mercurial > sdl-ios-xcode
annotate src/video/x11/SDL_x11image.c @ 252:e8157fcb3114
Updated the source with the correct e-mail address
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 14 Dec 2001 12:38:15 +0000 |
parents | 39877400bd1e |
children | 37fa1484f71b |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 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 | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
166
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 #include <stdlib.h> | |
166
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
29 #include <unistd.h> |
0 | 30 |
31 #include "SDL_error.h" | |
32 #include "SDL_endian.h" | |
161
eb6b76a95f2d
An expose event is now sent when using XVideo output.
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
33 #include "SDL_events_c.h" |
0 | 34 #include "SDL_x11image_c.h" |
35 | |
36 #ifndef NO_SHARED_MEMORY | |
37 | |
38 /* Shared memory information */ | |
39 extern int XShmQueryExtension(Display *dpy); /* Not in X11 headers */ | |
40 | |
41 /* Shared memory error handler routine */ | |
42 static int shm_error; | |
43 static int (*X_handler)(Display *, XErrorEvent *) = NULL; | |
44 static int shm_errhandler(Display *d, XErrorEvent *e) | |
45 { | |
46 if ( e->error_code == BadAccess ) { | |
47 ++shm_error; | |
48 return(0); | |
49 } else | |
50 return(X_handler(d,e)); | |
51 } | |
52 #endif /* ! NO_SHARED_MEMORY */ | |
53 | |
54 /* Various screen update functions available */ | |
55 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); | |
56 static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects); | |
57 | |
58 int X11_SetupImage(_THIS, SDL_Surface *screen) | |
59 { | |
60 #ifdef NO_SHARED_MEMORY | |
61 screen->pixels = malloc(screen->h*screen->pitch); | |
62 #else | |
63 /* Allocate shared memory if possible */ | |
64 if ( use_mitshm ) { | |
65 shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch, | |
66 IPC_CREAT|0777); | |
67 if ( shminfo.shmid >= 0 ) { | |
68 shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0); | |
69 shminfo.readOnly = False; | |
70 if ( shminfo.shmaddr != (char *)-1 ) { | |
71 shm_error = False; | |
72 X_handler = XSetErrorHandler(shm_errhandler); | |
73 XShmAttach(SDL_Display, &shminfo); | |
74 XSync(SDL_Display, True); | |
75 XSetErrorHandler(X_handler); | |
76 if ( shm_error == True ) | |
77 shmdt(shminfo.shmaddr); | |
78 } else { | |
79 shm_error = True; | |
80 } | |
81 shmctl(shminfo.shmid, IPC_RMID, NULL); | |
82 } else { | |
83 shm_error = True; | |
84 } | |
85 if ( shm_error == True ) | |
86 use_mitshm = 0; | |
87 } | |
88 if ( use_mitshm ) { | |
89 screen->pixels = shminfo.shmaddr; | |
90 } else { | |
91 screen->pixels = malloc(screen->h*screen->pitch); | |
92 } | |
93 #endif /* NO_SHARED_MEMORY */ | |
94 if ( screen->pixels == NULL ) { | |
95 SDL_OutOfMemory(); | |
96 return(-1); | |
97 } | |
98 | |
99 #ifdef NO_SHARED_MEMORY | |
100 { | |
101 int bpp = screen->format->BytesPerPixel; | |
102 SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual, | |
103 this->hidden->depth, ZPixmap, 0, | |
104 (char *)screen->pixels, | |
105 screen->w, screen->h, | |
106 (bpp == 3) ? 32 : bpp * 8, | |
107 0); | |
108 } | |
109 #else | |
110 if ( use_mitshm ) { | |
111 SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual, | |
112 this->hidden->depth, ZPixmap, | |
113 shminfo.shmaddr, &shminfo, | |
114 screen->w, screen->h); | |
115 } else { | |
116 int bpp = screen->format->BytesPerPixel; | |
117 SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual, | |
118 this->hidden->depth, ZPixmap, 0, | |
119 (char *)screen->pixels, | |
120 screen->w, screen->h, | |
121 (bpp == 3) ? 32 : bpp * 8, | |
122 0); | |
123 } | |
124 #endif /* NO_SHARED_MEMORY */ | |
125 if ( SDL_Ximage == NULL ) { | |
126 SDL_SetError("Couldn't create XImage"); | |
127 #ifndef NO_SHARED_MEMORY | |
128 if ( use_mitshm ) { | |
129 XShmDetach(SDL_Display, &shminfo); | |
130 XSync(SDL_Display, False); | |
131 shmdt(shminfo.shmaddr); | |
132 screen->pixels = NULL; | |
133 } | |
134 #endif /* ! NO_SHARED_MEMORY */ | |
135 return(-1); | |
136 } | |
137 screen->pitch = SDL_Ximage->bytes_per_line; | |
138 | |
139 /* Determine what blit function to use */ | |
140 #ifdef NO_SHARED_MEMORY | |
141 this->UpdateRects = X11_NormalUpdate; | |
142 #else | |
143 if ( use_mitshm ) { | |
144 this->UpdateRects = X11_MITSHMUpdate; | |
145 } else { | |
146 this->UpdateRects = X11_NormalUpdate; | |
147 } | |
148 #endif | |
149 return(0); | |
150 } | |
151 | |
152 void X11_DestroyImage(_THIS, SDL_Surface *screen) | |
153 { | |
154 if ( SDL_Ximage ) { | |
155 XDestroyImage(SDL_Ximage); | |
156 #ifndef NO_SHARED_MEMORY | |
157 if ( use_mitshm ) { | |
158 XShmDetach(SDL_Display, &shminfo); | |
159 XSync(SDL_Display, False); | |
160 shmdt(shminfo.shmaddr); | |
161 } | |
162 #endif /* ! NO_SHARED_MEMORY */ | |
163 SDL_Ximage = NULL; | |
164 } | |
165 if ( screen ) { | |
166 screen->pixels = NULL; | |
167 } | |
168 } | |
169 | |
166
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
170 /* Determine the number of CPUs in the system */ |
0 | 171 static int num_CPU(void) |
172 { | |
173 static int num_cpus = 0; | |
174 | |
175 if(!num_cpus) { | |
166
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
176 #if defined(__linux) |
0 | 177 char line[BUFSIZ]; |
178 FILE *pstat = fopen("/proc/stat", "r"); | |
179 if ( pstat ) { | |
180 while ( fgets(line, sizeof(line), pstat) ) { | |
181 if (memcmp(line, "cpu", 3) == 0 && line[3] != ' ') { | |
182 ++num_cpus; | |
183 } | |
184 } | |
185 fclose(pstat); | |
186 } | |
166
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
187 #elif defined(_SC_NPROCESSORS_ONLN) |
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
188 /* number of processors online (SVR4.0MP compliant machines) */ |
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
189 num_cpus = sysconf(_SC_NPROCESSORS_ONLN); |
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
190 #elif defined(_SC_NPROCESSORS_CONF) |
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
191 /* number of processors configured (SVR4.0MP compliant machines) */ |
39877400bd1e
Fixed Solaris nitpicks (thanks Mattias!)
Sam Lantinga <slouken@libsdl.org>
parents:
161
diff
changeset
|
192 num_cpus = sysconf(_SC_NPROCESSORS_CONF); |
0 | 193 #endif |
194 if ( num_cpus <= 0 ) { | |
195 num_cpus = 1; | |
196 } | |
197 } | |
198 return num_cpus; | |
199 } | |
200 | |
201 int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags) | |
202 { | |
203 int retval; | |
204 | |
205 X11_DestroyImage(this, screen); | |
206 if ( flags & SDL_OPENGL ) { /* No image when using GL */ | |
207 retval = 0; | |
208 } else { | |
209 retval = X11_SetupImage(this, screen); | |
210 /* We support asynchronous blitting on the display */ | |
211 if ( flags & SDL_ASYNCBLIT ) { | |
212 /* This is actually slower on single-CPU systems, | |
213 probably because of CPU contention between the | |
214 X server and the application. | |
215 Note: Is this still true with XFree86 4.0? | |
216 */ | |
217 if ( num_CPU() > 1 ) { | |
218 screen->flags |= SDL_ASYNCBLIT; | |
219 } | |
220 } | |
221 } | |
222 return(retval); | |
223 } | |
224 | |
225 /* We don't actually allow hardware surfaces other than the main one */ | |
226 int X11_AllocHWSurface(_THIS, SDL_Surface *surface) | |
227 { | |
228 return(-1); | |
229 } | |
230 void X11_FreeHWSurface(_THIS, SDL_Surface *surface) | |
231 { | |
232 return; | |
233 } | |
234 | |
235 int X11_LockHWSurface(_THIS, SDL_Surface *surface) | |
236 { | |
237 if ( (surface == SDL_VideoSurface) && blit_queued ) { | |
238 XSync(GFX_Display, False); | |
239 blit_queued = 0; | |
240 } | |
241 return(0); | |
242 } | |
243 void X11_UnlockHWSurface(_THIS, SDL_Surface *surface) | |
244 { | |
245 return; | |
246 } | |
247 | |
248 int X11_FlipHWSurface(_THIS, SDL_Surface *surface) | |
249 { | |
250 return(0); | |
251 } | |
252 | |
253 /* Byte-swap the pixels in the display image */ | |
254 static void X11_SwapAllPixels(SDL_Surface *screen) | |
255 { | |
256 int x, y; | |
257 | |
258 switch (screen->format->BytesPerPixel) { | |
259 case 2: { | |
260 Uint16 *spot; | |
261 for ( y=0; y<screen->h; ++y ) { | |
262 spot = (Uint16 *) ((Uint8 *)screen->pixels + | |
263 y * screen->pitch); | |
264 for ( x=0; x<screen->w; ++x, ++spot ) { | |
265 *spot = SDL_Swap16(*spot); | |
266 } | |
267 } | |
268 } | |
269 break; | |
270 | |
271 case 4: { | |
272 Uint32 *spot; | |
273 for ( y=0; y<screen->h; ++y ) { | |
274 spot = (Uint32 *) ((Uint8 *)screen->pixels + | |
275 y * screen->pitch); | |
276 for ( x=0; x<screen->w; ++x, ++spot ) { | |
277 *spot = SDL_Swap32(*spot); | |
278 } | |
279 } | |
280 } | |
281 break; | |
282 | |
283 default: | |
284 /* should never get here */ | |
285 break; | |
286 } | |
287 } | |
288 static void X11_SwapPixels(SDL_Surface *screen, SDL_Rect *rect) | |
289 { | |
290 int x, minx, maxx; | |
291 int y, miny, maxy; | |
292 | |
293 switch (screen->format->BytesPerPixel) { | |
294 case 2: { | |
295 Uint16 *spot; | |
296 minx = rect->x; | |
297 maxx = rect->x + rect->w; | |
298 miny = rect->y; | |
299 maxy = rect->y + rect->h; | |
300 for ( y=miny; y<maxy; ++y ) { | |
301 spot = (Uint16 *) ((Uint8 *)screen->pixels + | |
302 y * screen->pitch + minx * 2); | |
303 for ( x=minx; x<maxx; ++x, ++spot ) { | |
304 *spot = SDL_Swap16(*spot); | |
305 } | |
306 } | |
307 } | |
308 break; | |
309 | |
310 case 4: { | |
311 Uint32 *spot; | |
312 minx = rect->x; | |
313 maxx = rect->x + rect->w; | |
314 miny = rect->y; | |
315 maxy = rect->y + rect->h; | |
316 for ( y=miny; y<maxy; ++y ) { | |
317 spot = (Uint32 *) ((Uint8 *)screen->pixels + | |
318 y * screen->pitch + minx * 4); | |
319 for ( x=minx; x<maxx; ++x, ++spot ) { | |
320 *spot = SDL_Swap32(*spot); | |
321 } | |
322 } | |
323 } | |
324 break; | |
325 | |
326 default: | |
327 /* should never get here */ | |
328 break; | |
329 } | |
330 } | |
331 | |
332 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) | |
333 { | |
334 int i; | |
335 | |
336 /* Check for endian-swapped X server, swap if necessary (VERY slow!) */ | |
337 if ( swap_pixels && | |
338 ((this->screen->format->BytesPerPixel%2) == 0) ) { | |
339 for ( i=0; i<numrects; ++i ) { | |
340 if ( ! rects[i].w ) { /* Clipped? */ | |
341 continue; | |
342 } | |
343 X11_SwapPixels(this->screen, rects + i); | |
344 XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, | |
345 rects[i].x, rects[i].y, | |
346 rects[i].x, rects[i].y, rects[i].w, rects[i].h); | |
347 X11_SwapPixels(this->screen, rects + i); | |
348 } | |
349 } else { | |
350 for ( i=0; i<numrects; ++i ) { | |
351 if ( ! rects[i].w ) { /* Clipped? */ | |
352 continue; | |
353 } | |
354 XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, | |
355 rects[i].x, rects[i].y, | |
356 rects[i].x, rects[i].y, rects[i].w, rects[i].h); | |
357 } | |
358 } | |
359 if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { | |
360 XFlush(GFX_Display); | |
361 ++blit_queued; | |
362 } else { | |
363 XSync(GFX_Display, False); | |
364 } | |
365 } | |
366 | |
367 static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects) | |
368 { | |
369 #ifndef NO_SHARED_MEMORY | |
370 int i; | |
371 | |
372 for ( i=0; i<numrects; ++i ) { | |
373 if ( ! rects[i].w ) { /* Clipped? */ | |
374 continue; | |
375 } | |
376 XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, | |
377 rects[i].x, rects[i].y, | |
378 rects[i].x, rects[i].y, rects[i].w, rects[i].h, | |
379 False); | |
380 } | |
381 if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { | |
382 XFlush(GFX_Display); | |
383 ++blit_queued; | |
384 } else { | |
385 XSync(GFX_Display, False); | |
386 } | |
387 #endif /* ! NO_SHARED_MEMORY */ | |
388 } | |
389 | |
390 /* There's a problem with the automatic refreshing of the display. | |
391 Even though the XVideo code uses the GFX_Display to update the | |
392 video memory, it appears that updating the window asynchronously | |
393 from a different thread will cause "blackouts" of the window. | |
394 This is a sort of a hacked workaround for the problem. | |
395 */ | |
396 static int enable_autorefresh = 1; | |
397 | |
398 void X11_DisableAutoRefresh(_THIS) | |
399 { | |
400 --enable_autorefresh; | |
401 } | |
402 | |
403 void X11_EnableAutoRefresh(_THIS) | |
404 { | |
405 ++enable_autorefresh; | |
406 } | |
407 | |
408 void X11_RefreshDisplay(_THIS) | |
409 { | |
161
eb6b76a95f2d
An expose event is now sent when using XVideo output.
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
410 /* Don't refresh a display that doesn't have an image (like GL) |
eb6b76a95f2d
An expose event is now sent when using XVideo output.
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
411 Instead, post an expose event so the application can refresh. |
eb6b76a95f2d
An expose event is now sent when using XVideo output.
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
412 */ |
0 | 413 if ( ! SDL_Ximage || (enable_autorefresh <= 0) ) { |
161
eb6b76a95f2d
An expose event is now sent when using XVideo output.
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
414 SDL_PrivateExpose(); |
0 | 415 return; |
416 } | |
417 #ifndef NO_SHARED_MEMORY | |
418 if ( this->UpdateRects == X11_MITSHMUpdate ) { | |
419 XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, | |
420 0, 0, 0, 0, this->screen->w, this->screen->h, | |
421 False); | |
422 } else { | |
423 #else | |
424 { | |
425 #endif /* ! NO_SHARED_MEMORY */ | |
426 /* Check for endian-swapped X server, swap if necessary */ | |
427 if ( swap_pixels && | |
428 ((this->screen->format->BytesPerPixel%2) == 0) ) { | |
429 X11_SwapAllPixels(this->screen); | |
430 XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, | |
431 0, 0, 0, 0, this->screen->w, this->screen->h); | |
432 X11_SwapAllPixels(this->screen); | |
433 } else { | |
434 XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, | |
435 0, 0, 0, 0, this->screen->w, this->screen->h); | |
436 } | |
437 } | |
438 XSync(SDL_Display, False); | |
439 } |