comparison src/video/x11/SDL_x11image.c @ 270:37fa1484f71b

From: "Mattias Engdeg�rd" <f91-men@nada.kth.se> To: slouken@devolution.com Subject: Re: [SDL] Question about SDL_FillRect() I benchmarked with and without clipping UpdateRects and was unable to find any difference on my moderately slow machine. Anyway, I haven't added clipping in this patch, but fixed a couple of bugs and generally cleaned up some of the X11 image code. Most importantly, UpdateRects now checks for both zero height and width. Also, I eliminated the entire code to byteswap X11 images since X11 can do that automatically if you ask it nicely :-)
author Sam Lantinga <slouken@libsdl.org>
date Fri, 18 Jan 2002 22:02:03 +0000
parents e8157fcb3114
children f6ffac90895c
comparison
equal deleted inserted replaced
269:4125b9859c71 270:37fa1484f71b
42 static int shm_error; 42 static int shm_error;
43 static int (*X_handler)(Display *, XErrorEvent *) = NULL; 43 static int (*X_handler)(Display *, XErrorEvent *) = NULL;
44 static int shm_errhandler(Display *d, XErrorEvent *e) 44 static int shm_errhandler(Display *d, XErrorEvent *e)
45 { 45 {
46 if ( e->error_code == BadAccess ) { 46 if ( e->error_code == BadAccess ) {
47 ++shm_error; 47 shm_error = 1;
48 return(0); 48 return(0);
49 } else 49 } else
50 return(X_handler(d,e)); 50 return(X_handler(d,e));
51 } 51 }
52
53 static void try_mitshm(_THIS, SDL_Surface *screen)
54 {
55 if(!use_mitshm)
56 return;
57 shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch,
58 IPC_CREAT | 0777);
59 if ( shminfo.shmid >= 0 ) {
60 shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0);
61 shminfo.readOnly = False;
62 if ( shminfo.shmaddr != (char *)-1 ) {
63 shm_error = False;
64 X_handler = XSetErrorHandler(shm_errhandler);
65 XShmAttach(SDL_Display, &shminfo);
66 XSync(SDL_Display, True);
67 XSetErrorHandler(X_handler);
68 if (shm_error)
69 shmdt(shminfo.shmaddr);
70 } else {
71 shm_error = True;
72 }
73 shmctl(shminfo.shmid, IPC_RMID, NULL);
74 } else {
75 shm_error = True;
76 }
77 if ( shm_error )
78 use_mitshm = 0;
79 if ( use_mitshm )
80 screen->pixels = shminfo.shmaddr;
81 }
52 #endif /* ! NO_SHARED_MEMORY */ 82 #endif /* ! NO_SHARED_MEMORY */
53 83
54 /* Various screen update functions available */ 84 /* Various screen update functions available */
55 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); 85 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
56 static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects); 86 static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects);
57 87
58 int X11_SetupImage(_THIS, SDL_Surface *screen) 88 int X11_SetupImage(_THIS, SDL_Surface *screen)
59 { 89 {
60 #ifdef NO_SHARED_MEMORY 90 #ifndef NO_SHARED_MEMORY
61 screen->pixels = malloc(screen->h*screen->pitch); 91 try_mitshm(this, screen);
62 #else 92 if(use_mitshm) {
63 /* Allocate shared memory if possible */ 93 SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual,
64 if ( use_mitshm ) { 94 this->hidden->depth, ZPixmap,
65 shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch, 95 shminfo.shmaddr, &shminfo,
66 IPC_CREAT|0777); 96 screen->w, screen->h);
67 if ( shminfo.shmid >= 0 ) { 97 if(!SDL_Ximage) {
68 shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0); 98 XShmDetach(SDL_Display, &shminfo);
69 shminfo.readOnly = False; 99 XSync(SDL_Display, False);
70 if ( shminfo.shmaddr != (char *)-1 ) { 100 shmdt(shminfo.shmaddr);
71 shm_error = False; 101 screen->pixels = NULL;
72 X_handler = XSetErrorHandler(shm_errhandler); 102 goto error;
73 XShmAttach(SDL_Display, &shminfo); 103 }
74 XSync(SDL_Display, True); 104 this->UpdateRects = X11_MITSHMUpdate;
75 XSetErrorHandler(X_handler); 105 }
76 if ( shm_error == True ) 106 #endif /* not NO_SHARED_MEMORY */
77 shmdt(shminfo.shmaddr); 107 if(!use_mitshm) {
78 } else { 108 int bpp;
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); 109 screen->pixels = malloc(screen->h*screen->pitch);
92 } 110 if ( screen->pixels == NULL ) {
93 #endif /* NO_SHARED_MEMORY */ 111 SDL_OutOfMemory();
94 if ( screen->pixels == NULL ) { 112 return -1;
95 SDL_OutOfMemory(); 113 }
96 return(-1); 114 bpp = screen->format->BytesPerPixel;
97 }
98
99 #ifdef NO_SHARED_MEMORY
100 {
101 int bpp = screen->format->BytesPerPixel;
102 SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual, 115 SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual,
103 this->hidden->depth, ZPixmap, 0, 116 this->hidden->depth, ZPixmap, 0,
104 (char *)screen->pixels, 117 (char *)screen->pixels,
105 screen->w, screen->h, 118 screen->w, screen->h,
106 (bpp == 3) ? 32 : bpp * 8, 119 32, 0);
107 0); 120 if ( SDL_Ximage == NULL )
108 } 121 goto error;
109 #else 122 /* XPutImage will convert byte sex automatically */
110 if ( use_mitshm ) { 123 SDL_Ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN)
111 SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual, 124 ? MSBFirst : LSBFirst;
112 this->hidden->depth, ZPixmap, 125 this->UpdateRects = X11_NormalUpdate;
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 } 126 }
137 screen->pitch = SDL_Ximage->bytes_per_line; 127 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); 128 return(0);
129
130 error:
131 SDL_SetError("Couldn't create XImage");
132 return 1;
150 } 133 }
151 134
152 void X11_DestroyImage(_THIS, SDL_Surface *screen) 135 void X11_DestroyImage(_THIS, SDL_Surface *screen)
153 { 136 {
154 if ( SDL_Ximage ) { 137 if ( SDL_Ximage ) {
248 int X11_FlipHWSurface(_THIS, SDL_Surface *surface) 231 int X11_FlipHWSurface(_THIS, SDL_Surface *surface)
249 { 232 {
250 return(0); 233 return(0);
251 } 234 }
252 235
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) 236 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
333 { 237 {
334 int i; 238 int i;
335 239
336 /* Check for endian-swapped X server, swap if necessary (VERY slow!) */ 240 for (i = 0; i < numrects; ++i) {
337 if ( swap_pixels && 241 if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */
338 ((this->screen->format->BytesPerPixel%2) == 0) ) { 242 continue;
339 for ( i=0; i<numrects; ++i ) { 243 }
340 if ( ! rects[i].w ) { /* Clipped? */ 244 XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage,
341 continue; 245 rects[i].x, rects[i].y,
342 } 246 rects[i].x, rects[i].y, rects[i].w, rects[i].h);
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 } 247 }
359 if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { 248 if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) {
360 XFlush(GFX_Display); 249 XFlush(GFX_Display);
361 ++blit_queued; 250 blit_queued = 1;
362 } else { 251 } else {
363 XSync(GFX_Display, False); 252 XSync(GFX_Display, False);
364 } 253 }
365 } 254 }
366 255
368 { 257 {
369 #ifndef NO_SHARED_MEMORY 258 #ifndef NO_SHARED_MEMORY
370 int i; 259 int i;
371 260
372 for ( i=0; i<numrects; ++i ) { 261 for ( i=0; i<numrects; ++i ) {
373 if ( ! rects[i].w ) { /* Clipped? */ 262 if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */
374 continue; 263 continue;
375 } 264 }
376 XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, 265 XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage,
377 rects[i].x, rects[i].y, 266 rects[i].x, rects[i].y,
378 rects[i].x, rects[i].y, rects[i].w, rects[i].h, 267 rects[i].x, rects[i].y, rects[i].w, rects[i].h,
379 False); 268 False);
380 } 269 }
381 if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { 270 if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) {
382 XFlush(GFX_Display); 271 XFlush(GFX_Display);
383 ++blit_queued; 272 blit_queued = 1;
384 } else { 273 } else {
385 XSync(GFX_Display, False); 274 XSync(GFX_Display, False);
386 } 275 }
387 #endif /* ! NO_SHARED_MEMORY */ 276 #endif /* ! NO_SHARED_MEMORY */
388 } 277 }
417 #ifndef NO_SHARED_MEMORY 306 #ifndef NO_SHARED_MEMORY
418 if ( this->UpdateRects == X11_MITSHMUpdate ) { 307 if ( this->UpdateRects == X11_MITSHMUpdate ) {
419 XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, 308 XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage,
420 0, 0, 0, 0, this->screen->w, this->screen->h, 309 0, 0, 0, 0, this->screen->w, this->screen->h,
421 False); 310 False);
422 } else { 311 } else
423 #else 312 #endif /* ! NO_SHARED_MEMORY */
424 { 313 {
425 #endif /* ! NO_SHARED_MEMORY */ 314 XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage,
426 /* Check for endian-swapped X server, swap if necessary */ 315 0, 0, 0, 0, this->screen->w, this->screen->h);
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 } 316 }
438 XSync(SDL_Display, False); 317 XSync(SDL_Display, False);
439 } 318 }