1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com SDL - Simple DirectMedia Layer 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com Copyright (C) 1997-2012 Sam Lantinga 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com This library is free software; you can redistribute it and/or 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com modify it under the terms of the GNU Lesser General Public 76806fe87e0b39e283291c1a1c7d1d864230aa2aatfarina@chromium.org License as published by the Free Software Foundation; either 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com version 2.1 of the License, or (at your option) any later version. 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com This library is distributed in the hope that it will be useful, 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com but WITHOUT ANY WARRANTY; without even the implied warranty of 125da3f220034f89f3234b16b98bd86e7246941ffecommit-bot@chromium.org MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 135da3f220034f89f3234b16b98bd86e7246941ffecommit-bot@chromium.org Lesser General Public License for more details. 140716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com You should have received a copy of the GNU Lesser General Public 168c3ff17e2cab6f7c798b9f8ff4515c4a3d3fd9d1bsalomon@google.com License along with this library; if not, write to the Free Software 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 180456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com 190456e0b7b85060e9b9597ce414c4c2b19aff4f58robertphillips@google.com Sam Lantinga 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com slouken@libsdl.org 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 220e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org#include "SDL_config.h" 230716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 240716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com/* This is the XFree86 Xv extension implementation of YUV video overlays */ 250716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 260716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#if SDL_VIDEO_DRIVER_X11_XV 27842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com 28842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com#include <X11/Xlib.h> 290716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#ifndef NO_SHARED_MEMORY 300e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org#include <sys/ipc.h> 310716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#include <sys/shm.h> 320716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#include <X11/extensions/XShm.h> 330716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#endif 340716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#include "../Xext/extensions/Xvlib.h" 350716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 360716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#include "SDL_x11yuv_c.h" 370716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#include "../SDL_yuvfuncs.h" 38fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 398426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com#define XFREE86_REFRESH_HACK 408426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com#ifdef XFREE86_REFRESH_HACK 418426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com#include "SDL_x11image_c.h" 428426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com#endif 43842292f10fc08bc8701114f7eec00944b6ea26d2reed@google.com 448426058dee0faf75a18b81cfcde47ee8ab8c31d9reed@google.com/* Workaround when pitch != width */ 451f90287df3129cb267422e482c52ebeca6a8990ftomhudson@google.com#define PITCH_WORKAROUND 46fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 470e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org/* Workaround intel i810 video overlay waiting with failing until the 480e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org first Xv[Shm]PutImage call <sigh> */ 490716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#define INTEL_XV_BADALLOC_WORKAROUND 500716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 510716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com/* Fix for the NVidia GeForce 2 - use the last available adaptor */ 520716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com/*#define USE_LAST_ADAPTOR*/ /* Apparently the NVidia drivers are fixed */ 530716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 540716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com/* The functions used to manipulate software video overlays */ 550716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.comstatic struct private_yuvhwfuncs x11_yuvfuncs = { 560716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com X11_LockYUVOverlay, 570716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com X11_UnlockYUVOverlay, 580716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com X11_DisplayYUVOverlay, 590716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com X11_FreeYUVOverlay 600716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com}; 618c3ff17e2cab6f7c798b9f8ff4515c4a3d3fd9d1bsalomon@google.com 620716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.comstruct private_yuvhwdata { 630716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com int port; 640716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#ifndef NO_SHARED_MEMORY 650716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com int yuv_use_mitshm; 660716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com XShmSegmentInfo yuvshm; 670716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#endif 680716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com SDL_NAME(XvImage) *image; 690716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com}; 700716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 710716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 720716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.comstatic int (*X_handler)(Display *, XErrorEvent *) = NULL; 730716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com 740716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com#ifndef NO_SHARED_MEMORY 750716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com/* Shared memory error handler routine */ 760716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.comstatic int shm_error; 770e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.orgstatic int shm_errhandler(Display *d, XErrorEvent *e) 780e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org{ 790e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org if ( e->error_code == BadAccess ) { 80a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org shm_error = True; 810716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com return(0); 820716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com } else 830716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com return(X_handler(d,e)); 840716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com} 854991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com#endif /* !NO_SHARED_MEMORY */ 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 87a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.orgstatic int xv_error; 88fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comstatic int xv_errhandler(Display *d, XErrorEvent *e) 890e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org{ 90a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org if ( e->error_code == BadMatch ) { 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com xv_error = True; 92a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org return(0); 93fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } else 948f838259ab65e44562902679fa88cb00575b99cecommit-bot@chromium.org return(X_handler(d,e)); 958f838259ab65e44562902679fa88cb00575b99cecommit-bot@chromium.org} 968f838259ab65e44562902679fa88cb00575b99cecommit-bot@chromium.org 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef INTEL_XV_BADALLOC_WORKAROUND 984e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.comstatic int intel_errhandler(Display *d, XErrorEvent *e) 994e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com{ 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ( e->error_code == BadAlloc ) { 1014991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com xv_error = True; 10274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org return(0); 10374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org } else 10474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org return(X_handler(d,e)); 10574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org} 106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void X11_ClearYUVOverlay(SDL_Overlay *overlay) 1088b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org{ 109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com int x,y; 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (overlay->format) 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SDL_YV12_OVERLAY: 1140716c63332a64c3cc77a9afb87ae2fd9614f0c4freed@google.com case SDL_IYUV_OVERLAY: 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (y = 0; y < overlay->h; y++) 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(overlay->pixels[0] + y * overlay->pitches[0], 1178f838259ab65e44562902679fa88cb00575b99cecommit-bot@chromium.org 0, overlay->w); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1194e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com for (y = 0; y < (overlay->h / 2); y++) 1204e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com { 1214e2b3d3fb1288c6dc0f3ea1c0aa4a0d7c603bd7breed@google.com memset(overlay->pixels[1] + y * overlay->pitches[1], 1220e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org -128, overlay->w / 2); 123a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org memset(overlay->pixels[2] + y * overlay->pitches[2], 1240e2810be95d3f1aa95c341521d3f514eb9e9ebdemike@reedtribe.org -128, overlay->w / 2); 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SDL_YUY2_OVERLAY: 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SDL_YVYU_OVERLAY: 129fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com for (y = 0; y < overlay->h; y++) 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 13174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org for (x = 0; x < overlay->w; x += 2) 13274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org { 13374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org Uint8 *pixel_pair = overlay->pixels[0] + 13474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org y * overlay->pitches[0] + x * 2; 13574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org pixel_pair[0] = 0; 13674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org pixel_pair[1] = -128; 13774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org pixel_pair[2] = 0; 13874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org pixel_pair[3] = -128; 13974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org } 14074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org } 14174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org break; 14274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org case SDL_UYVY_OVERLAY: 14374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org for (y = 0; y < overlay->h; y++) 14474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org { 14574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org for (x = 0; x < overlay->w; x += 2) 14674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org { 14774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org Uint8 *pixel_pair = overlay->pixels[0] + 14874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org y * overlay->pitches[0] + x * 2; 14974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org pixel_pair[0] = -128; 15074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org pixel_pair[1] = 0; 15174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org pixel_pair[2] = -128; 15274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org pixel_pair[3] = 0; 15374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org } 15474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org } 15574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org break; 15674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org } 15774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org} 15874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org#endif 15974ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org 16074ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.orgSDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) 16174ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org{ 16274ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org SDL_Overlay *overlay; 16374ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org struct private_yuvhwdata *hwdata; 16474ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org int xv_port; 16574ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org unsigned int i, j, k; 16674ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org unsigned int adaptors; 16774ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org SDL_NAME(XvAdaptorInfo) *ainfo; 16874ba2f62dce1998bd6555291ab0a5330c276301dcommit-bot@chromium.org int bpp; 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef NO_SHARED_MEMORY 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com XShmSegmentInfo *yuvshm; 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#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 472int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay) 473{ 474 return(0); 475} 476 477void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) 478{ 479 return; 480} 481 482int 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 507void 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 */ 539