comparison src/video/x11/SDL_x11yuv.c @ 4106:12bb6311fd5d SDL-1.2

Hans de Goede fixed bug #495 When running boswars: http://www.boswars.org/ on a machine with intel integrathed graphics it crashes when it tries to play the initial theora splashscreen video: X Error of failed request: BadAlloc (insufficient resources for operation) Major opcode of failed request: 140 (XVideo) Minor opcode of failed request: 19 () Serial number of failed request: 25 Current serial number in output stream: 26 boswars: xcb_xlib.c:41: xcb_xlib_lock: Assertion `!c->xlib.lock' failed. Aborted I recognized this problem from a few years back, when I encountered it while working on the Xv blitter for xmame. The problem is that for some reason creation the Xvport and XvImage succeeds, and failure (lack of resources / hw capability?) is only indicated during the first XvPut[Shm]Image. I've written a patch for SDL using the work around for this I developed for xmame (and which is still used successfully in xmame after many years of usage). I'll admit it isn't very pretty, but after investigating several possibilities this was the best option, any other fixes would need changes to the SDL api and abi.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 29 Dec 2007 02:23:48 +0000
parents 51038e80ae59
children a1b03ba2fcd0
comparison
equal deleted inserted replaced
4105:84882a89ca50 4106:12bb6311fd5d
41 #include "SDL_x11image_c.h" 41 #include "SDL_x11image_c.h"
42 #endif 42 #endif
43 43
44 /* Workaround when pitch != width */ 44 /* Workaround when pitch != width */
45 #define PITCH_WORKAROUND 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
46 50
47 /* Fix for the NVidia GeForce 2 - use the last available adaptor */ 51 /* Fix for the NVidia GeForce 2 - use the last available adaptor */
48 /*#define USE_LAST_ADAPTOR*/ /* Apparently the NVidia drivers are fixed */ 52 /*#define USE_LAST_ADAPTOR*/ /* Apparently the NVidia drivers are fixed */
49 53
50 /* The functions used to manipulate software video overlays */ 54 /* The functions used to manipulate software video overlays */
88 return(0); 92 return(0);
89 } else 93 } else
90 return(X_handler(d,e)); 94 return(X_handler(d,e));
91 } 95 }
92 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
93 SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) 160 SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display)
94 { 161 {
95 SDL_Overlay *overlay; 162 SDL_Overlay *overlay;
96 struct private_yuvhwdata *hwdata; 163 struct private_yuvhwdata *hwdata;
97 int xv_port; 164 int xv_port;
99 unsigned int adaptors; 166 unsigned int adaptors;
100 SDL_NAME(XvAdaptorInfo) *ainfo; 167 SDL_NAME(XvAdaptorInfo) *ainfo;
101 int bpp; 168 int bpp;
102 #ifndef NO_SHARED_MEMORY 169 #ifndef NO_SHARED_MEMORY
103 XShmSegmentInfo *yuvshm; 170 XShmSegmentInfo *yuvshm;
171 #endif
172 #ifdef INTEL_XV_BADALLOC_WORKAROUND
173 int intel_adapter = False;
104 #endif 174 #endif
105 175
106 /* Look for the XVideo extension with a valid port for this format */ 176 /* Look for the XVideo extension with a valid port for this format */
107 xv_port = -1; 177 xv_port = -1;
108 if ( (Success == SDL_NAME(XvQueryExtension)(GFX_Display, &j, &j, &j, &j, &j)) && 178 if ( (Success == SDL_NAME(XvQueryExtension)(GFX_Display, &j, &j, &j, &j, &j)) &&
127 } 197 }
128 if ( ! visual_ok ) { 198 if ( ! visual_ok ) {
129 continue; 199 continue;
130 } 200 }
131 } 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
132 if ( (ainfo[i].type & XvInputMask) && 208 if ( (ainfo[i].type & XvInputMask) &&
133 (ainfo[i].type & XvImageMask) ) { 209 (ainfo[i].type & XvImageMask) ) {
134 int num_formats; 210 int num_formats;
135 SDL_NAME(XvImageFormatValues) *formats; 211 SDL_NAME(XvImageFormatValues) *formats;
136 formats = SDL_NAME(XvListImageFormats)(GFX_Display, 212 formats = SDL_NAME(XvListImageFormats)(GFX_Display,
338 being output to them. See SDL_x11image.c for more details. 414 being output to them. See SDL_x11image.c for more details.
339 */ 415 */
340 X11_DisableAutoRefresh(this); 416 X11_DisableAutoRefresh(this);
341 #endif 417 #endif
342 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
343 /* We're all done.. */ 468 /* We're all done.. */
344 return(overlay); 469 return(overlay);
345 } 470 }
346 471
347 int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay) 472 int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay)