diff options
author | Franklin Wei <git@fwei.tk> | 2017-01-21 15:18:31 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2017-12-23 21:01:26 -0500 |
commit | a855d6202536ff28e5aae4f22a0f31d8f5b325d0 (patch) | |
tree | 8c75f224dd64ed360505afa8843d016b0d75000b /apps/plugins/sdl/src/video/x11/SDL_x11image.c | |
parent | 01c6dcf6c7b9bb1ad2fa0450f99bacc5f3d3e04b (diff) | |
download | rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.tar.gz rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.zip |
Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL
for Rockbox.
Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
Diffstat (limited to 'apps/plugins/sdl/src/video/x11/SDL_x11image.c')
-rw-r--r-- | apps/plugins/sdl/src/video/x11/SDL_x11image.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/video/x11/SDL_x11image.c b/apps/plugins/sdl/src/video/x11/SDL_x11image.c new file mode 100644 index 0000000000..464bc37ba7 --- /dev/null +++ b/apps/plugins/sdl/src/video/x11/SDL_x11image.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 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 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #include <stdio.h> | ||
25 | #include <unistd.h> | ||
26 | |||
27 | #include "SDL_endian.h" | ||
28 | #include "../../events/SDL_events_c.h" | ||
29 | #include "SDL_x11image_c.h" | ||
30 | |||
31 | #ifndef NO_SHARED_MEMORY | ||
32 | |||
33 | /* Shared memory error handler routine */ | ||
34 | static int shm_error; | ||
35 | static int (*X_handler)(Display *, XErrorEvent *) = NULL; | ||
36 | static int shm_errhandler(Display *d, XErrorEvent *e) | ||
37 | { | ||
38 | if ( e->error_code == BadAccess ) { | ||
39 | shm_error = True; | ||
40 | return(0); | ||
41 | } else | ||
42 | return(X_handler(d,e)); | ||
43 | } | ||
44 | |||
45 | static void try_mitshm(_THIS, SDL_Surface *screen) | ||
46 | { | ||
47 | /* Dynamic X11 may not have SHM entry points on this box. */ | ||
48 | if ((use_mitshm) && (!SDL_X11_HAVE_SHM)) | ||
49 | use_mitshm = 0; | ||
50 | |||
51 | if(!use_mitshm) | ||
52 | return; | ||
53 | shminfo.shmid = shmget(IPC_PRIVATE, screen->h*screen->pitch, | ||
54 | IPC_CREAT | 0777); | ||
55 | if ( shminfo.shmid >= 0 ) { | ||
56 | shminfo.shmaddr = (char *)shmat(shminfo.shmid, 0, 0); | ||
57 | shminfo.readOnly = False; | ||
58 | if ( shminfo.shmaddr != (char *)-1 ) { | ||
59 | shm_error = False; | ||
60 | X_handler = XSetErrorHandler(shm_errhandler); | ||
61 | XShmAttach(SDL_Display, &shminfo); | ||
62 | XSync(SDL_Display, True); | ||
63 | XSetErrorHandler(X_handler); | ||
64 | if ( shm_error ) | ||
65 | shmdt(shminfo.shmaddr); | ||
66 | } else { | ||
67 | shm_error = True; | ||
68 | } | ||
69 | shmctl(shminfo.shmid, IPC_RMID, NULL); | ||
70 | } else { | ||
71 | shm_error = True; | ||
72 | } | ||
73 | if ( shm_error ) | ||
74 | use_mitshm = 0; | ||
75 | if ( use_mitshm ) | ||
76 | screen->pixels = shminfo.shmaddr; | ||
77 | } | ||
78 | #endif /* ! NO_SHARED_MEMORY */ | ||
79 | |||
80 | /* Various screen update functions available */ | ||
81 | static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); | ||
82 | static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects); | ||
83 | |||
84 | int X11_SetupImage(_THIS, SDL_Surface *screen) | ||
85 | { | ||
86 | #ifndef NO_SHARED_MEMORY | ||
87 | try_mitshm(this, screen); | ||
88 | if(use_mitshm) { | ||
89 | SDL_Ximage = XShmCreateImage(SDL_Display, SDL_Visual, | ||
90 | this->hidden->depth, ZPixmap, | ||
91 | shminfo.shmaddr, &shminfo, | ||
92 | screen->w, screen->h); | ||
93 | if(!SDL_Ximage) { | ||
94 | XShmDetach(SDL_Display, &shminfo); | ||
95 | XSync(SDL_Display, False); | ||
96 | shmdt(shminfo.shmaddr); | ||
97 | screen->pixels = NULL; | ||
98 | goto error; | ||
99 | } | ||
100 | this->UpdateRects = X11_MITSHMUpdate; | ||
101 | } | ||
102 | if(!use_mitshm) | ||
103 | #endif /* not NO_SHARED_MEMORY */ | ||
104 | { | ||
105 | screen->pixels = SDL_malloc(screen->h*screen->pitch); | ||
106 | if ( screen->pixels == NULL ) { | ||
107 | SDL_OutOfMemory(); | ||
108 | return -1; | ||
109 | } | ||
110 | SDL_Ximage = XCreateImage(SDL_Display, SDL_Visual, | ||
111 | this->hidden->depth, ZPixmap, 0, | ||
112 | (char *)screen->pixels, | ||
113 | screen->w, screen->h, | ||
114 | 32, 0); | ||
115 | if ( SDL_Ximage == NULL ) | ||
116 | goto error; | ||
117 | /* XPutImage will convert byte sex automatically */ | ||
118 | SDL_Ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) | ||
119 | ? MSBFirst : LSBFirst; | ||
120 | this->UpdateRects = X11_NormalUpdate; | ||
121 | } | ||
122 | screen->pitch = SDL_Ximage->bytes_per_line; | ||
123 | return(0); | ||
124 | |||
125 | error: | ||
126 | SDL_SetError("Couldn't create XImage"); | ||
127 | return 1; | ||
128 | } | ||
129 | |||
130 | void X11_DestroyImage(_THIS, SDL_Surface *screen) | ||
131 | { | ||
132 | if ( SDL_Ximage ) { | ||
133 | XDestroyImage(SDL_Ximage); | ||
134 | #ifndef NO_SHARED_MEMORY | ||
135 | if ( use_mitshm ) { | ||
136 | XShmDetach(SDL_Display, &shminfo); | ||
137 | XSync(SDL_Display, False); | ||
138 | shmdt(shminfo.shmaddr); | ||
139 | } | ||
140 | #endif /* ! NO_SHARED_MEMORY */ | ||
141 | SDL_Ximage = NULL; | ||
142 | } | ||
143 | if ( screen ) { | ||
144 | screen->pixels = NULL; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | /* Determine the number of CPUs in the system */ | ||
149 | static int num_CPU(void) | ||
150 | { | ||
151 | static int num_cpus = 0; | ||
152 | |||
153 | if(!num_cpus) { | ||
154 | #if defined(__LINUX__) | ||
155 | char line[BUFSIZ]; | ||
156 | FILE *pstat = fopen("/proc/stat", "r"); | ||
157 | if ( pstat ) { | ||
158 | while ( fgets(line, sizeof(line), pstat) ) { | ||
159 | if (SDL_memcmp(line, "cpu", 3) == 0 && line[3] != ' ') { | ||
160 | ++num_cpus; | ||
161 | } | ||
162 | } | ||
163 | fclose(pstat); | ||
164 | } | ||
165 | #elif defined(__IRIX__) | ||
166 | num_cpus = sysconf(_SC_NPROC_ONLN); | ||
167 | #elif defined(_SC_NPROCESSORS_ONLN) | ||
168 | /* number of processors online (SVR4.0MP compliant machines) */ | ||
169 | num_cpus = sysconf(_SC_NPROCESSORS_ONLN); | ||
170 | #elif defined(_SC_NPROCESSORS_CONF) | ||
171 | /* number of processors configured (SVR4.0MP compliant machines) */ | ||
172 | num_cpus = sysconf(_SC_NPROCESSORS_CONF); | ||
173 | #endif | ||
174 | if ( num_cpus <= 0 ) { | ||
175 | num_cpus = 1; | ||
176 | } | ||
177 | } | ||
178 | return num_cpus; | ||
179 | } | ||
180 | |||
181 | int X11_ResizeImage(_THIS, SDL_Surface *screen, Uint32 flags) | ||
182 | { | ||
183 | int retval; | ||
184 | |||
185 | X11_DestroyImage(this, screen); | ||
186 | if ( flags & SDL_OPENGL ) { /* No image when using GL */ | ||
187 | retval = 0; | ||
188 | } else { | ||
189 | retval = X11_SetupImage(this, screen); | ||
190 | /* We support asynchronous blitting on the display */ | ||
191 | if ( flags & SDL_ASYNCBLIT ) { | ||
192 | /* This is actually slower on single-CPU systems, | ||
193 | probably because of CPU contention between the | ||
194 | X server and the application. | ||
195 | Note: Is this still true with XFree86 4.0? | ||
196 | */ | ||
197 | if ( num_CPU() > 1 ) { | ||
198 | screen->flags |= SDL_ASYNCBLIT; | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | return(retval); | ||
203 | } | ||
204 | |||
205 | /* We don't actually allow hardware surfaces other than the main one */ | ||
206 | int X11_AllocHWSurface(_THIS, SDL_Surface *surface) | ||
207 | { | ||
208 | return(-1); | ||
209 | } | ||
210 | void X11_FreeHWSurface(_THIS, SDL_Surface *surface) | ||
211 | { | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | int X11_LockHWSurface(_THIS, SDL_Surface *surface) | ||
216 | { | ||
217 | if ( (surface == SDL_VideoSurface) && blit_queued ) { | ||
218 | XSync(GFX_Display, False); | ||
219 | blit_queued = 0; | ||
220 | } | ||
221 | return(0); | ||
222 | } | ||
223 | void X11_UnlockHWSurface(_THIS, SDL_Surface *surface) | ||
224 | { | ||
225 | return; | ||
226 | } | ||
227 | |||
228 | int X11_FlipHWSurface(_THIS, SDL_Surface *surface) | ||
229 | { | ||
230 | return(0); | ||
231 | } | ||
232 | |||
233 | static void X11_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) | ||
234 | { | ||
235 | int i; | ||
236 | |||
237 | for (i = 0; i < numrects; ++i) { | ||
238 | if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */ | ||
239 | continue; | ||
240 | } | ||
241 | XPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, | ||
242 | rects[i].x, rects[i].y, | ||
243 | rects[i].x, rects[i].y, rects[i].w, rects[i].h); | ||
244 | } | ||
245 | if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { | ||
246 | XFlush(GFX_Display); | ||
247 | blit_queued = 1; | ||
248 | } else { | ||
249 | XSync(GFX_Display, False); | ||
250 | } | ||
251 | } | ||
252 | |||
253 | static void X11_MITSHMUpdate(_THIS, int numrects, SDL_Rect *rects) | ||
254 | { | ||
255 | #ifndef NO_SHARED_MEMORY | ||
256 | int i; | ||
257 | |||
258 | for ( i=0; i<numrects; ++i ) { | ||
259 | if ( rects[i].w == 0 || rects[i].h == 0 ) { /* Clipped? */ | ||
260 | continue; | ||
261 | } | ||
262 | XShmPutImage(GFX_Display, SDL_Window, SDL_GC, SDL_Ximage, | ||
263 | rects[i].x, rects[i].y, | ||
264 | rects[i].x, rects[i].y, rects[i].w, rects[i].h, | ||
265 | False); | ||
266 | } | ||
267 | if ( SDL_VideoSurface->flags & SDL_ASYNCBLIT ) { | ||
268 | XFlush(GFX_Display); | ||
269 | blit_queued = 1; | ||
270 | } else { | ||
271 | XSync(GFX_Display, False); | ||
272 | } | ||
273 | #endif /* ! NO_SHARED_MEMORY */ | ||
274 | } | ||
275 | |||
276 | /* There's a problem with the automatic refreshing of the display. | ||
277 | Even though the XVideo code uses the GFX_Display to update the | ||
278 | video memory, it appears that updating the window asynchronously | ||
279 | from a different thread will cause "blackouts" of the window. | ||
280 | This is a sort of a hacked workaround for the problem. | ||
281 | */ | ||
282 | static int enable_autorefresh = 1; | ||
283 | |||
284 | void X11_DisableAutoRefresh(_THIS) | ||
285 | { | ||
286 | --enable_autorefresh; | ||
287 | } | ||
288 | |||
289 | void X11_EnableAutoRefresh(_THIS) | ||
290 | { | ||
291 | ++enable_autorefresh; | ||
292 | } | ||
293 | |||
294 | void X11_RefreshDisplay(_THIS) | ||
295 | { | ||
296 | /* Don't refresh a display that doesn't have an image (like GL) | ||
297 | Instead, post an expose event so the application can refresh. | ||
298 | */ | ||
299 | if ( ! SDL_Ximage || (enable_autorefresh <= 0) ) { | ||
300 | SDL_PrivateExpose(); | ||
301 | return; | ||
302 | } | ||
303 | #ifndef NO_SHARED_MEMORY | ||
304 | if ( this->UpdateRects == X11_MITSHMUpdate ) { | ||
305 | XShmPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, | ||
306 | 0, 0, 0, 0, this->screen->w, this->screen->h, | ||
307 | False); | ||
308 | } else | ||
309 | #endif /* ! NO_SHARED_MEMORY */ | ||
310 | { | ||
311 | XPutImage(SDL_Display, SDL_Window, SDL_GC, SDL_Ximage, | ||
312 | 0, 0, 0, 0, this->screen->w, this->screen->h); | ||
313 | } | ||
314 | XSync(SDL_Display, False); | ||
315 | } | ||
316 | |||