diff options
Diffstat (limited to 'apps/plugins/sdl/src/video/x11/SDL_x11yuv.c')
-rw-r--r-- | apps/plugins/sdl/src/video/x11/SDL_x11yuv.c | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/video/x11/SDL_x11yuv.c b/apps/plugins/sdl/src/video/x11/SDL_x11yuv.c new file mode 100644 index 0000000000..62698dfd9b --- /dev/null +++ b/apps/plugins/sdl/src/video/x11/SDL_x11yuv.c | |||
@@ -0,0 +1,538 @@ | |||
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 | /* This is the XFree86 Xv extension implementation of YUV video overlays */ | ||
25 | |||
26 | #if SDL_VIDEO_DRIVER_X11_XV | ||
27 | |||
28 | #include <X11/Xlib.h> | ||
29 | #ifndef NO_SHARED_MEMORY | ||
30 | #include <sys/ipc.h> | ||
31 | #include <sys/shm.h> | ||
32 | #include <X11/extensions/XShm.h> | ||
33 | #endif | ||
34 | #include "../Xext/extensions/Xvlib.h" | ||
35 | |||
36 | #include "SDL_x11yuv_c.h" | ||
37 | #include "../SDL_yuvfuncs.h" | ||
38 | |||
39 | #define XFREE86_REFRESH_HACK | ||
40 | #ifdef XFREE86_REFRESH_HACK | ||
41 | #include "SDL_x11image_c.h" | ||
42 | #endif | ||
43 | |||
44 | /* Workaround when pitch != width */ | ||
45 | #define PITCH_WORKAROUND | ||
46 | |||
47 | /* Workaround intel i810 video overlay waiting with failing until the | ||
48 | first Xv[Shm]PutImage call <sigh> */ | ||
49 | #define INTEL_XV_BADALLOC_WORKAROUND | ||
50 | |||
51 | /* Fix for the NVidia GeForce 2 - use the last available adaptor */ | ||
52 | /*#define USE_LAST_ADAPTOR*/ /* Apparently the NVidia drivers are fixed */ | ||
53 | |||
54 | /* The functions used to manipulate software video overlays */ | ||
55 | static struct private_yuvhwfuncs x11_yuvfuncs = { | ||
56 | X11_LockYUVOverlay, | ||
57 | X11_UnlockYUVOverlay, | ||
58 | X11_DisplayYUVOverlay, | ||
59 | X11_FreeYUVOverlay | ||
60 | }; | ||
61 | |||
62 | struct private_yuvhwdata { | ||
63 | int port; | ||
64 | #ifndef NO_SHARED_MEMORY | ||
65 | int yuv_use_mitshm; | ||
66 | XShmSegmentInfo yuvshm; | ||
67 | #endif | ||
68 | SDL_NAME(XvImage) *image; | ||
69 | }; | ||
70 | |||
71 | |||
72 | static int (*X_handler)(Display *, XErrorEvent *) = NULL; | ||
73 | |||
74 | #ifndef NO_SHARED_MEMORY | ||
75 | /* Shared memory error handler routine */ | ||
76 | static int shm_error; | ||
77 | static int shm_errhandler(Display *d, XErrorEvent *e) | ||
78 | { | ||
79 | if ( e->error_code == BadAccess ) { | ||
80 | shm_error = True; | ||
81 | return(0); | ||
82 | } else | ||
83 | return(X_handler(d,e)); | ||
84 | } | ||
85 | #endif /* !NO_SHARED_MEMORY */ | ||
86 | |||
87 | static int xv_error; | ||
88 | static int xv_errhandler(Display *d, XErrorEvent *e) | ||
89 | { | ||
90 | if ( e->error_code == BadMatch ) { | ||
91 | xv_error = True; | ||
92 | return(0); | ||
93 | } else | ||
94 | return(X_handler(d,e)); | ||
95 | } | ||
96 | |||
97 | #ifdef INTEL_XV_BADALLOC_WORKAROUND | ||
98 | static int intel_errhandler(Display *d, XErrorEvent *e) | ||
99 | { | ||
100 | if ( e->error_code == BadAlloc ) { | ||
101 | xv_error = True; | ||
102 | return(0); | ||
103 | } else | ||
104 | return(X_handler(d,e)); | ||
105 | } | ||
106 | |||
107 | static void X11_ClearYUVOverlay(SDL_Overlay *overlay) | ||
108 | { | ||
109 | int x,y; | ||
110 | |||
111 | switch (overlay->format) | ||
112 | { | ||
113 | case SDL_YV12_OVERLAY: | ||
114 | case SDL_IYUV_OVERLAY: | ||
115 | for (y = 0; y < overlay->h; y++) | ||
116 | memset(overlay->pixels[0] + y * overlay->pitches[0], | ||
117 | 0, overlay->w); | ||
118 | |||
119 | for (y = 0; y < (overlay->h / 2); y++) | ||
120 | { | ||
121 | memset(overlay->pixels[1] + y * overlay->pitches[1], | ||
122 | -128, overlay->w / 2); | ||
123 | memset(overlay->pixels[2] + y * overlay->pitches[2], | ||
124 | -128, overlay->w / 2); | ||
125 | } | ||
126 | break; | ||
127 | case SDL_YUY2_OVERLAY: | ||
128 | case SDL_YVYU_OVERLAY: | ||
129 | for (y = 0; y < overlay->h; y++) | ||
130 | { | ||
131 | for (x = 0; x < overlay->w; x += 2) | ||
132 | { | ||
133 | Uint8 *pixel_pair = overlay->pixels[0] + | ||
134 | y * overlay->pitches[0] + x * 2; | ||
135 | pixel_pair[0] = 0; | ||
136 | pixel_pair[1] = -128; | ||
137 | pixel_pair[2] = 0; | ||
138 | pixel_pair[3] = -128; | ||
139 | } | ||
140 | } | ||
141 | break; | ||
142 | case SDL_UYVY_OVERLAY: | ||
143 | for (y = 0; y < overlay->h; y++) | ||
144 | { | ||
145 | for (x = 0; x < overlay->w; x += 2) | ||
146 | { | ||
147 | Uint8 *pixel_pair = overlay->pixels[0] + | ||
148 | y * overlay->pitches[0] + x * 2; | ||
149 | pixel_pair[0] = -128; | ||
150 | pixel_pair[1] = 0; | ||
151 | pixel_pair[2] = -128; | ||
152 | pixel_pair[3] = 0; | ||
153 | } | ||
154 | } | ||
155 | break; | ||
156 | } | ||
157 | } | ||
158 | #endif | ||
159 | |||
160 | SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) | ||
161 | { | ||
162 | SDL_Overlay *overlay; | ||
163 | struct private_yuvhwdata *hwdata; | ||
164 | int xv_port; | ||
165 | unsigned int i, j, k; | ||
166 | unsigned int adaptors; | ||
167 | SDL_NAME(XvAdaptorInfo) *ainfo; | ||
168 | int bpp; | ||
169 | #ifndef NO_SHARED_MEMORY | ||
170 | XShmSegmentInfo *yuvshm; | ||
171 | #endif | ||
172 | #ifdef INTEL_XV_BADALLOC_WORKAROUND | ||
173 | int intel_adapter = False; | ||
174 | #endif | ||
175 | |||
176 | /* Look for the XVideo extension with a valid port for this format */ | ||
177 | xv_port = -1; | ||
178 | if ( (Success == SDL_NAME(XvQueryExtension)(GFX_Display, &j, &j, &j, &j, &j)) && | ||
179 | (Success == SDL_NAME(XvQueryAdaptors)(GFX_Display, | ||
180 | RootWindow(GFX_Display, SDL_Screen), | ||
181 | &adaptors, &ainfo)) ) { | ||
182 | #ifdef USE_LAST_ADAPTOR | ||
183 | for ( i=0; i < adaptors; ++i ) | ||
184 | #else | ||
185 | for ( i=0; (i < adaptors) && (xv_port == -1); ++i ) | ||
186 | #endif /* USE_LAST_ADAPTOR */ | ||
187 | { | ||
188 | /* Check to see if the visual can be used */ | ||
189 | if ( BUGGY_XFREE86(<=, 4001) ) { | ||
190 | int visual_ok = 0; | ||
191 | for ( j=0; j<ainfo[i].num_formats; ++j ) { | ||
192 | if ( ainfo[i].formats[j].visual_id == | ||
193 | SDL_Visual->visualid ) { | ||
194 | visual_ok = 1; | ||
195 | break; | ||
196 | } | ||
197 | } | ||
198 | if ( ! visual_ok ) { | ||
199 | continue; | ||
200 | } | ||
201 | } | ||
202 | #ifdef INTEL_XV_BADALLOC_WORKAROUND | ||
203 | if ( !strcmp(ainfo[i].name, "Intel(R) Video Overla")) | ||
204 | intel_adapter = True; | ||
205 | else | ||
206 | intel_adapter = False; | ||
207 | #endif | ||
208 | if ( (ainfo[i].type & XvInputMask) && | ||
209 | (ainfo[i].type & XvImageMask) ) { | ||
210 | int num_formats; | ||
211 | SDL_NAME(XvImageFormatValues) *formats; | ||
212 | formats = SDL_NAME(XvListImageFormats)(GFX_Display, | ||
213 | ainfo[i].base_id, &num_formats); | ||
214 | #ifdef USE_LAST_ADAPTOR | ||
215 | for ( j=0; j < num_formats; ++j ) | ||
216 | #else | ||
217 | for ( j=0; (j < num_formats) && (xv_port == -1); ++j ) | ||
218 | #endif /* USE_LAST_ADAPTOR */ | ||
219 | { | ||
220 | if ( (Uint32)formats[j].id == format ) { | ||
221 | for ( k=0; k < ainfo[i].num_ports; ++k ) { | ||
222 | if ( Success == SDL_NAME(XvGrabPort)(GFX_Display, ainfo[i].base_id+k, CurrentTime) ) { | ||
223 | xv_port = ainfo[i].base_id+k; | ||
224 | break; | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | if ( formats ) { | ||
230 | XFree(formats); | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | SDL_NAME(XvFreeAdaptorInfo)(ainfo); | ||
235 | } | ||
236 | |||
237 | /* Precalculate the bpp for the pitch workaround below */ | ||
238 | switch (format) { | ||
239 | /* Add any other cases we need to support... */ | ||
240 | case SDL_YUY2_OVERLAY: | ||
241 | case SDL_UYVY_OVERLAY: | ||
242 | case SDL_YVYU_OVERLAY: | ||
243 | bpp = 2; | ||
244 | break; | ||
245 | default: | ||
246 | bpp = 1; | ||
247 | break; | ||
248 | } | ||
249 | |||
250 | #if 0 | ||
251 | /* | ||
252 | * !!! FIXME: | ||
253 | * "Here are some diffs for X11 and yuv. Note that the last part 2nd | ||
254 | * diff should probably be a new call to XvQueryAdaptorFree with ainfo | ||
255 | * and the number of adaptors, instead of the loop through like I did." | ||
256 | * | ||
257 | * ACHTUNG: This is broken! It looks like XvFreeAdaptorInfo does this | ||
258 | * for you, so we end up with a double-free. I need to look at this | ||
259 | * more closely... --ryan. | ||
260 | */ | ||
261 | for ( i=0; i < adaptors; ++i ) { | ||
262 | if (ainfo[i].name != NULL) Xfree(ainfo[i].name); | ||
263 | if (ainfo[i].formats != NULL) Xfree(ainfo[i].formats); | ||
264 | } | ||
265 | Xfree(ainfo); | ||
266 | #endif | ||
267 | |||
268 | if ( xv_port == -1 ) { | ||
269 | SDL_SetError("No available video ports for requested format"); | ||
270 | return(NULL); | ||
271 | } | ||
272 | |||
273 | /* Enable auto-painting of the overlay colorkey */ | ||
274 | { | ||
275 | static const char *attr[] = { "XV_AUTOPAINT_COLORKEY", "XV_AUTOPAINT_COLOURKEY" }; | ||
276 | unsigned int i; | ||
277 | |||
278 | SDL_NAME(XvSelectPortNotify)(GFX_Display, xv_port, True); | ||
279 | X_handler = XSetErrorHandler(xv_errhandler); | ||
280 | for ( i=0; i < sizeof(attr)/(sizeof attr[0]); ++i ) { | ||
281 | Atom a; | ||
282 | |||
283 | xv_error = False; | ||
284 | a = XInternAtom(GFX_Display, attr[i], True); | ||
285 | if ( a != None ) { | ||
286 | SDL_NAME(XvSetPortAttribute)(GFX_Display, xv_port, a, 1); | ||
287 | XSync(GFX_Display, True); | ||
288 | if ( ! xv_error ) { | ||
289 | break; | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | XSetErrorHandler(X_handler); | ||
294 | SDL_NAME(XvSelectPortNotify)(GFX_Display, xv_port, False); | ||
295 | } | ||
296 | |||
297 | /* Create the overlay structure */ | ||
298 | overlay = (SDL_Overlay *)SDL_malloc(sizeof *overlay); | ||
299 | if ( overlay == NULL ) { | ||
300 | SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); | ||
301 | SDL_OutOfMemory(); | ||
302 | return(NULL); | ||
303 | } | ||
304 | SDL_memset(overlay, 0, (sizeof *overlay)); | ||
305 | |||
306 | /* Fill in the basic members */ | ||
307 | overlay->format = format; | ||
308 | overlay->w = width; | ||
309 | overlay->h = height; | ||
310 | |||
311 | /* Set up the YUV surface function structure */ | ||
312 | overlay->hwfuncs = &x11_yuvfuncs; | ||
313 | overlay->hw_overlay = 1; | ||
314 | |||
315 | /* Create the pixel data and lookup tables */ | ||
316 | hwdata = (struct private_yuvhwdata *)SDL_malloc(sizeof *hwdata); | ||
317 | overlay->hwdata = hwdata; | ||
318 | if ( hwdata == NULL ) { | ||
319 | SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); | ||
320 | SDL_OutOfMemory(); | ||
321 | SDL_FreeYUVOverlay(overlay); | ||
322 | return(NULL); | ||
323 | } | ||
324 | hwdata->port = xv_port; | ||
325 | #ifndef NO_SHARED_MEMORY | ||
326 | yuvshm = &hwdata->yuvshm; | ||
327 | SDL_memset(yuvshm, 0, sizeof(*yuvshm)); | ||
328 | hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, | ||
329 | 0, width, height, yuvshm); | ||
330 | #ifdef PITCH_WORKAROUND | ||
331 | if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) { | ||
332 | /* Ajust overlay width according to pitch */ | ||
333 | width = hwdata->image->pitches[0] / bpp; | ||
334 | XFree(hwdata->image); | ||
335 | hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, | ||
336 | 0, width, height, yuvshm); | ||
337 | } | ||
338 | #endif /* PITCH_WORKAROUND */ | ||
339 | hwdata->yuv_use_mitshm = (hwdata->image != NULL); | ||
340 | if ( hwdata->yuv_use_mitshm ) { | ||
341 | yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size, | ||
342 | IPC_CREAT | 0777); | ||
343 | if ( yuvshm->shmid >= 0 ) { | ||
344 | yuvshm->shmaddr = (char *)shmat(yuvshm->shmid, 0, 0); | ||
345 | yuvshm->readOnly = False; | ||
346 | if ( yuvshm->shmaddr != (char *)-1 ) { | ||
347 | shm_error = False; | ||
348 | X_handler = XSetErrorHandler(shm_errhandler); | ||
349 | XShmAttach(GFX_Display, yuvshm); | ||
350 | XSync(GFX_Display, True); | ||
351 | XSetErrorHandler(X_handler); | ||
352 | if ( shm_error ) | ||
353 | shmdt(yuvshm->shmaddr); | ||
354 | } else { | ||
355 | shm_error = True; | ||
356 | } | ||
357 | shmctl(yuvshm->shmid, IPC_RMID, NULL); | ||
358 | } else { | ||
359 | shm_error = True; | ||
360 | } | ||
361 | if ( shm_error ) { | ||
362 | XFree(hwdata->image); | ||
363 | hwdata->yuv_use_mitshm = 0; | ||
364 | } else { | ||
365 | hwdata->image->data = yuvshm->shmaddr; | ||
366 | } | ||
367 | } | ||
368 | if ( !hwdata->yuv_use_mitshm ) | ||
369 | #endif /* NO_SHARED_MEMORY */ | ||
370 | { | ||
371 | hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format, | ||
372 | 0, width, height); | ||
373 | |||
374 | #ifdef PITCH_WORKAROUND | ||
375 | if ( hwdata->image != NULL && hwdata->image->pitches[0] != (width*bpp) ) { | ||
376 | /* Ajust overlay width according to pitch */ | ||
377 | XFree(hwdata->image); | ||
378 | width = hwdata->image->pitches[0] / bpp; | ||
379 | hwdata->image = SDL_NAME(XvCreateImage)(GFX_Display, xv_port, format, | ||
380 | 0, width, height); | ||
381 | } | ||
382 | #endif /* PITCH_WORKAROUND */ | ||
383 | if ( hwdata->image == NULL ) { | ||
384 | SDL_SetError("Couldn't create XVideo image"); | ||
385 | SDL_FreeYUVOverlay(overlay); | ||
386 | return(NULL); | ||
387 | } | ||
388 | hwdata->image->data = SDL_malloc(hwdata->image->data_size); | ||
389 | if ( hwdata->image->data == NULL ) { | ||
390 | SDL_OutOfMemory(); | ||
391 | SDL_FreeYUVOverlay(overlay); | ||
392 | return(NULL); | ||
393 | } | ||
394 | } | ||
395 | |||
396 | /* Find the pitch and offset values for the overlay */ | ||
397 | overlay->planes = hwdata->image->num_planes; | ||
398 | overlay->pitches = (Uint16 *)SDL_malloc(overlay->planes * sizeof(Uint16)); | ||
399 | overlay->pixels = (Uint8 **)SDL_malloc(overlay->planes * sizeof(Uint8 *)); | ||
400 | if ( !overlay->pitches || !overlay->pixels ) { | ||
401 | SDL_OutOfMemory(); | ||
402 | SDL_FreeYUVOverlay(overlay); | ||
403 | return(NULL); | ||
404 | } | ||
405 | for ( i=0; i<overlay->planes; ++i ) { | ||
406 | overlay->pitches[i] = hwdata->image->pitches[i]; | ||
407 | overlay->pixels[i] = (Uint8 *)hwdata->image->data + | ||
408 | hwdata->image->offsets[i]; | ||
409 | } | ||
410 | |||
411 | #ifdef XFREE86_REFRESH_HACK | ||
412 | /* Work around an XFree86 X server bug (?) | ||
413 | We can't perform normal updates in windows that have video | ||
414 | being output to them. See SDL_x11image.c for more details. | ||
415 | */ | ||
416 | X11_DisableAutoRefresh(this); | ||
417 | #endif | ||
418 | |||
419 | #ifdef INTEL_XV_BADALLOC_WORKAROUND | ||
420 | /* HACK, GRRR sometimes (i810) creating the overlay succeeds, but the | ||
421 | first call to XvShm[Put]Image to a mapped window fails with: | ||
422 | "BadAlloc (insufficient resources for operation)". This happens with | ||
423 | certain formats when the XvImage is too large to the i810's liking. | ||
424 | |||
425 | We work around this by doing a test XvShm[Put]Image with a black | ||
426 | Xv image, this may cause some flashing, so only do this check if we | ||
427 | are running on an intel Xv-adapter. */ | ||
428 | if (intel_adapter) | ||
429 | { | ||
430 | xv_error = False; | ||
431 | X_handler = XSetErrorHandler(intel_errhandler); | ||
432 | |||
433 | X11_ClearYUVOverlay(overlay); | ||
434 | |||
435 | /* We set the destination height and width to 1 pixel to avoid | ||
436 | putting a large black rectangle over the screen, thus | ||
437 | strongly reducing possible flashing. */ | ||
438 | #ifndef NO_SHARED_MEMORY | ||
439 | if ( hwdata->yuv_use_mitshm ) { | ||
440 | SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, | ||
441 | SDL_Window, SDL_GC, | ||
442 | hwdata->image, | ||
443 | 0, 0, overlay->w, overlay->h, | ||
444 | 0, 0, 1, 1, False); | ||
445 | } | ||
446 | else | ||
447 | #endif | ||
448 | { | ||
449 | SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, | ||
450 | SDL_Window, SDL_GC, | ||
451 | hwdata->image, | ||
452 | 0, 0, overlay->w, overlay->h, | ||
453 | 0, 0, 1, 1); | ||
454 | } | ||
455 | XSync(GFX_Display, False); | ||
456 | XSetErrorHandler(X_handler); | ||
457 | |||
458 | if (xv_error) | ||
459 | { | ||
460 | X11_FreeYUVOverlay(this, overlay); | ||
461 | return NULL; | ||
462 | } | ||
463 | /* Repair the (1 pixel worth of) damage we've just done */ | ||
464 | X11_RefreshDisplay(this); | ||
465 | } | ||
466 | #endif | ||
467 | |||
468 | /* We're all done.. */ | ||
469 | return(overlay); | ||
470 | } | ||
471 | |||
472 | int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay) | ||
473 | { | ||
474 | return(0); | ||
475 | } | ||
476 | |||
477 | void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) | ||
478 | { | ||
479 | return; | ||
480 | } | ||
481 | |||
482 | int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst) | ||
483 | { | ||
484 | struct private_yuvhwdata *hwdata; | ||
485 | |||
486 | hwdata = overlay->hwdata; | ||
487 | |||
488 | #ifndef NO_SHARED_MEMORY | ||
489 | if ( hwdata->yuv_use_mitshm ) { | ||
490 | SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, | ||
491 | hwdata->image, | ||
492 | src->x, src->y, src->w, src->h, | ||
493 | dst->x, dst->y, dst->w, dst->h, False); | ||
494 | } | ||
495 | else | ||
496 | #endif | ||
497 | { | ||
498 | SDL_NAME(XvPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, | ||
499 | hwdata->image, | ||
500 | src->x, src->y, src->w, src->h, | ||
501 | dst->x, dst->y, dst->w, dst->h); | ||
502 | } | ||
503 | XSync(GFX_Display, False); | ||
504 | return(0); | ||
505 | } | ||
506 | |||
507 | void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) | ||
508 | { | ||
509 | struct private_yuvhwdata *hwdata; | ||
510 | |||
511 | hwdata = overlay->hwdata; | ||
512 | if ( hwdata ) { | ||
513 | SDL_NAME(XvUngrabPort)(GFX_Display, hwdata->port, CurrentTime); | ||
514 | #ifndef NO_SHARED_MEMORY | ||
515 | if ( hwdata->yuv_use_mitshm ) { | ||
516 | XShmDetach(GFX_Display, &hwdata->yuvshm); | ||
517 | shmdt(hwdata->yuvshm.shmaddr); | ||
518 | } | ||
519 | #endif | ||
520 | if ( hwdata->image ) { | ||
521 | XFree(hwdata->image); | ||
522 | } | ||
523 | SDL_free(hwdata); | ||
524 | } | ||
525 | if ( overlay->pitches ) { | ||
526 | SDL_free(overlay->pitches); | ||
527 | overlay->pitches = NULL; | ||
528 | } | ||
529 | if ( overlay->pixels ) { | ||
530 | SDL_free(overlay->pixels); | ||
531 | overlay->pixels = NULL; | ||
532 | } | ||
533 | #ifdef XFREE86_REFRESH_HACK | ||
534 | X11_EnableAutoRefresh(this); | ||
535 | #endif | ||
536 | } | ||
537 | |||
538 | #endif /* SDL_VIDEO_DRIVER_X11_XV */ | ||