comparison src/video/x11/SDL_x11image.c @ 1662:782fd950bd46 SDL-1.3

Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API. WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid. The code is now run through a consistent indent format: indent -i4 -nut -nsc -br -ce The headers are being converted to automatically generate doxygen documentation.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 28 May 2006 13:04:16 +0000
parents e49147870aac
children 4da1ee79c9af
comparison
equal deleted inserted replaced
1661:281d3f4870e5 1662:782fd950bd46
30 30
31 #ifndef NO_SHARED_MEMORY 31 #ifndef NO_SHARED_MEMORY
32 32
33 /* Shared memory error handler routine */ 33 /* Shared memory error handler routine */
34 static int shm_error; 34 static int shm_error;
35 static int (*X_handler)(Display *, XErrorEvent *) = NULL; 35 static int (*X_handler) (Display *, XErrorEvent *) = NULL;
36 static int shm_errhandler(Display *d, XErrorEvent *e) 36 static int
37 { 37 shm_errhandler (Display * d, XErrorEvent * e)
38 if ( e->error_code == BadAccess ) { 38 {
39 shm_error = True; 39 if (e->error_code == BadAccess) {
40 return(0); 40 shm_error = True;
41 } else 41 return (0);
42 return(X_handler(d,e)); 42 } else
43 } 43 return (X_handler (d, e));
44 44 }
45 static void try_mitshm(_THIS, SDL_Surface *screen) 45
46 { 46 static void
47 /* Dynamic X11 may not have SHM entry points on this box. */ 47 try_mitshm (_THIS, SDL_Surface * screen)
48 if ((use_mitshm) && (!SDL_X11_HAVE_SHM)) 48 {
49 use_mitshm = 0; 49 /* Dynamic X11 may not have SHM entry points on this box. */
50 50 if ((use_mitshm) && (!SDL_X11_HAVE_SHM))
51 if(!use_mitshm) 51 use_mitshm = 0;
52 return; 52
53 shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch, 53 if (!use_mitshm)
54 IPC_CREAT | 0777); 54 return;
55 if ( shminfo.shmid >= 0 ) { 55 shminfo.shmid = shmget (IPC_PRIVATE, screen->h * screen->pitch,
56 shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0); 56 IPC_CREAT | 0777);
57 shminfo.readOnly = False; 57 if (shminfo.shmid >= 0) {
58 if ( shminfo.shmaddr != (char *)-1 ) { 58 shminfo.shmaddr = (char *) shmat (shminfo.shmid, 0, 0);
59 shm_error = False; 59 shminfo.readOnly = False;
60 X_handler = XSetErrorHandler(shm_errhandler); 60 if (shminfo.shmaddr != (char *) -1) {
61 XShmAttach(SDL_Display, &shminfo); 61 shm_error = False;
62 XSync(SDL_Display, True); 62 X_handler = XSetErrorHandler (shm_errhandler);
63 XSetErrorHandler(X_handler); 63 XShmAttach (SDL_Display, &shminfo);
64 if ( shm_error ) 64 XSync (SDL_Display, True);
65 shmdt(shminfo.shmaddr); 65 XSetErrorHandler (X_handler);
66 } else { 66 if (shm_error)
67 shm_error = True; 67 shmdt (shminfo.shmaddr);
68 } 68 } else {
69 shmctl(shminfo.shmid, IPC_RMID, NULL); 69 shm_error = True;
70 } else { 70 }
71 shm_error = True; 71 shmctl (shminfo.shmid, IPC_RMID, NULL);
72 } 72 } else {
73 if ( shm_error ) 73 shm_error = True;
74 use_mitshm = 0; 74 }
75 if ( use_mitshm ) 75 if (shm_error)
76 screen->pixels = shminfo.shmaddr; 76 use_mitshm = 0;
77 if (use_mitshm)
78 screen->pixels = shminfo.shmaddr;
77 } 79 }
78 #endif /* ! NO_SHARED_MEMORY */ 80 #endif /* ! NO_SHARED_MEMORY */
79 81
80 /* Various screen update functions available */ 82 /* Various screen update functions available */
81 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); 83 static void X11_NormalUpdate (_THIS, int numrects, SDL_Rect * rects);
82 static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects); 84 static void X11_MITSHMUpdate (_THIS, int numrects, SDL_Rect * rects);
83 85
84 int X11_SetupImage(_THIS, SDL_Surface *screen) 86 int
85 { 87 X11_SetupImage (_THIS, SDL_Surface * screen)
86 #ifndef NO_SHARED_MEMORY 88 {
87 try_mitshm(this, screen); 89 #ifndef NO_SHARED_MEMORY
88 if(use_mitshm) { 90 try_mitshm (this, screen);
89 SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual, 91 if (use_mitshm) {
90 this->hidden->depth, ZPixmap, 92 SDL_Ximage = XShmCreateImage (SDL_Display, SDL_Visual,
91 shminfo.shmaddr, &shminfo, 93 this->hidden->depth, ZPixmap,
92 screen->w, screen->h); 94 shminfo.shmaddr, &shminfo,
93 if(!SDL_Ximage) { 95 screen->w, screen->h);
94 XShmDetach(SDL_Display, &shminfo); 96 if (!SDL_Ximage) {
95 XSync(SDL_Display, False); 97 XShmDetach (SDL_Display, &shminfo);
96 shmdt(shminfo.shmaddr); 98 XSync (SDL_Display, False);
97 screen->pixels = NULL; 99 shmdt (shminfo.shmaddr);
98 goto error; 100 screen->pixels = NULL;
99 } 101 goto error;
100 this->UpdateRects = X11_MITSHMUpdate; 102 }
101 } 103 this->UpdateRects = X11_MITSHMUpdate;
102 if(!use_mitshm) 104 }
105 if (!use_mitshm)
103 #endif /* not NO_SHARED_MEMORY */ 106 #endif /* not NO_SHARED_MEMORY */
104 { 107 {
105 int bpp; 108 int bpp;
106 screen->pixels = SDL_malloc(screen->h*screen->pitch); 109 screen->pixels = SDL_malloc (screen->h * screen->pitch);
107 if ( screen->pixels == NULL ) { 110 if (screen->pixels == NULL) {
108 SDL_OutOfMemory(); 111 SDL_OutOfMemory ();
109 return -1; 112 return -1;
110 } 113 }
111 bpp = screen->format->BytesPerPixel; 114 bpp = screen->format->BytesPerPixel;
112 SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual, 115 SDL_Ximage = XCreateImage (SDL_Display, SDL_Visual,
113 this->hidden->depth, ZPixmap, 0, 116 this->hidden->depth, ZPixmap, 0,
114 (char *)screen->pixels, 117 (char *) screen->pixels,
115 screen->w, screen->h, 118 screen->w, screen->h, 32, 0);
116 32, 0); 119 if (SDL_Ximage == NULL)
117 if ( SDL_Ximage == NULL ) 120 goto error;
118 goto error; 121 /* XPutImage will convert byte sex automatically */
119 /* XPutImage will convert byte sex automatically */ 122 SDL_Ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN)
120 SDL_Ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) 123 ? MSBFirst : LSBFirst;
121 ? MSBFirst : LSBFirst; 124 this->UpdateRects = X11_NormalUpdate;
122 this->UpdateRects = X11_NormalUpdate; 125 }
123 } 126 screen->pitch = SDL_Ximage->bytes_per_line;
124 screen->pitch = SDL_Ximage->bytes_per_line; 127 return (0);
125 return(0); 128
126 129 error:
127 error: 130 SDL_SetError ("Couldn't create XImage");
128 SDL_SetError("Couldn't create XImage"); 131 return 1;
129 return 1; 132 }
130 } 133
131 134 void
132 void X11_DestroyImage(_THIS, SDL_Surface *screen) 135 X11_DestroyImage (_THIS, SDL_Surface * screen)
133 { 136 {
134 if ( SDL_Ximage ) { 137 if (SDL_Ximage) {
135 XDestroyImage(SDL_Ximage); 138 XDestroyImage (SDL_Ximage);
136 #ifndef NO_SHARED_MEMORY 139 #ifndef NO_SHARED_MEMORY
137 if ( use_mitshm ) { 140 if (use_mitshm) {
138 XShmDetach(SDL_Display, &shminfo); 141 XShmDetach (SDL_Display, &shminfo);
139 XSync(SDL_Display, False); 142 XSync (SDL_Display, False);
140 shmdt(shminfo.shmaddr); 143 shmdt (shminfo.shmaddr);
141 } 144 }
142 #endif /* ! NO_SHARED_MEMORY */ 145 #endif /* ! NO_SHARED_MEMORY */
143 SDL_Ximage = NULL; 146 SDL_Ximage = NULL;
144 } 147 }
145 if ( screen ) { 148 if (screen) {
146 screen->pixels = NULL; 149 screen->pixels = NULL;
147 } 150 }
148 } 151 }
149 152
150 /* Determine the number of CPUs in the system */ 153 /* Determine the number of CPUs in the system */
151 static int num_CPU(void) 154 static int
152 { 155 num_CPU (void)
153 static int num_cpus = 0; 156 {
154 157 static int num_cpus = 0;
155 if(!num_cpus) { 158
159 if (!num_cpus) {
156 #if defined(__LINUX__) 160 #if defined(__LINUX__)
157 char line[BUFSIZ]; 161 char line[BUFSIZ];
158 FILE *pstat = fopen("/proc/stat", "r"); 162 FILE *pstat = fopen ("/proc/stat", "r");
159 if ( pstat ) { 163 if (pstat) {
160 while ( fgets(line, sizeof(line), pstat) ) { 164 while (fgets (line, sizeof (line), pstat)) {
161 if (SDL_memcmp(line, "cpu", 3) == 0 && line[3] != ' ') { 165 if (SDL_memcmp (line, "cpu", 3) == 0 && line[3] != ' ') {
162 ++num_cpus; 166 ++num_cpus;
163 } 167 }
164 } 168 }
165 fclose(pstat); 169 fclose (pstat);
166 } 170 }
167 #elif defined(__IRIX__) 171 #elif defined(__IRIX__)
168 num_cpus = sysconf(_SC_NPROC_ONLN); 172 num_cpus = sysconf (_SC_NPROC_ONLN);
169 #elif defined(_SC_NPROCESSORS_ONLN) 173 #elif defined(_SC_NPROCESSORS_ONLN)
170 /* number of processors online (SVR4.0MP compliant machines) */ 174 /* number of processors online (SVR4.0MP compliant machines) */
171 num_cpus = sysconf(_SC_NPROCESSORS_ONLN); 175 num_cpus = sysconf (_SC_NPROCESSORS_ONLN);
172 #elif defined(_SC_NPROCESSORS_CONF) 176 #elif defined(_SC_NPROCESSORS_CONF)
173 /* number of processors configured (SVR4.0MP compliant machines) */ 177 /* number of processors configured (SVR4.0MP compliant machines) */
174 num_cpus = sysconf(_SC_NPROCESSORS_CONF); 178 num_cpus = sysconf (_SC_NPROCESSORS_CONF);
175 #endif 179 #endif
176 if ( num_cpus <= 0 ) { 180 if (num_cpus <= 0) {
177 num_cpus = 1; 181 num_cpus = 1;
178 } 182 }
179 } 183 }
180 return num_cpus; 184 return num_cpus;
181 } 185 }
182 186
183 int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags) 187 int
184 { 188 X11_ResizeImage (_THIS, SDL_Surface * screen, Uint32 flags)
185 int retval; 189 {
186 190 int retval;
187 X11_DestroyImage(this, screen); 191
188 if ( flags & SDL_INTERNALOPENGL ) { /* No image when using GL */ 192 X11_DestroyImage (this, screen);
189 retval = 0; 193 if (flags & SDL_INTERNALOPENGL) { /* No image when using GL */
190 } else { 194 retval = 0;
191 retval = X11_SetupImage(this, screen); 195 } else {
192 /* We support asynchronous blitting on the display */ 196 retval = X11_SetupImage (this, screen);
193 if ( flags & SDL_ASYNCBLIT ) { 197 /* We support asynchronous blitting on the display */
194 /* This is actually slower on single-CPU systems, 198 if (flags & SDL_ASYNCBLIT) {
195 probably because of CPU contention between the 199 /* This is actually slower on single-CPU systems,
196 X server and the application. 200 probably because of CPU contention between the
197 Note: Is this still true with XFree86 4.0? 201 X server and the application.
198 */ 202 Note: Is this still true with XFree86 4.0?
199 if ( num_CPU() > 1 ) { 203 */
200 screen->flags |= SDL_ASYNCBLIT; 204 if (num_CPU () > 1) {
201 } 205 screen->flags |= SDL_ASYNCBLIT;
202 } 206 }
203 } 207 }
204 return(retval); 208 }
209 return (retval);
205 } 210 }
206 211
207 /* We don't actually allow hardware surfaces other than the main one */ 212 /* We don't actually allow hardware surfaces other than the main one */
208 int X11_AllocHWSurface(_THIS, SDL_Surface *surface) 213 int
209 { 214 X11_AllocHWSurface (_THIS, SDL_Surface * surface)
210 return(-1); 215 {
211 } 216 return (-1);
212 void X11_FreeHWSurface(_THIS, SDL_Surface *surface) 217 }
213 { 218
214 return; 219 void
215 } 220 X11_FreeHWSurface (_THIS, SDL_Surface * surface)
216 221 {
217 int X11_LockHWSurface(_THIS, SDL_Surface *surface) 222 return;
218 { 223 }
219 if ( (surface == SDL_VideoSurface) && blit_queued ) { 224
220 XSync(GFX_Display, False); 225 int
221 blit_queued = 0; 226 X11_LockHWSurface (_THIS, SDL_Surface * surface)
222 } 227 {
223 return(0); 228 if ((surface == SDL_VideoSurface) && blit_queued) {
224 } 229 XSync (GFX_Display, False);
225 void X11_UnlockHWSurface(_THIS, SDL_Surface *surface) 230 blit_queued = 0;
226 { 231 }
227 return; 232 return (0);
228 } 233 }
229 234
230 int X11_FlipHWSurface(_THIS, SDL_Surface *surface) 235 void
231 { 236 X11_UnlockHWSurface (_THIS, SDL_Surface * surface)
232 return(0); 237 {
233 } 238 return;
234 239 }
235 static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) 240
236 { 241 int
237 int i; 242 X11_FlipHWSurface (_THIS, SDL_Surface * surface)
238 243 {
239 for (i = 0; i < numrects; ++i) { 244 return (0);
240 if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */ 245 }
241 continue; 246
242 } 247 static void
243 XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, 248 X11_NormalUpdate (_THIS, int numrects, SDL_Rect * rects)
244 rects[i].x, rects[i].y, 249 {
245 rects[i].x, rects[i].y, rects[i].w, rects[i].h); 250 int i;
246 } 251
247 if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { 252 for (i = 0; i < numrects; ++i) {
248 XFlush(GFX_Display); 253 if (rects[i].w == 0 || rects[i].h == 0) { /* Clipped? */
249 blit_queued = 1; 254 continue;
250 } else { 255 }
251 XSync(GFX_Display, False); 256 XPutImage (GFX_Display, SDL_Window, SDL_GC, SDL_Ximage,
252 } 257 rects[i].x, rects[i].y,
253 } 258 rects[i].x, rects[i].y, rects[i].w, rects[i].h);
254 259 }
255 static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects) 260 if (SDL_VideoSurface->flags & SDL_ASYNCBLIT) {
256 { 261 XFlush (GFX_Display);
257 #ifndef NO_SHARED_MEMORY 262 blit_queued = 1;
258 int i; 263 } else {
259 264 XSync (GFX_Display, False);
260 for ( i=0; i<numrects; ++i ) { 265 }
261 if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */ 266 }
262 continue; 267
263 } 268 static void
264 XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, 269 X11_MITSHMUpdate (_THIS, int numrects, SDL_Rect * rects)
265 rects[i].x, rects[i].y, 270 {
266 rects[i].x, rects[i].y, rects[i].w, rects[i].h, 271 #ifndef NO_SHARED_MEMORY
267 False); 272 int i;
268 } 273
269 if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { 274 for (i = 0; i < numrects; ++i) {
270 XFlush(GFX_Display); 275 if (rects[i].w == 0 || rects[i].h == 0) { /* Clipped? */
271 blit_queued = 1; 276 continue;
272 } else { 277 }
273 XSync(GFX_Display, False); 278 XShmPutImage (GFX_Display, SDL_Window, SDL_GC, SDL_Ximage,
274 } 279 rects[i].x, rects[i].y,
280 rects[i].x, rects[i].y, rects[i].w, rects[i].h, False);
281 }
282 if (SDL_VideoSurface->flags & SDL_ASYNCBLIT) {
283 XFlush (GFX_Display);
284 blit_queued = 1;
285 } else {
286 XSync (GFX_Display, False);
287 }
275 #endif /* ! NO_SHARED_MEMORY */ 288 #endif /* ! NO_SHARED_MEMORY */
276 } 289 }
277 290
278 /* There's a problem with the automatic refreshing of the display. 291 /* There's a problem with the automatic refreshing of the display.
279 Even though the XVideo code uses the GFX_Display to update the 292 Even though the XVideo code uses the GFX_Display to update the
281 from a different thread will cause "blackouts" of the window. 294 from a different thread will cause "blackouts" of the window.
282 This is a sort of a hacked workaround for the problem. 295 This is a sort of a hacked workaround for the problem.
283 */ 296 */
284 static int enable_autorefresh = 1; 297 static int enable_autorefresh = 1;
285 298
286 void X11_DisableAutoRefresh(_THIS) 299 void
287 { 300 X11_DisableAutoRefresh (_THIS)
288 --enable_autorefresh; 301 {
289 } 302 --enable_autorefresh;
290 303 }
291 void X11_EnableAutoRefresh(_THIS) 304
292 { 305 void
293 ++enable_autorefresh; 306 X11_EnableAutoRefresh (_THIS)
294 } 307 {
295 308 ++enable_autorefresh;
296 void X11_RefreshDisplay(_THIS) 309 }
297 { 310
298 /* Don't refresh a display that doesn't have an image (like GL) 311 void
299 Instead, post an expose event so the application can refresh. 312 X11_RefreshDisplay (_THIS)
300 */ 313 {
301 if ( ! SDL_Ximage || (enable_autorefresh <= 0) ) { 314 /* Don't refresh a display that doesn't have an image (like GL)
302 SDL_PrivateExpose(); 315 Instead, post an expose event so the application can refresh.
303 return; 316 */
304 } 317 if (!SDL_Ximage || (enable_autorefresh <= 0)) {
305 #ifndef NO_SHARED_MEMORY 318 SDL_PrivateExpose ();
306 if ( this->UpdateRects == X11_MITSHMUpdate ) { 319 return;
307 XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, 320 }
308 0, 0, 0, 0, this->screen->w, this->screen->h, 321 #ifndef NO_SHARED_MEMORY
309 False); 322 if (this->UpdateRects == X11_MITSHMUpdate) {
310 } else 323 XShmPutImage (SDL_Display, SDL_Window, SDL_GC, SDL_Ximage,
324 0, 0, SDL_CurrentWindow.offset_x,
325 SDL_CurrentWindow.offset_y,
326 SDL_CurrentDisplay.current_mode.w,
327 SDL_CurrentDisplay.current_mode.h, False);
328 } else
311 #endif /* ! NO_SHARED_MEMORY */ 329 #endif /* ! NO_SHARED_MEMORY */
312 { 330 {
313 XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, 331 XPutImage (SDL_Display, SDL_Window, SDL_GC, SDL_Ximage,
314 0, 0, 0, 0, this->screen->w, this->screen->h); 332 0, 0, SDL_CurrentWindow.offset_x,
315 } 333 SDL_CurrentWindow.offset_y,
316 XSync(SDL_Display, False); 334 SDL_CurrentDisplay.current_mode.w,
317 } 335 SDL_CurrentDisplay.current_mode.h);
318 336 }
337 XSync (SDL_Display, False);
338 }
339
340 /* vi: set ts=4 sw=4 expandtab: */