Mercurial > mplayer.hg
comparison libvo/vo_xvmc.c @ 10698:7ab88b24cb81
OSD support, optinal queue, optional use of sleep(), and benchmark mode
author | iive |
---|---|
date | Mon, 25 Aug 2003 21:41:10 +0000 |
parents | 2cae82f2ab02 |
children | 240e212130d3 |
comparison
equal
deleted
inserted
replaced
10697:f0cddd635519 | 10698:7ab88b24cb81 |
---|---|
1 #include <stdlib.h> | 1 #include <stdlib.h> |
2 #include <stdio.h> | 2 #include <stdio.h> |
3 #include <string.h> | 3 #include <string.h> |
4 | 4 #include <unistd.h> |
5 #include <X11/Xlib.h> | |
6 #include <X11/Xutil.h> | |
7 #include <X11/Xatom.h> | |
8 #include <X11/extensions/Xv.h> | |
9 #include <X11/extensions/Xvlib.h> | |
10 #include <X11/extensions/XvMClib.h> | |
11 | 5 |
12 #include "config.h" | 6 #include "config.h" |
13 #include "mp_msg.h" | 7 #include "mp_msg.h" |
14 #include "video_out.h" | 8 #include "video_out.h" |
15 #include "video_out_internal.h" | 9 #include "video_out_internal.h" |
16 #include "fastmemcpy.h" | 10 #include "fastmemcpy.h" |
11 #include "osdep/timer.h" | |
12 | |
13 #include <X11/Xlib.h> | |
14 #include <X11/Xutil.h> | |
15 #include <X11/Xatom.h> | |
16 | |
17 #ifdef HAVE_SHM | |
18 #include <sys/ipc.h> | |
19 #include <sys/shm.h> | |
20 #include <X11/extensions/XShm.h> | |
21 #endif | |
22 | |
23 #include <X11/extensions/Xv.h> | |
24 #include <X11/extensions/Xvlib.h> | |
25 #include <X11/extensions/XvMClib.h> | |
17 | 26 |
18 #include "x11_common.h" | 27 #include "x11_common.h" |
19 #include "xvmc_render.h" | 28 #include "xvmc_render.h" |
20 | 29 |
21 #include "sub.h" | 30 #include "sub.h" |
23 | 32 |
24 #ifdef HAVE_NEW_GUI | 33 #ifdef HAVE_NEW_GUI |
25 #include "../Gui/interface.h" | 34 #include "../Gui/interface.h" |
26 #endif | 35 #endif |
27 | 36 |
37 //no chanse xinerama to be suported in near future | |
28 #undef HAVE_XINERAMA | 38 #undef HAVE_XINERAMA |
29 | 39 |
30 #undef NDEBUG | 40 #undef NDEBUG |
31 #include <assert.h> | 41 #include <assert.h> |
32 | 42 |
33 //no chanse xinerama to be suported in near future | |
34 | 43 |
35 #define UNUSED(x) ((void)(x)) | 44 #define UNUSED(x) ((void)(x)) |
36 | 45 |
37 | 46 |
38 extern int vo_directrendering; | 47 extern int vo_directrendering; |
39 extern int vo_verbose; | 48 extern int vo_verbose; |
40 | 49 |
41 static void xvmc_free(void); | 50 static int benchmark; |
51 static int busy_wait; | |
52 static int use_queue; | |
42 | 53 |
43 static int image_width,image_height; | 54 static int image_width,image_height; |
44 static uint32_t drwX,drwY; | 55 static uint32_t drwX,drwY; |
45 | 56 |
46 static XvPortID xv_port; | 57 static XvPortID xv_port; |
47 | 58 |
48 //0-auto;1-backgound always keycolor;2-autopaint(by X);3-manual fill | 59 #define AUTO_COLORKEY 0 |
60 #define BACKGROUND_COLORKEY 1 | |
61 #define AUTOPAINT_COLORKEY 2 | |
62 #define MANUALFILL_COLORKEY 3 | |
49 static int keycolor_handling; | 63 static int keycolor_handling; |
50 static unsigned long keycolor; | 64 static unsigned long keycolor; |
65 | |
66 #define NO_SUBPICTURE 0 | |
67 #define OVERLAY_SUBPICTURE 1 | |
68 #define BLEND_SUBPICTURE 2 | |
69 #define BACKEND_SUBPICTURE 3 | |
70 | |
71 static int subpicture_mode; | |
72 static int subpicture_alloc; | |
73 static XvMCSubpicture subpicture; | |
74 static XvImageFormatValues subpicture_info; | |
75 static int subpicture_clear_color;//transparent color for the subpicture or color key for overlay | |
51 | 76 |
52 static XvMCSurfaceInfo surface_info; | 77 static XvMCSurfaceInfo surface_info; |
53 static XvMCContext ctx; | 78 static XvMCContext ctx; |
54 static XvMCBlockArray data_blocks; | 79 static XvMCBlockArray data_blocks; |
55 static XvMCMacroBlockArray mv_blocks; | 80 static XvMCMacroBlockArray mv_blocks; |
59 static XvMCSurface surface_array[MAX_SURFACES]; | 84 static XvMCSurface surface_array[MAX_SURFACES]; |
60 static xvmc_render_state_t * surface_render; | 85 static xvmc_render_state_t * surface_render; |
61 | 86 |
62 static xvmc_render_state_t * p_render_surface_to_show=NULL; | 87 static xvmc_render_state_t * p_render_surface_to_show=NULL; |
63 static xvmc_render_state_t * p_render_surface_visible=NULL; | 88 static xvmc_render_state_t * p_render_surface_visible=NULL; |
89 | |
90 //display queue, kinda render ahead | |
91 static xvmc_render_state_t * show_queue[MAX_SURFACES]; | |
92 static int free_element; | |
93 | |
94 | |
95 static void (*draw_osd_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride); | |
96 static void (*clear_osd_fnc)(int x0,int y0, int w,int h); | |
97 static void (*init_osd_fnc)(void); | |
98 | |
99 static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride); | |
100 static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride); | |
101 static void clear_osd_subpic(int x0,int y0, int w,int h); | |
102 static void init_osd_yuv_pal(void); | |
103 | |
104 | |
105 static const struct{ | |
106 int id;//id as xvimages or as mplayer RGB|{8,15,16,24,32} | |
107 void (* init_func_ptr)(); | |
108 void (* draw_func_ptr)(); | |
109 void (* clear_func_ptr)(); | |
110 } osd_render[]={ | |
111 {0x34344149,init_osd_yuv_pal,draw_osd_AI44,clear_osd_subpic}, | |
112 {0x34344941,init_osd_yuv_pal,draw_osd_IA44,clear_osd_subpic}, | |
113 {0,NULL,NULL,NULL} | |
114 }; | |
115 | |
116 static void xvmc_free(void); | |
117 static int count_free_surfaces(); | |
118 static xvmc_render_state_t * find_free_surface(); | |
64 | 119 |
65 static vo_info_t info = { | 120 static vo_info_t info = { |
66 "XVideo Motion Compensation", | 121 "XVideo Motion Compensation", |
67 "xvmc", | 122 "xvmc", |
68 "Ivan Kalvachev <iive@users.sf.net>", | 123 "Ivan Kalvachev <iive@users.sf.net>", |
69 "" | 124 "" |
70 }; | 125 }; |
71 | 126 |
72 LIBVO_EXTERN(xvmc); | 127 LIBVO_EXTERN(xvmc); |
73 | 128 |
129 //shm stuff from vo_xv | |
130 #ifdef HAVE_SHM | |
131 /* since it doesn't seem to be defined on some platforms */ | |
132 int XShmGetEventBase(Display*); | |
133 static XShmSegmentInfo Shminfo; | |
134 static int Shmem_Flag; | |
135 #endif | |
136 XvImage * xvimage; | |
137 | |
138 | |
139 static void allocate_xvimage(int xvimage_width,int xvimage_height,int xv_format) | |
140 { | |
141 /* | |
142 * allocate XvImages. FIXME: no error checking, without | |
143 * mit-shm this will bomb... trzing to fix ::atmos | |
144 */ | |
145 #ifdef HAVE_SHM | |
146 if ( mLocalDisplay && XShmQueryExtension( mDisplay ) ) Shmem_Flag = 1; | |
147 else | |
148 { | |
149 Shmem_Flag = 0; | |
150 mp_msg(MSGT_VO,MSGL_INFO, "Shared memory not supported\nReverting to normal Xv\n" ); | |
151 } | |
152 if ( Shmem_Flag ) | |
153 { | |
154 xvimage = (XvImage *) XvShmCreateImage(mDisplay, xv_port, xv_format, | |
155 NULL, xvimage_width, xvimage_height, &Shminfo); | |
156 | |
157 Shminfo.shmid = shmget(IPC_PRIVATE, xvimage->data_size, IPC_CREAT | 0777); | |
158 Shminfo.shmaddr = (char *) shmat(Shminfo.shmid, 0, 0); | |
159 Shminfo.readOnly = False; | |
160 | |
161 xvimage->data = Shminfo.shmaddr; | |
162 XShmAttach(mDisplay, &Shminfo); | |
163 XSync(mDisplay, False); | |
164 shmctl(Shminfo.shmid, IPC_RMID, 0); | |
165 } | |
166 else | |
167 #endif | |
168 { | |
169 xvimage = (XvImage *) XvCreateImage(mDisplay, xv_port, xv_format, NULL, xvimage_width, xvimage_height); | |
170 xvimage->data = malloc(xvimage->data_size); | |
171 XSync(mDisplay,False); | |
172 } | |
173 // memset(xvimage->data,128,xvimage->data_size); | |
174 return; | |
175 } | |
176 | |
177 static void deallocate_xvimage() | |
178 { | |
179 #ifdef HAVE_SHM | |
180 if ( Shmem_Flag ) | |
181 { | |
182 XShmDetach( mDisplay,&Shminfo ); | |
183 shmdt( Shminfo.shmaddr ); | |
184 } | |
185 else | |
186 #endif | |
187 { | |
188 free(xvimage->data); | |
189 } | |
190 XFree(xvimage); | |
191 | |
192 XFlush( mDisplay ); | |
193 XSync(mDisplay, False); | |
194 return; | |
195 } | |
196 //end of vo_xv shm/xvimage code | |
197 | |
198 | |
74 static void init_keycolor(){ | 199 static void init_keycolor(){ |
75 Atom xv_atom; | 200 Atom xv_atom; |
76 XvAttribute * attributes; | 201 XvAttribute * attributes; |
77 int colorkey; | 202 int colorkey; |
78 int rez; | 203 int rez; |
79 int attrib_count,i; | 204 int attrib_count,i; |
80 | 205 |
81 keycolor=2110; | 206 keycolor=2110; |
82 | 207 |
83 if(keycolor_handling == 0){ | 208 if(keycolor_handling == AUTO_COLORKEY){ |
84 //XV_AUTOPING_COLORKEY doesn't work for XvMC yet(NVidia 43.63) | 209 //XV_AUTOPING_COLORKEY doesn't work for XvMC yet(NVidia 43.63) |
85 attributes = XvQueryPortAttributes(mDisplay, xv_port, &attrib_count); | 210 attributes = XvQueryPortAttributes(mDisplay, xv_port, &attrib_count); |
86 if(attributes!=NULL) | 211 if(attributes!=NULL) |
87 for (i = 0; i < attrib_count; i++) | 212 for (i = 0; i < attrib_count; i++) |
88 if (!strcmp(attributes[i].name, "XV_AUTOPAINT_COLORKEY")) | 213 if (!strcmp(attributes[i].name, "XV_AUTOPAINT_COLORKEY")) |
89 { | 214 { |
90 xv_atom = XInternAtom(mDisplay, "XV_AUTOPAINT_COLORKEY", False); | 215 xv_atom = XInternAtom(mDisplay, "XV_AUTOPAINT_COLORKEY", False); |
91 if(xv_atom!=None) | 216 if(xv_atom!=None) |
92 { | 217 { |
93 rez=XvSetPortAttribute(mDisplay, xv_port, xv_atom, 1); | 218 rez=XvSetPortAttribute(mDisplay, xv_port, xv_atom, 1); |
94 if(rez == Success) | 219 if(rez == Success) |
95 keycolor_handling = 2;//this is the way vo_xv works | 220 keycolor_handling = AUTOPAINT_COLORKEY; |
96 } | 221 } |
97 break; | 222 break; |
98 } | 223 } |
99 XFree(attributes); | 224 XFree(attributes); |
100 } | 225 } |
101 | 226 |
102 xv_atom = XInternAtom(mDisplay, "XV_COLORKEY",False); | 227 xv_atom = XInternAtom(mDisplay, "XV_COLORKEY",False); |
103 if(xv_atom == None) return; | 228 if(xv_atom == None) return; |
104 rez=XvGetPortAttribute(mDisplay,xv_port, xv_atom, &colorkey); | 229 rez=XvGetPortAttribute(mDisplay,xv_port, xv_atom, &colorkey); |
105 if(rez == Success){ | 230 if(rez == Success){ |
106 keycolor=colorkey; | 231 keycolor = colorkey; |
107 if(keycolor_handling == 0){ | 232 if(keycolor_handling == AUTO_COLORKEY){ |
108 keycolor_handling = 3; | 233 keycolor_handling = MANUALFILL_COLORKEY; |
109 } | 234 } |
110 } | 235 } |
111 } | 236 } |
112 | 237 |
113 //from vo_xmga | 238 //from vo_xmga |
114 static void mDrawColorKey(uint32_t x,uint32_t y, uint32_t w, uint32_t h) | 239 static void mDrawColorKey(uint32_t x,uint32_t y, uint32_t w, uint32_t h) |
115 { | 240 { |
116 if( (keycolor_handling != 2) && (keycolor_handling != 3) ) | 241 if( (keycolor_handling != AUTOPAINT_COLORKEY) && |
117 return ;//unknown method | 242 (keycolor_handling != MANUALFILL_COLORKEY) ) |
243 return; | |
118 | 244 |
119 XSetBackground( mDisplay,vo_gc,0 ); | 245 XSetBackground( mDisplay,vo_gc,0 ); |
120 XClearWindow( mDisplay,vo_window ); | 246 XClearWindow( mDisplay,vo_window ); |
121 | 247 |
122 if(keycolor_handling == 3){ | 248 if(keycolor_handling == MANUALFILL_COLORKEY){ |
123 XSetForeground( mDisplay,vo_gc,keycolor ); | 249 XSetForeground( mDisplay,vo_gc,keycolor ); |
124 XFillRectangle( mDisplay,vo_window,vo_gc,x,y,w,h); | 250 XFillRectangle( mDisplay,vo_window,vo_gc,x,y,w,h); |
125 } | 251 } |
126 XFlush( mDisplay ); | 252 XFlush( mDisplay ); |
127 } | 253 } |
128 | 254 |
129 // now it is ugly, but i need it working | 255 |
130 static int xvmc_check_surface_format(uint32_t format, XvMCSurfaceInfo * surf_info){ | 256 static int xvmc_check_surface_format(uint32_t format, XvMCSurfaceInfo * surf_info){ |
131 if ( format == IMGFMT_XVMC_IDCT_MPEG2 ){ | 257 if ( format == IMGFMT_XVMC_IDCT_MPEG2 ){ |
132 if( surf_info->mc_type != (XVMC_IDCT|XVMC_MPEG_2) ) return -1; | 258 if( surf_info->mc_type != (XVMC_IDCT|XVMC_MPEG_2) ) return -1; |
133 if( surf_info->chroma_format != XVMC_CHROMA_FORMAT_420 ) return -1; | 259 if( surf_info->chroma_format != XVMC_CHROMA_FORMAT_420 ) return -1; |
134 return 0; | 260 return 0; |
139 return 0; | 265 return 0; |
140 } | 266 } |
141 return -1;//fail | 267 return -1;//fail |
142 } | 268 } |
143 | 269 |
270 //print all info needed to add new format | |
271 static void print_xvimage_format_values(XvImageFormatValues *xifv){ | |
272 int i; | |
273 printf("Format_ID = 0x%X\n",xifv->id); | |
274 | |
275 printf(" type = "); | |
276 if(xifv->type == XvRGB) printf("RGB\n"); | |
277 else if(xifv->type == XvYUV) printf("YUV\n"); | |
278 else printf("Unknown\n"); | |
279 | |
280 printf(" byte_order = "); | |
281 if(xifv->byte_order == LSBFirst) printf("LSB First\n"); | |
282 else if(xifv->type == MSBFirst) printf("MSB First\n"); | |
283 else printf("Unknown\n");//yes Linux support other types too | |
284 | |
285 printf(" guid = "); | |
286 for(i=0;i<16;i++) | |
287 printf("%02X ",(unsigned char)xifv->guid[i]); | |
288 printf("\n"); | |
289 | |
290 printf(" bits_per_pixel = %d\n",xifv->bits_per_pixel); | |
291 | |
292 printf(" format = "); | |
293 if(xifv->format == XvPacked) printf("XvPacked\n"); | |
294 else if(xifv->format == XvPlanar) printf("XvPlanar\n"); | |
295 else printf("Unknown\n"); | |
296 | |
297 printf(" num_planes = %d\n",xifv->num_planes); | |
298 | |
299 if(xifv->type == XvRGB){ | |
300 printf(" red_mask = %0X\n", xifv->red_mask); | |
301 printf(" green_mask = %0X\n",xifv->green_mask); | |
302 printf(" blue_mask = %0X\n", xifv->blue_mask); | |
303 } | |
304 if(xifv->type == XvYUV){ | |
305 printf(" y_sample_bits = %d\n u_sample_bits = %d\n v_sample_bits = %d\n", | |
306 xifv->y_sample_bits,xifv->u_sample_bits,xifv->v_sample_bits); | |
307 printf(" horz_y_period = %d\n horz_u_period = %d\n horz_v_period = %d\n", | |
308 xifv->horz_y_period,xifv->horz_u_period,xifv->horz_v_period); | |
309 printf(" vert_y_period = %d\n vert_u_period = %d\n vert_v_period = %d\n", | |
310 xifv->vert_y_period,xifv->vert_u_period,xifv->vert_v_period); | |
311 | |
312 printf(" component_order = "); | |
313 for(i=0;i<32;i++) | |
314 if(xifv->component_order[i]>=32) | |
315 printf("%c",xifv->component_order[i]); | |
316 printf("\n"); | |
317 | |
318 printf(" scanline = "); | |
319 if(xifv->scanline_order == XvTopToBottom) printf("XvTopToBottom\n"); | |
320 else if(xifv->scanline_order == XvBottomToTop) printf("XvBottomToTop\n"); | |
321 else printf("Unknown\n"); | |
322 } | |
323 printf("\n"); | |
324 } | |
325 | |
144 // WARNING This function may changes xv_port and surface_info! | 326 // WARNING This function may changes xv_port and surface_info! |
145 static int xvmc_find_surface_by_format(int format,int width,int height, | 327 static int xvmc_find_surface_by_format(int format,int width,int height, |
146 XvMCSurfaceInfo * surf_info,int query){ | 328 XvMCSurfaceInfo * surf_info,int query){ |
147 int rez; | 329 int rez; |
148 XvAdaptorInfo * ai; | 330 XvAdaptorInfo * ai; |
149 int num_adaptors,i; | 331 int num_adaptors,i; |
150 unsigned long p; | 332 unsigned long p; |
151 int s,mc_surf_num; | 333 int s,mc_surf_num; |
152 XvMCSurfaceInfo * mc_surf_list; | 334 XvMCSurfaceInfo * mc_surf_list; |
153 | 335 |
154 rez = XvQueryAdaptors(mDisplay,DefaultRootWindow(mDisplay),&num_adaptors,&ai); | 336 rez = XvQueryAdaptors(mDisplay,DefaultRootWindow(mDisplay),&num_adaptors,&ai); |
155 if( rez != Success ) return -1; | 337 if( rez != Success ) return -1; |
156 if( verbose > 2 ) printf("vo_xvmc: Querying %d adaptors\n",num_adaptors); | 338 if( verbose > 2 ) printf("vo_xvmc: Querying %d adaptors\n",num_adaptors); |
157 for(i=0; i<num_adaptors; i++) | 339 for(i=0; i<num_adaptors; i++) |
158 { | 340 { |
169 } | 351 } |
170 if( verbose > 2) printf("vo_xvmc: XvMC list have %d surfaces\n",mc_surf_num); | 352 if( verbose > 2) printf("vo_xvmc: XvMC list have %d surfaces\n",mc_surf_num); |
171 //we have XvMC list! | 353 //we have XvMC list! |
172 for(s=0; s<mc_surf_num; s++) | 354 for(s=0; s<mc_surf_num; s++) |
173 { | 355 { |
174 if( width > mc_surf_list[s].max_width ) continue; | 356 if( width > mc_surf_list[s].max_width ) continue; |
175 if( height > mc_surf_list[s].max_height ) continue; | 357 if( height > mc_surf_list[s].max_height ) continue; |
176 if( xvmc_check_surface_format(format,&mc_surf_list[s])<0 ) continue; | 358 if( xvmc_check_surface_format(format,&mc_surf_list[s])<0 ) continue; |
177 //we have match! | 359 //we have match! |
178 | 360 |
179 if(!query){ | 361 if(!query){ |
180 rez = XvGrabPort(mDisplay,p,CurrentTime); | 362 rez = XvGrabPort(mDisplay,p,CurrentTime); |
181 if(rez != Success){ | 363 if(rez != Success){ |
182 if (verbose > 2) printf("vo_xvmc: Fail to grab port %ld\n",p); | 364 if (verbose > 2) printf("vo_xvmc: Fail to grab port %ld\n",p); |
183 continue; | 365 continue; |
184 } | 366 } |
185 printf("vo_xvmc: Port %ld grabed\n",p); | 367 printf("vo_xvmc: Port %ld grabed\n",p); |
188 goto surface_found; | 370 goto surface_found; |
189 }//for mc surf | 371 }//for mc surf |
190 XFree(mc_surf_list);//if mc_surf_num==0 is list==NULL ? | 372 XFree(mc_surf_list);//if mc_surf_num==0 is list==NULL ? |
191 }//for ports | 373 }//for ports |
192 }//for adaptors | 374 }//for adaptors |
193 | 375 |
194 if(!query) printf("vo_xvmc: Could not find free matching surface. Sorry.\n"); | 376 if(!query) printf("vo_xvmc: Could not find free matching surface. Sorry.\n"); |
195 return 0; | 377 return 0; |
196 | 378 |
197 // somebody know cleaner way to escape from 3 internal loops? | 379 // somebody know cleaner way to escape from 3 internal loops? |
198 surface_found: | 380 surface_found: |
208 xvmc_render_state_t * rndr; | 390 xvmc_render_state_t * rndr; |
209 | 391 |
210 assert(mpi!=NULL); | 392 assert(mpi!=NULL); |
211 assert(mpi->flags &MP_IMGFLAG_DIRECT); | 393 assert(mpi->flags &MP_IMGFLAG_DIRECT); |
212 // assert(mpi->flags &MP_IMGFLAGS_DRAWBACK); | 394 // assert(mpi->flags &MP_IMGFLAGS_DRAWBACK); |
213 | 395 |
214 rndr = (xvmc_render_state_t*)mpi->priv;//there is copy in plane[2] | 396 rndr = (xvmc_render_state_t*)mpi->priv;//there is copy in plane[2] |
215 assert( rndr != NULL ); | 397 assert( rndr != NULL ); |
216 assert( rndr->magic == MP_XVMC_RENDER_MAGIC ); | 398 assert( rndr->magic == MP_XVMC_RENDER_MAGIC ); |
217 if( verbose > 3 ) | 399 if( verbose > 3 ) |
218 printf("vo_xvmc: draw_image(show rndr=%p)\n",rndr); | 400 printf("vo_xvmc: draw_image(show rndr=%p)\n",rndr); |
225 static uint32_t preinit(const char *arg){ | 407 static uint32_t preinit(const char *arg){ |
226 int xv_version,xv_release,xv_request_base,xv_event_base,xv_error_base; | 408 int xv_version,xv_release,xv_request_base,xv_event_base,xv_error_base; |
227 int mc_eventBase,mc_errorBase; | 409 int mc_eventBase,mc_errorBase; |
228 int mc_ver,mc_rev; | 410 int mc_ver,mc_rev; |
229 | 411 |
230 //Obtain display handler | 412 //Obtain display handler |
231 if (!vo_init()) return -1;//vo_xv | 413 if (!vo_init()) return -1;//vo_xv |
232 | 414 |
233 //XvMC is subdivision of XVideo | 415 //XvMC is subdivision of XVideo |
234 if (Success != XvQueryExtension(mDisplay,&xv_version,&xv_release,&xv_request_base, | 416 if (Success != XvQueryExtension(mDisplay,&xv_version,&xv_release,&xv_request_base, |
235 &xv_event_base,&xv_error_base) ){ | 417 &xv_event_base,&xv_error_base) ){ |
236 mp_msg(MSGT_VO,MSGL_ERR,"Sorry, Xv(MC) not supported by this X11 version/driver\n"); | 418 mp_msg(MSGT_VO,MSGL_ERR,"Sorry, Xv(MC) not supported by this X11 version/driver\n"); |
237 mp_msg(MSGT_VO,MSGL_ERR,"********** Try with -vo x11 or -vo sdl ***********\n"); | 419 mp_msg(MSGT_VO,MSGL_ERR,"********** Try with -vo x11 or -vo sdl ***********\n"); |
238 return -1; | 420 return -1; |
239 } | 421 } |
240 printf("vo_xvmc: X-Video extension %d.%d\n",xv_version,xv_release); | 422 printf("vo_xvmc: X-Video extension %d.%d\n",xv_version,xv_release); |
241 | 423 |
242 if( True != XvMCQueryExtension(mDisplay,&mc_eventBase,&mc_errorBase) ){ | 424 if( True != XvMCQueryExtension(mDisplay,&mc_eventBase,&mc_errorBase) ){ |
243 printf("vo_xvmc: No X-Video MotionCompensation Extension on %s\n", | 425 printf("vo_xvmc: No X-Video MotionCompensation Extension on %s\n", |
244 XDisplayName(NULL)); | 426 XDisplayName(NULL)); |
245 return -1; | 427 return -1; |
246 } | 428 } |
247 | 429 |
248 if(Success == XvMCQueryVersion(mDisplay, &mc_ver, &mc_rev) ){ | 430 if(Success == XvMCQueryVersion(mDisplay, &mc_ver, &mc_rev) ){ |
249 printf("vo_xvmc: X-Video MotionCompensation Extension version %i.%i\n", | 431 printf("vo_xvmc: X-Video MotionCompensation Extension version %i.%i\n", |
250 mc_ver,mc_rev); | 432 mc_ver,mc_rev); |
251 } | 433 } |
252 else{ | 434 else{ |
253 printf("vo_xvmc: Error querying version info!\n"); | 435 printf("vo_xvmc: Error querying version info!\n"); |
254 return -1; | 436 return -1; |
255 } | 437 } |
438 surface_render = NULL; | |
256 xv_port = 0; | 439 xv_port = 0; |
257 number_of_surfaces = 0; | 440 number_of_surfaces = 0; |
258 keycolor_handling = 3;//!!fixme | 441 keycolor_handling = MANUALFILL_COLORKEY;//fixme |
259 surface_render=NULL; | 442 subpicture_alloc = 0; |
260 | 443 |
444 benchmark = 0; //disable PutImageto allow faster display than screen refresh | |
445 busy_wait = 1; | |
446 use_queue = 0; | |
447 if(arg) | |
448 while(*arg){ | |
449 if(strncmp(arg,"benchmark",9) == 0){ | |
450 arg+=9; | |
451 if(*arg == ':') arg++; | |
452 benchmark = 1;//disable PutImageto allow faster display than screen refresh | |
453 continue; | |
454 } | |
455 if(strncmp(arg,"wait",4) == 0){ | |
456 arg+=4; | |
457 if(*arg == ':') arg++; | |
458 busy_wait = 1; | |
459 continue; | |
460 } | |
461 if(strncmp(arg,"sleep",5) == 0){ | |
462 arg+=5; | |
463 if(*arg == ':') arg++; | |
464 busy_wait = 0; | |
465 continue; | |
466 } | |
467 if(strncmp(arg,"queue",5) == 0){ | |
468 arg+=5; | |
469 if(*arg == ':') arg++; | |
470 use_queue = 1; | |
471 continue; | |
472 } | |
473 break; | |
474 } | |
475 | |
261 return 0; | 476 return 0; |
262 } | 477 } |
263 | 478 |
264 static uint32_t config(uint32_t width, uint32_t height, | 479 static uint32_t config(uint32_t width, uint32_t height, |
265 uint32_t d_width, uint32_t d_height, | 480 uint32_t d_width, uint32_t d_height, |
295 xvmc_free(); | 510 xvmc_free(); |
296 }; | 511 }; |
297 numblocks=((width+15)/16)*((height+15)/16); | 512 numblocks=((width+15)/16)*((height+15)/16); |
298 // Find Supported Surface Type | 513 // Find Supported Surface Type |
299 mode_id = xvmc_find_surface_by_format(format,width,height,&surface_info,0);//false=1 to grab port, not query | 514 mode_id = xvmc_find_surface_by_format(format,width,height,&surface_info,0);//false=1 to grab port, not query |
300 | 515 |
301 rez = XvMCCreateContext(mDisplay, xv_port,mode_id,width,height,XVMC_DIRECT,&ctx); | 516 rez = XvMCCreateContext(mDisplay, xv_port,mode_id,width,height,XVMC_DIRECT,&ctx); |
302 if( rez != Success ) return -1; | 517 if( rez != Success ) return -1; |
303 if( ctx.flags & XVMC_DIRECT ){ | 518 if( ctx.flags & XVMC_DIRECT ){ |
304 printf("vo_xvmc: Allocated Direct Context\n"); | 519 printf("vo_xvmc: Allocated Direct Context\n"); |
305 }else{ | 520 }else{ |
306 printf("vo_xvmc: Allocated Indirect Context!\n"); | 521 printf("vo_xvmc: Allocated Indirect Context!\n"); |
307 } | 522 } |
308 | 523 |
524 | |
309 blocks_per_macroblock = 6; | 525 blocks_per_macroblock = 6; |
310 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_422) | 526 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_422) |
311 blocks_per_macroblock = 8; | 527 blocks_per_macroblock = 8; |
312 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_444) | 528 if(surface_info.chroma_format == XVMC_CHROMA_FORMAT_444) |
313 blocks_per_macroblock = 12; | 529 blocks_per_macroblock = 12; |
314 | 530 |
315 rez = XvMCCreateBlocks(mDisplay,&ctx,numblocks*blocks_per_macroblock,&data_blocks); | 531 rez = XvMCCreateBlocks(mDisplay,&ctx,numblocks*blocks_per_macroblock,&data_blocks); |
316 if( rez != Success ){ | 532 if( rez != Success ){ |
317 XvMCDestroyContext(mDisplay,&ctx); | 533 XvMCDestroyContext(mDisplay,&ctx); |
327 } | 543 } |
328 printf("vo_xvmc: mv_blocks allocated\n"); | 544 printf("vo_xvmc: mv_blocks allocated\n"); |
329 | 545 |
330 if(surface_render==NULL) | 546 if(surface_render==NULL) |
331 surface_render=malloc(MAX_SURFACES*sizeof(xvmc_render_state_t));//easy mem debug | 547 surface_render=malloc(MAX_SURFACES*sizeof(xvmc_render_state_t));//easy mem debug |
332 | 548 |
333 for(i=0; i<MAX_SURFACES; i++){ | 549 for(i=0; i<MAX_SURFACES; i++){ |
334 rez=XvMCCreateSurface(mDisplay,&ctx,&surface_array[i]); | 550 rez=XvMCCreateSurface(mDisplay,&ctx,&surface_array[i]); |
335 if( rez != Success ) | 551 if( rez != Success ) |
336 break; | 552 break; |
337 memset(&surface_render[i],0,sizeof(xvmc_render_state_t)); | 553 memset(&surface_render[i],0,sizeof(xvmc_render_state_t)); |
360 //debug | 576 //debug |
361 printf("vo_xvmc: idct=%d unsigned_intra=%d\n", | 577 printf("vo_xvmc: idct=%d unsigned_intra=%d\n", |
362 (surface_info.mc_type & XVMC_IDCT) == XVMC_IDCT, | 578 (surface_info.mc_type & XVMC_IDCT) == XVMC_IDCT, |
363 (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED); | 579 (surface_info.flags & XVMC_INTRA_UNSIGNED) == XVMC_INTRA_UNSIGNED); |
364 | 580 |
581 // Find way to display OSD & subtitle | |
582 printf("vo_xvmc: looking for OSD support\n"); | |
583 subpicture_mode = NO_SUBPICTURE; | |
584 if(surface_info.flags & XVMC_OVERLAID_SURFACE) | |
585 subpicture_mode = OVERLAY_SUBPICTURE; | |
586 | |
587 if(surface_info.subpicture_max_width != 0 && | |
588 surface_info.subpicture_max_height != 0 ){ | |
589 int s,k,num_subpic; | |
590 | |
591 XvImageFormatValues * xvfmv; | |
592 xvfmv = XvMCListSubpictureTypes(mDisplay, xv_port, | |
593 surface_info.surface_type_id, &num_subpic); | |
594 | |
595 if(num_subpic != 0 && xvfmv != NULL){ | |
596 if(verbose > 3){//Print All subpicture types for debug | |
597 for(s=0;s<num_subpic;s++) | |
598 printf(" Subpicture id 0x%08X\n",xvfmv[s].id); | |
599 } | |
600 | |
601 if(verbose > 0) | |
602 for(s=0;s<num_subpic;s++){ | |
603 for(k=0;osd_render[k].draw_func_ptr!=NULL;k++) | |
604 | |
605 if(xvfmv[s].id == osd_render[k].id) | |
606 { | |
607 init_osd_fnc = osd_render[k].init_func_ptr; | |
608 draw_osd_fnc = osd_render[k].draw_func_ptr; | |
609 clear_osd_fnc = osd_render[k].clear_func_ptr; | |
610 | |
611 subpicture_mode = BLEND_SUBPICTURE; | |
612 subpicture_info = xvfmv[s]; | |
613 print_xvimage_format_values(&subpicture_info); | |
614 goto found_subpic; | |
615 } | |
616 } | |
617 found_subpic: | |
618 XFree(xvfmv); | |
619 } | |
620 //Blend2 supicture is always possible, blend1 only at backend | |
621 if( (subpicture_mode == BLEND_SUBPICTURE) && | |
622 (surface_info.flags & XVMC_BACKEND_SUBPICTURE) ) | |
623 { | |
624 subpicture_mode = BACKEND_SUBPICTURE; | |
625 } | |
626 | |
627 } | |
628 | |
629 switch(subpicture_mode){ | |
630 case NO_SUBPICTURE: | |
631 printf("vo_xvmc: No OSD support for this mode\n"); | |
632 break; | |
633 case OVERLAY_SUBPICTURE: | |
634 printf("vo_xvmc: OSD support via color key tricks\n"); | |
635 printf("vo_xvmc: not yet implemented:(\n"); | |
636 break; | |
637 case BLEND_SUBPICTURE: | |
638 printf("vo_xvmc: OSD support by additional frontend rendering\n"); | |
639 break; | |
640 case BACKEND_SUBPICTURE: | |
641 printf("vo_xvmc: OSD support by beckend rendering (fast)\n"); | |
642 printf("vo_xvmc: Pleace send feedback to configrm that it work,otherwise send bugreport!\n"); | |
643 break; | |
644 } | |
645 | |
365 init_keycolor();// take keycolor value and choose method for handling it | 646 init_keycolor();// take keycolor value and choose method for handling it |
366 | 647 |
367 //taken from vo_xv | 648 //taken from vo_xv |
368 panscan_init(); | 649 panscan_init(); |
369 | 650 |
370 aspect_save_orig(width,height); | 651 aspect_save_orig(width,height); |
371 aspect_save_prescale(d_width,d_height); | 652 aspect_save_prescale(d_width,d_height); |
372 | 653 |
373 image_height = height; | 654 image_height = height; |
374 image_width = width; | 655 image_width = width; |
375 | 656 |
376 vo_mouse_autohide = 1; | 657 vo_mouse_autohide = 1; |
377 | 658 |
378 vo_dx=( vo_screenwidth - d_width ) / 2; vo_dy=( vo_screenheight - d_height ) / 2; | 659 vo_dx=( vo_screenwidth - d_width ) / 2; vo_dy=( vo_screenheight - d_height ) / 2; |
379 geometry(&vo_dx, &vo_dy, &d_width, &d_height, vo_screenwidth, vo_screenheight); | 660 geometry(&vo_dx, &vo_dy, &d_width, &d_height, vo_screenwidth, vo_screenheight); |
380 vo_dwidth=d_width; vo_dheight=d_height; | 661 vo_dwidth=d_width; vo_dheight=d_height; |
381 | 662 |
382 #ifdef HAVE_XF86VM | 663 #ifdef HAVE_XF86VM |
383 if( flags&0x02 ) vm = 1; | 664 if( flags&0x02 ) vm = 1; |
384 #endif | 665 #endif |
385 | 666 |
386 aspect_save_screenres(vo_screenwidth,vo_screenheight); | 667 aspect_save_screenres(vo_screenwidth,vo_screenheight); |
433 depth=attribs.depth; | 714 depth=attribs.depth; |
434 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) depth = 24; | 715 if (depth != 15 && depth != 16 && depth != 24 && depth != 32) depth = 24; |
435 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo); | 716 XMatchVisualInfo(mDisplay, mScreen, depth, TrueColor, &vinfo); |
436 | 717 |
437 xswa.background_pixel = 0; | 718 xswa.background_pixel = 0; |
438 if (keycolor_handling == 1) | 719 if (keycolor_handling == BACKGROUND_COLORKEY) |
439 xswa.background_pixel = keycolor;// 2110; | 720 xswa.background_pixel = keycolor;// 2110; |
440 xswa.border_pixel = 0; | 721 xswa.border_pixel = 0; |
441 xswamask = CWBackPixel | CWBorderPixel; | 722 xswamask = CWBackPixel | CWBorderPixel; |
442 | 723 |
443 if ( WinID>=0 ){ | 724 if ( WinID>=0 ){ |
475 // vo_fs set means we were already at fullscreen | 756 // vo_fs set means we were already at fullscreen |
476 vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 ); | 757 vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 ); |
477 if ( !vo_fs ) XMoveResizeWindow( mDisplay,vo_window,hint.x,hint.y,hint.width,hint.height ); | 758 if ( !vo_fs ) XMoveResizeWindow( mDisplay,vo_window,hint.x,hint.y,hint.width,hint.height ); |
478 if ( flags&1 && !vo_fs ) vo_x11_fullscreen(); // handle -fs on non-first file | 759 if ( flags&1 && !vo_fs ) vo_x11_fullscreen(); // handle -fs on non-first file |
479 } | 760 } |
480 | 761 |
481 // vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 ); | 762 // vo_x11_sizehint( hint.x, hint.y, hint.width, hint.height,0 ); |
482 | 763 |
483 if ( vo_gc != None ) XFreeGC( mDisplay,vo_gc ); | 764 if ( vo_gc != None ) XFreeGC( mDisplay,vo_gc ); |
484 vo_gc = XCreateGC(mDisplay, vo_window, GCForeground, &xgcv); | 765 vo_gc = XCreateGC(mDisplay, vo_window, GCForeground, &xgcv); |
485 XFlush(mDisplay); | 766 XFlush(mDisplay); |
486 XSync(mDisplay, False); | 767 XSync(mDisplay, False); |
487 #ifdef HAVE_XF86VM | 768 #ifdef HAVE_XF86VM |
512 | 793 |
513 mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight ); | 794 mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight ); |
514 | 795 |
515 saver_off(mDisplay); // turning off screen saver | 796 saver_off(mDisplay); // turning off screen saver |
516 //end vo_xv | 797 //end vo_xv |
517 | 798 |
518 /* store image dimesions for displaying */ | 799 /* store image dimesions for displaying */ |
519 p_render_surface_visible = NULL; | 800 p_render_surface_visible = NULL; |
520 p_render_surface_to_show = NULL; | 801 p_render_surface_to_show = NULL; |
521 | 802 |
803 free_element = 0; | |
804 | |
522 vo_directrendering = 1;//ugly hack, coz xvmc works only with direct rendering | 805 vo_directrendering = 1;//ugly hack, coz xvmc works only with direct rendering |
523 return 0; | 806 return 0; |
524 } | 807 } |
525 | 808 |
526 static uint32_t draw_frame(uint8_t *srcp[]){ | 809 static uint32_t draw_frame(uint8_t *srcp[]){ |
527 assert(0 && srcp==NULL);//silense unused srcp warning | 810 UNUSED(srcp); |
811 assert(0); | |
812 } | |
813 | |
814 static void init_osd_yuv_pal(){ | |
815 char * palette; | |
816 int rez; | |
817 int i,j; | |
818 int snum,seb; | |
819 int Y,U,V; | |
820 | |
821 subpicture_clear_color = 0; | |
822 | |
823 if(subpicture.num_palette_entries > 0){ | |
824 | |
825 snum = subpicture.num_palette_entries; | |
826 seb = subpicture.entry_bytes; | |
827 palette = (char*)malloc(snum*seb);//check fail | |
828 if(palette == NULL) return; | |
829 for(i=0; i<snum; i++){ | |
830 // 0-black max-white the other are gradients | |
831 Y = i*(1 << subpicture_info.y_sample_bits)/snum;//snum=2;->(0),(1*(1<<1)/2) | |
832 U = 1 << (subpicture_info.u_sample_bits - 1); | |
833 V = 1 << (subpicture_info.v_sample_bits - 1); | |
834 for(j=0; j<seb; j++) | |
835 switch(subpicture.component_order[j]){ | |
836 case 'U': palette[i*seb+j] = U; break; | |
837 case 'V': palette[i*seb+j] = V; break; | |
838 case 'Y': | |
839 default: | |
840 palette[i*seb+j] = Y; break; | |
841 } | |
842 } | |
843 rez = XvMCSetSubpicturePalette(mDisplay, &subpicture, palette); | |
844 if(rez!=Success){ | |
845 printf("vo_xvmc: set pallete fail\n"); | |
846 } | |
847 } | |
848 } | |
849 | |
850 static void clear_osd_subpic(int x0, int y0, int w, int h){ | |
851 int rez; | |
852 rez=XvMCClearSubpicture(mDisplay, &subpicture, | |
853 x0, y0, w,h, | |
854 subpicture_clear_color); | |
855 if(rez != Success) | |
856 printf("vo_xvmc: XvMCClearSubpicture failed!\n"); | |
857 } | |
858 | |
859 static void OSD_init(){ | |
860 unsigned short osd_height, osd_width; | |
861 int rez; | |
862 | |
863 if(subpicture_alloc){ | |
864 if(verbose>3) | |
865 printf("vo_xvmc: destroying subpicture\n"); | |
866 XvMCDestroySubpicture(mDisplay,&subpicture); | |
867 deallocate_xvimage(); | |
868 subpicture_alloc = 0; | |
869 } | |
870 | |
871 /* if(surface_info.flags & XVMC_SUBPICTURE_INDEPENDENT_SCALING){ | |
872 osd_width = vo_dwidth; | |
873 osd_height = vo_dheight; | |
874 }else*/ | |
875 { | |
876 osd_width = image_width; | |
877 osd_height = image_height; | |
878 } | |
879 | |
880 if(osd_width > surface_info.subpicture_max_width) | |
881 osd_width = surface_info.subpicture_max_width; | |
882 if(osd_height > surface_info.subpicture_max_height) | |
883 osd_height = surface_info.subpicture_max_height; | |
884 if(osd_width == 0 || osd_height == 0) | |
885 return;//if called before window size is known | |
886 | |
887 if(verbose > 3) | |
888 printf("vo_xvmc: creating subpicture (%d,%d) format %X\n", | |
889 osd_width,osd_height,subpicture_info.id); | |
890 | |
891 rez = XvMCCreateSubpicture(mDisplay,&ctx,&subpicture, | |
892 osd_width,osd_height,subpicture_info.id); | |
893 if(rez != Success){ | |
894 subpicture_mode = NO_SUBPICTURE; | |
895 printf("vo_xvmc: Create Subpicture failed, OSD disabled\n"); | |
896 return; | |
897 } | |
898 if(verbose > 3){ | |
899 int i; | |
900 printf("vo_xvmc: Created Subpicture:\n"); | |
901 printf(" xvimage_id=0x%X\n",subpicture.xvimage_id); | |
902 printf(" width=%d\n",subpicture.width); | |
903 printf(" height=%d\n",subpicture.height); | |
904 printf(" num_palette_entries=0x%X\n",subpicture.num_palette_entries); | |
905 printf(" entry_bytes=0x%X\n",subpicture.entry_bytes); | |
906 | |
907 printf(" component_order=\""); | |
908 for(i=0; i<4; i++) | |
909 if(subpicture.component_order[i] >= 32) | |
910 printf("%c", subpicture.component_order[i]); | |
911 printf("\"\n"); | |
912 } | |
913 | |
914 //call init for the surface type | |
915 init_osd_fnc();//init palete,clear color etc ... | |
916 if(verbose > 3) | |
917 printf("vo_xvmc: clearing subpicture\n"); | |
918 clear_osd_fnc(0, 0, subpicture.width, subpicture.height); | |
919 | |
920 allocate_xvimage(subpicture.width, subpicture.height, subpicture_info.id); | |
921 subpicture_alloc = 1; | |
922 } | |
923 | |
924 static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ | |
925 int ox,oy; | |
926 int rez; | |
927 | |
928 if(verbose > 3) | |
929 printf("vo_xvmc:composite AI44 subpicture (%d,%d - %d,%d)\n",x0,y0,w,h); | |
930 | |
931 for(ox=0; ox<w; ox++){ | |
932 for(oy=0; oy<h; oy++){ | |
933 xvimage->data[oy*xvimage->width+ox] = (src[oy*stride+ox]>>4) | ((0-srca[oy*stride+ox])&0xf0); | |
934 } | |
935 } | |
936 rez = XvMCCompositeSubpicture(mDisplay, &subpicture, xvimage, 0, 0, | |
937 w,h,x0,y0); | |
938 if(rez != Success){ | |
939 printf("vo_xvmc: composite subpicture failed\n"); | |
940 assert(0); | |
941 } | |
942 } | |
943 | |
944 static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ | |
945 int ox,oy; | |
946 int rez; | |
947 if( verbose > 3) | |
948 printf("vo_xvmc:composite AI44 subpicture (%d,%d - %d,%d)\n",x0,y0,w,h); | |
949 | |
950 for(ox=0; ox<w; ox++){ | |
951 for(oy=0; oy<h; oy++){ | |
952 xvimage->data[oy*xvimage->width+ox] = (src[oy*stride+ox]&0xf0) | (((0-srca[oy*stride+ox])>>4)&0xf); | |
953 } | |
954 } | |
955 rez = XvMCCompositeSubpicture(mDisplay, &subpicture, xvimage, 0, 0, | |
956 w,h,x0,y0); | |
957 if(rez != Success){ | |
958 printf("vo_xvmc: composite subpicture failed\n"); | |
959 assert(0); | |
960 } | |
528 } | 961 } |
529 | 962 |
530 static void draw_osd(void){ | 963 static void draw_osd(void){ |
964 xvmc_render_state_t * osd_rndr; | |
965 int osd_has_changed; | |
966 int have_osd_to_draw; | |
967 int rez; | |
968 | |
969 if(verbose > 3) | |
970 printf("vo_xvmc: draw_osd ,OSD_mode=%d, surface_to_show=%p\n", | |
971 subpicture_mode,p_render_surface_to_show); | |
972 | |
973 if(subpicture_mode == BLEND_SUBPICTURE || | |
974 subpicture_mode == BACKEND_SUBPICTURE ){ | |
975 | |
976 if(!subpicture_alloc) //allocate subpicture when dimensions are known | |
977 OSD_init(); | |
978 if(!subpicture_alloc) | |
979 return;//dimensions still unknown. | |
980 | |
981 osd_has_changed = vo_update_osd(subpicture.width, subpicture.height); | |
982 have_osd_to_draw = vo_osd_check_range_update(0, 0, subpicture.width, | |
983 subpicture.height); | |
984 | |
985 if(!have_osd_to_draw) | |
986 return;//nothing to draw,no subpic, no blend | |
987 | |
988 if(osd_has_changed){ | |
989 //vo_remove_text(subpicture.width, subpicture.height,clear_osd_fnc) | |
990 clear_osd_fnc(0,0,subpicture.width,subpicture.height); | |
991 vo_draw_text(subpicture.width, subpicture.height, draw_osd_fnc); | |
992 } | |
993 XvMCSyncSubpicture(mDisplay,&subpicture);//todo usleeep wait! | |
994 | |
995 if(subpicture_mode == BLEND_SUBPICTURE){ | |
996 osd_rndr = find_free_surface(); | |
997 if(osd_rndr == NULL) | |
998 return;// no free surface to draw OSD in | |
999 | |
1000 rez = XvMCBlendSubpicture2(mDisplay, | |
1001 p_render_surface_to_show->p_surface, osd_rndr->p_surface, | |
1002 &subpicture, | |
1003 0, 0, subpicture.width, subpicture.height, | |
1004 0, 0, image_width, image_height); | |
1005 if(rez!=Success){ | |
1006 printf("vo_xvmc: BlendSubpicture failed rez=%d\n",rez); | |
1007 assert(0); | |
1008 return; | |
1009 } | |
1010 // XvMCFlushSurface(mDisplay,osd_rndr->p_surface);//fixme- should I? | |
1011 | |
1012 //When replaceing the surface with osd one, save the flags too! | |
1013 osd_rndr->picture_structure = p_render_surface_to_show->picture_structure; | |
1014 osd_rndr->display_flags = p_render_surface_to_show->display_flags; | |
1015 //add more if needed osd_rndr-> = p_render_surface_to_show->; | |
1016 | |
1017 p_render_surface_to_show->state &= ~MP_XVMC_STATE_DISPLAY_PENDING; | |
1018 p_render_surface_to_show->state |= MP_XVMC_STATE_OSD_SOURCE; | |
1019 p_render_surface_to_show->p_osd_target_surface_render = osd_rndr; | |
1020 | |
1021 p_render_surface_to_show = osd_rndr; | |
1022 p_render_surface_to_show->state = MP_XVMC_STATE_DISPLAY_PENDING; | |
1023 | |
1024 if(verbose > 3) | |
1025 printf("vo_xvmc:draw_osd: surface_to_show changed to %p\n",osd_rndr); | |
1026 }//endof if(BLEND) | |
1027 if(subpicture_mode == BACKEND_SUBPICTURE){ | |
1028 rez = XvMCBlendSubpicture(mDisplay, | |
1029 p_render_surface_to_show->p_surface, | |
1030 &subpicture, | |
1031 0, 0, subpicture.width, subpicture.height, | |
1032 0, 0, image_width, image_height); | |
1033 | |
1034 } | |
1035 | |
1036 }//if(BLEND||BACKEND) | |
531 } | 1037 } |
532 | 1038 |
533 static void xvmc_sync_surface(XvMCSurface * srf){ | 1039 static void xvmc_sync_surface(XvMCSurface * srf){ |
534 int status,rez; | 1040 int status,rez; |
535 rez = XvMCGetSurfaceStatus(mDisplay,srf,&status); | 1041 rez = XvMCGetSurfaceStatus(mDisplay,srf,&status); |
536 assert(rez==Success); | 1042 assert(rez==Success); |
537 if( status & XVMC_RENDERING ) | 1043 if((status & XVMC_RENDERING) == 0) |
538 XvMCSyncSurface(mDisplay, srf); | 1044 return;//surface is already complete |
539 /* | 1045 if(!busy_wait){ |
540 rez = XvMCFlushSurface(mDisplay, srf); | 1046 rez = XvMCFlushSurface(mDisplay, srf); |
541 assert(rez==Success); | 1047 assert(rez==Success); |
542 | 1048 |
543 do { | 1049 do{ |
544 usleep(1); | 1050 usec_sleep(1000);//1ms (may be 20ms on linux) |
545 printf("waiting...\n"); | 1051 XvMCGetSurfaceStatus(mDisplay,srf,&status); |
546 XvMCGetSurfaceStatus(mDisplay,srf,&status); | 1052 } while (status & XVMC_RENDERING); |
547 } while (status & XVMC_RENDERING); | 1053 return;//done |
548 */ | 1054 } |
1055 | |
1056 XvMCSyncSurface(mDisplay, srf); | |
549 } | 1057 } |
550 | 1058 |
551 static void flip_page(void){ | 1059 static void flip_page(void){ |
552 int rez; | 1060 int rez; |
553 int clipX,clipY,clipW,clipH; | 1061 int clipX,clipY,clipW,clipH; |
1062 int i,cfs; | |
554 | 1063 |
555 clipX = drwX-(vo_panscan_x>>1); | 1064 clipX = drwX-(vo_panscan_x>>1); |
556 clipY = drwY-(vo_panscan_y>>1); | 1065 clipY = drwY-(vo_panscan_y>>1); |
557 clipW = vo_dwidth+vo_panscan_x; | 1066 clipW = vo_dwidth+vo_panscan_x; |
558 clipH = vo_dheight+vo_panscan_y;// | 1067 clipH = vo_dheight+vo_panscan_y; |
559 | 1068 |
560 if( verbose > 3 ) | 1069 if( verbose > 3 ) |
561 printf("vo_xvmc: flip_page show(rndr=%p)\n\n",p_render_surface_to_show); | 1070 printf("vo_xvmc: flip_page show(rndr=%p)\n\n",p_render_surface_to_show); |
562 | 1071 |
563 if(p_render_surface_to_show == NULL) return; | 1072 if(p_render_surface_to_show == NULL) return; |
564 assert( p_render_surface_to_show->magic == MP_XVMC_RENDER_MAGIC ); | 1073 assert( p_render_surface_to_show->magic == MP_XVMC_RENDER_MAGIC ); |
565 //fixme assert( p_render_surface_to_show != p_render_surface_visible); | 1074 //fixme assert( p_render_surface_to_show != p_render_surface_visible); |
566 | 1075 |
1076 if(use_queue){ | |
1077 // fill the queue until only n free surfaces remain | |
1078 // after that start displaying | |
1079 cfs = count_free_surfaces(); | |
1080 show_queue[free_element++] = p_render_surface_to_show; | |
1081 if(cfs > 3){//well have 3 free surfaces after add queue | |
1082 if(free_element > 1)//a little voodoo magic | |
1083 xvmc_sync_surface(show_queue[0]->p_surface); | |
1084 return; | |
1085 } | |
1086 p_render_surface_to_show=show_queue[0]; | |
1087 if(verbose > 4) | |
1088 printf("vo_xvmc: flip_queue free_element=%d\n",free_element); | |
1089 free_element--; | |
1090 for(i=0; i<free_element; i++){ | |
1091 show_queue[i] = show_queue[i+1]; | |
1092 } | |
1093 show_queue[free_element] = NULL; | |
1094 } | |
1095 | |
567 // make sure the rendering is done | 1096 // make sure the rendering is done |
568 xvmc_sync_surface(p_render_surface_to_show->p_surface); | 1097 xvmc_sync_surface(p_render_surface_to_show->p_surface); |
569 | 1098 |
570 //the visible surface won't be displayed anymore, mark it as free | 1099 //the visible surface won't be displayed anymore, mark it as free |
571 if( p_render_surface_visible!=NULL ) | 1100 if(p_render_surface_visible != NULL) |
572 p_render_surface_visible->state &= ~MP_XVMC_STATE_DISPLAY_PENDING; | 1101 p_render_surface_visible->state &= ~MP_XVMC_STATE_DISPLAY_PENDING; |
573 | 1102 |
574 //!!fixme assert(p_render_surface_to_show->state & MP_XVMC_STATE_DISPLAY_PENDING); | 1103 //!!fixme assert(p_render_surface_to_show->state & MP_XVMC_STATE_DISPLAY_PENDING); |
575 | 1104 |
576 // show it | 1105 //show it, displaying is always vsynced, so skip it for benchmark |
577 // if(benchmark) | 1106 if(!benchmark){ |
578 rez=XvMCPutSurface(mDisplay, p_render_surface_to_show->p_surface, vo_window, | 1107 rez = XvMCPutSurface(mDisplay, p_render_surface_to_show->p_surface, |
579 0, 0, image_width, image_height, | 1108 vo_window, |
580 clipX, clipY, clipW, clipH, | 1109 0, 0, image_width, image_height, |
581 3);//p_render_surface_to_show->display_flags); | 1110 clipX, clipY, clipW, clipH, |
582 | 1111 3);//p_render_surface_to_show->display_flags); |
583 assert(rez==Success); | 1112 if(rez != Success){ |
584 | 1113 printf("vo_xvmc: PutSurface failer, critical error!\n"); |
1114 assert(0); | |
1115 } | |
1116 } | |
1117 | |
585 p_render_surface_visible = p_render_surface_to_show; | 1118 p_render_surface_visible = p_render_surface_to_show; |
586 p_render_surface_to_show = NULL; | 1119 p_render_surface_to_show = NULL; |
587 } | 1120 } |
588 | 1121 |
589 static void check_events(void){ | 1122 static void check_events(void){ |
593 | 1126 |
594 int e=vo_x11_check_events(mDisplay); | 1127 int e=vo_x11_check_events(mDisplay); |
595 if(e&VO_EVENT_RESIZE) | 1128 if(e&VO_EVENT_RESIZE) |
596 { | 1129 { |
597 e |= VO_EVENT_EXPOSE; | 1130 e |= VO_EVENT_EXPOSE; |
598 | 1131 |
599 XGetGeometry( mDisplay,vo_window,&mRoot,&drwX,&drwY,&vo_dwidth,&vo_dheight, | 1132 XGetGeometry( mDisplay,vo_window,&mRoot,&drwX,&drwY,&vo_dwidth,&vo_dheight, |
600 &drwBorderWidth,&drwDepth ); | 1133 &drwBorderWidth,&drwDepth ); |
601 drwX = drwY = 0; | 1134 drwX = drwY = 0; |
602 mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY, | 1135 mp_msg(MSGT_VO,MSGL_V, "[xvmc] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY, |
603 vo_dwidth,vo_dheight ); | 1136 vo_dwidth,vo_dheight ); |
613 mp_msg(MSGT_VO,MSGL_V, "[xvmc-fs] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight ); | 1146 mp_msg(MSGT_VO,MSGL_V, "[xvmc-fs] dx: %d dy: %d dw: %d dh: %d\n",drwX,drwY,vo_dwidth,vo_dheight ); |
614 } | 1147 } |
615 } | 1148 } |
616 if ( e & VO_EVENT_EXPOSE ) | 1149 if ( e & VO_EVENT_EXPOSE ) |
617 { | 1150 { |
618 mDrawColorKey(drwX,drwY,vo_dwidth,vo_dheight); | 1151 mDrawColorKey(drwX,drwY,vo_dwidth,vo_dheight); |
619 if(p_render_surface_visible != NULL) | 1152 if(p_render_surface_visible != NULL) |
620 XvMCPutSurface(mDisplay, p_render_surface_visible->p_surface,vo_window, | 1153 XvMCPutSurface(mDisplay, p_render_surface_visible->p_surface,vo_window, |
621 0, 0, image_width, image_height, | 1154 0, 0, image_width, image_height, |
622 drwX,drwY,vo_dwidth,vo_dheight, | 1155 drwX,drwY,vo_dwidth,vo_dheight, |
623 3);//,p_render_surface_visible->display_flags);!! | 1156 3);//,p_render_surface_visible->display_flags);!! |
624 } | 1157 } |
625 } | 1158 } |
626 | 1159 |
627 static void xvmc_free(void){ | 1160 static void xvmc_free(void){ |
628 int i; | 1161 int i; |
1162 if( subpicture_alloc ){ | |
1163 | |
1164 XvMCDestroySubpicture(mDisplay,&subpicture); | |
1165 deallocate_xvimage(); | |
1166 | |
1167 subpicture_alloc = 0; | |
1168 | |
1169 if(verbose > 3) | |
1170 printf("vo_xvmc: subpicture destroyed\n"); | |
1171 } | |
629 | 1172 |
630 if( number_of_surfaces ){ | 1173 if( number_of_surfaces ){ |
1174 | |
631 XvMCDestroyMacroBlocks(mDisplay,&mv_blocks); | 1175 XvMCDestroyMacroBlocks(mDisplay,&mv_blocks); |
632 XvMCDestroyBlocks(mDisplay,&data_blocks); | 1176 XvMCDestroyBlocks(mDisplay,&data_blocks); |
1177 | |
633 for(i=0; i<number_of_surfaces; i++) | 1178 for(i=0; i<number_of_surfaces; i++) |
634 { | 1179 { |
635 XvMCHideSurface(mDisplay,&surface_array[i]);//it doesn't hurt, I hope | 1180 XvMCHideSurface(mDisplay,&surface_array[i]);//it doesn't hurt, I hope |
636 XvMCDestroySurface(mDisplay,&surface_array[i]); | 1181 XvMCDestroySurface(mDisplay,&surface_array[i]); |
637 | 1182 |
638 if( (surface_render[i].state != 0) && | 1183 if( (surface_render[i].state != 0) && |
639 (p_render_surface_visible != &surface_render[i]) ) | 1184 (p_render_surface_visible != &surface_render[i]) ) |
640 printf("vo_xvmc::uninit surface_render[%d].status=%d\n",i, | 1185 printf("vo_xvmc::uninit surface_render[%d].status=%d\n",i, |
641 surface_render[i].state); | 1186 surface_render[i].state); |
642 } | 1187 } |
643 | 1188 |
644 free(surface_render);surface_render=NULL; | 1189 free(surface_render);surface_render=NULL; |
645 | 1190 |
646 XvMCDestroyContext(mDisplay,&ctx); | 1191 XvMCDestroyContext(mDisplay,&ctx); |
647 if( verbose > 3) printf("vo_xvmc: Context sucessfuly freed\n"); | |
648 number_of_surfaces = 0; | 1192 number_of_surfaces = 0; |
649 } | 1193 |
1194 if(verbose > 3) printf("vo_xvmc: Context sucessfuly freed\n"); | |
1195 } | |
1196 | |
1197 | |
650 if( xv_port !=0 ){ | 1198 if( xv_port !=0 ){ |
651 XvUngrabPort(mDisplay,xv_port,CurrentTime); | 1199 XvUngrabPort(mDisplay,xv_port,CurrentTime); |
652 xv_port = 0; | 1200 xv_port = 0; |
653 if( verbose > 3) printf("vo_xvmc: xv_port sucessfuly ungrabed\n"); | 1201 if(verbose > 3) printf("vo_xvmc: xv_port sucessfuly ungrabed\n"); |
654 } | 1202 } |
655 } | 1203 } |
656 | 1204 |
657 static void uninit(void){ | 1205 static void uninit(void){ |
658 if( verbose > 3 ) printf("vo_xvmc: uninit called\n"); | 1206 if( verbose > 3 ) printf("vo_xvmc: uninit called\n"); |
673 | 1221 |
674 if(!IMGFMT_IS_XVMC(format)) return 0;// no caps supported | 1222 if(!IMGFMT_IS_XVMC(format)) return 0;// no caps supported |
675 mode_id = xvmc_find_surface_by_format(format, 16, 16, &qsurface_info, 1);//true=1 - quering | 1223 mode_id = xvmc_find_surface_by_format(format, 16, 16, &qsurface_info, 1);//true=1 - quering |
676 | 1224 |
677 if( mode_id == 0 ) return 0; | 1225 if( mode_id == 0 ) return 0; |
678 | 1226 |
679 flags = VFCAP_CSP_SUPPORTED | | 1227 flags = VFCAP_CSP_SUPPORTED | |
680 VFCAP_CSP_SUPPORTED_BY_HW | | 1228 VFCAP_CSP_SUPPORTED_BY_HW | |
681 VFCAP_ACCEPT_STRIDE; | 1229 VFCAP_ACCEPT_STRIDE; |
682 | 1230 |
683 // if(surfce_info.subpicture) | 1231 if( (qsurface_info.subpicture_max_width != 0) && |
684 // flags|=VFCAP_OSD; | 1232 (qsurface_info.subpicture_max_height != 0) ) |
1233 flags|=VFCAP_OSD; | |
685 return flags; | 1234 return flags; |
686 } | 1235 } |
687 | 1236 |
688 | 1237 |
689 static uint32_t draw_slice(uint8_t *image[], int stride[], | 1238 static uint32_t draw_slice(uint8_t *image[], int stride[], |
695 printf("vo_xvmc: draw_slice y=%d\n",y); | 1244 printf("vo_xvmc: draw_slice y=%d\n",y); |
696 | 1245 |
697 rndr = (xvmc_render_state_t*)image[2];//this is copy of priv-ate | 1246 rndr = (xvmc_render_state_t*)image[2];//this is copy of priv-ate |
698 assert( rndr != NULL ); | 1247 assert( rndr != NULL ); |
699 assert( rndr->magic == MP_XVMC_RENDER_MAGIC ); | 1248 assert( rndr->magic == MP_XVMC_RENDER_MAGIC ); |
700 | |
701 if(rndr->p_past_surface != NULL) | |
702 xvmc_sync_surface(rndr->p_past_surface); | |
703 if(rndr->p_future_surface != NULL) | |
704 xvmc_sync_surface(rndr->p_future_surface); | |
705 | 1249 |
706 rez = XvMCRenderSurface(mDisplay,&ctx,rndr->picture_structure, | 1250 rez = XvMCRenderSurface(mDisplay,&ctx,rndr->picture_structure, |
707 rndr->p_surface, | 1251 rndr->p_surface, |
708 rndr->p_past_surface, | 1252 rndr->p_past_surface, |
709 rndr->p_future_surface, | 1253 rndr->p_future_surface, |
710 rndr->flags, | 1254 rndr->flags, |
711 rndr->filled_mv_blocks_num,rndr->start_mv_blocks_num, | 1255 rndr->filled_mv_blocks_num,rndr->start_mv_blocks_num, |
712 &mv_blocks,&data_blocks); | 1256 &mv_blocks,&data_blocks); |
713 #if 1 | 1257 #if 1 |
714 if(rez!=Success) | 1258 if(rez != Success) |
715 { | 1259 { |
716 int i; | 1260 int i; |
717 printf("vo_xvmc::slice: RenderSirface returned %d\n",rez); | 1261 printf("vo_xvmc::slice: RenderSirface returned %d\n",rez); |
718 | 1262 |
719 printf("vo_xvmc::slice: pict=%d,flags=%x,start_blocks=%d,num_blocks=%d\n", | 1263 printf("vo_xvmc::slice: pict=%d,flags=%x,start_blocks=%d,num_blocks=%d\n", |
720 rndr->picture_structure,rndr->flags,rndr->start_mv_blocks_num, | 1264 rndr->picture_structure,rndr->flags,rndr->start_mv_blocks_num, |
721 rndr->filled_mv_blocks_num); | 1265 rndr->filled_mv_blocks_num); |
722 printf("vo_xvmc::slice: this_surf=%p, past_surf=%p, future_surf=%p\n", | 1266 printf("vo_xvmc::slice: this_surf=%p, past_surf=%p, future_surf=%p\n", |
723 rndr->p_surface,rndr->p_past_surface,rndr->p_future_surface); | 1267 rndr->p_surface,rndr->p_past_surface,rndr->p_future_surface); |
724 | 1268 |
725 for(i=0;i<rndr->filled_mv_blocks_num;i++){ | 1269 for(i=0; i<rndr->filled_mv_blocks_num; i++){ |
726 XvMCMacroBlock* testblock; | 1270 XvMCMacroBlock* testblock; |
727 testblock=&mv_blocks.macro_blocks[i]; | 1271 testblock = &mv_blocks.macro_blocks[i]; |
728 | 1272 |
729 printf("vo_xvmc::slice: mv_block - x=%d,y=%d,mb_type=0x%x,mv_type=0x%x,mv_field_select=%d\n", | 1273 printf("vo_xvmc::slice: mv_block - x=%d,y=%d,mb_type=0x%x,mv_type=0x%x,mv_field_select=%d\n", |
730 testblock->x,testblock->y,testblock->macroblock_type, | 1274 testblock->x,testblock->y,testblock->macroblock_type, |
731 testblock->motion_type,testblock->motion_vertical_field_select); | 1275 testblock->motion_type,testblock->motion_vertical_field_select); |
732 printf("vo_xvmc::slice: dct_type=%d,data_index=0x%x,cbp=%d,pad0=%d\n", | 1276 printf("vo_xvmc::slice: dct_type=%d,data_index=0x%x,cbp=%d,pad0=%d\n", |
733 testblock->dct_type,testblock->index,testblock->coded_block_pattern, | 1277 testblock->dct_type,testblock->index,testblock->coded_block_pattern, |
734 testblock->pad0); | 1278 testblock->pad0); |
735 printf("vo_xvmc::slice: PMV[0][0][0/1]=(%d,%d)\n", | 1279 printf("vo_xvmc::slice: PMV[0][0][0/1]=(%d,%d)\n", |
736 testblock->PMV[0][0][0],testblock->PMV[0][0][1]); | 1280 testblock->PMV[0][0][0],testblock->PMV[0][0][1]); |
737 | |
738 } | 1281 } |
739 | |
740 } | 1282 } |
741 #endif | 1283 #endif |
742 assert(rez==Success); | 1284 assert(rez==Success); |
743 if(verbose > 3 ) printf("vo_xvmc: flush surface\n"); | 1285 if(verbose > 3 ) printf("vo_xvmc: flush surface\n"); |
744 rez = XvMCFlushSurface(mDisplay, rndr->p_surface); | 1286 rez = XvMCFlushSurface(mDisplay, rndr->p_surface); |
751 rndr->next_free_data_block_num = 0; | 1293 rndr->next_free_data_block_num = 0; |
752 | 1294 |
753 return VO_TRUE; | 1295 return VO_TRUE; |
754 } | 1296 } |
755 | 1297 |
756 | 1298 //XvMCHide hides the surface on next retrace, so |
757 static inline int find_free_surface(){ | 1299 //check if the surface is not still displaying |
758 int i,j,t; | 1300 static void check_osd_source(xvmc_render_state_t * src_rndr){ |
1301 xvmc_render_state_t * osd_rndr; | |
759 int stat; | 1302 int stat; |
760 | 1303 //If this is source surface, check does the OSD rendering is compleate |
761 j=-1; | 1304 if(src_rndr->state & MP_XVMC_STATE_OSD_SOURCE){ |
1305 if(verbose > 3) | |
1306 printf("vo_xvmc: OSD surface=%p quering\n",src_rndr); | |
1307 osd_rndr = src_rndr->p_osd_target_surface_render; | |
1308 XvMCGetSurfaceStatus(mDisplay, osd_rndr->p_surface, &stat); | |
1309 if(!(stat & XVMC_RENDERING)) | |
1310 src_rndr->state &= ~MP_XVMC_STATE_OSD_SOURCE; | |
1311 } | |
1312 } | |
1313 static int count_free_surfaces(){ | |
1314 int i,num; | |
1315 num=0; | |
762 for(i=0; i<number_of_surfaces; i++){ | 1316 for(i=0; i<number_of_surfaces; i++){ |
763 // printf("vo_xvmc: surface[%d].state=%d ( surf=%p)\n",i, | 1317 check_osd_source(&surface_render[i]); |
764 // surface_render[i].state, surface_render[i].p_surface); | 1318 if(surface_render[i].state == 0) |
1319 num++; | |
1320 } | |
1321 return num; | |
1322 } | |
1323 | |
1324 static xvmc_render_state_t * find_free_surface(){ | |
1325 int i,t; | |
1326 int stat; | |
1327 xvmc_render_state_t * visible_rndr; | |
1328 | |
1329 visible_rndr = NULL; | |
1330 for(i=0; i<number_of_surfaces; i++){ | |
1331 | |
1332 check_osd_source(&surface_render[i]); | |
765 if( surface_render[i].state == 0){ | 1333 if( surface_render[i].state == 0){ |
766 XvMCGetSurfaceStatus(mDisplay, surface_render[i].p_surface,&stat); | 1334 XvMCGetSurfaceStatus(mDisplay, surface_render[i].p_surface,&stat); |
767 if( (stat & XVMC_DISPLAYING) == 0 ) return i; | 1335 if( (stat & XVMC_DISPLAYING) == 0 ) |
768 j=i; | 1336 return &surface_render[i]; |
769 } | 1337 visible_rndr = &surface_render[i];// remember it, use as last resort |
770 } | 1338 } |
771 if(j>=0){//all surfaces are busy, but there is one that will be free | 1339 } |
1340 | |
1341 //all surfaces are busy, but there is one that will be free | |
772 //on next monitor retrace, we just have to wait | 1342 //on next monitor retrace, we just have to wait |
773 for(t=0;t<1000;t++){ | 1343 if(visible_rndr != NULL){ |
774 // usleep(10); //!!! | 1344 printf("vo_xvmc: waiting retrace\n"); |
775 printf("vo_xvmc: waiting retrace\n"); | 1345 for(t=0;t<1000;t++){ |
776 XvMCGetSurfaceStatus(mDisplay, surface_render[j].p_surface,&stat); | 1346 usec_sleep(1000);//1ms |
777 if( (stat & XVMC_DISPLAYING) == 0 ) return j; | 1347 XvMCGetSurfaceStatus(mDisplay, visible_rndr->p_surface,&stat); |
778 } | 1348 if( (stat & XVMC_DISPLAYING) == 0 ) |
779 assert(0);//10 seconds wait for surface to get free! | 1349 return visible_rndr; |
780 exit(1); | 1350 } |
781 } | 1351 } |
782 return -1; | 1352 //todo remove when stable |
1353 printf("vo_xvmc: no free surfaces, this should not happen in g1\n"); | |
1354 for(i=0;i<number_of_surfaces;i++) | |
1355 printf("vo_xvmc: surface[%d].state=%d\n",i,surface_render[i].state); | |
1356 return NULL; | |
783 } | 1357 } |
784 | 1358 |
785 static uint32_t get_image(mp_image_t *mpi){ | 1359 static uint32_t get_image(mp_image_t *mpi){ |
786 int getsrf; | 1360 xvmc_render_state_t * rndr; |
787 | 1361 |
788 | 1362 rndr = find_free_surface(); |
789 getsrf=find_free_surface(); | 1363 |
790 if(getsrf<0){ | 1364 if(rndr == NULL){ |
791 int i; | 1365 printf("vo_xvmc: get_image failed\n"); |
792 printf("vo_xvmc: no free surfaces, this should not happen in g1\n"); | |
793 for(i=0;i<number_of_surfaces;i++) | |
794 printf("vo_xvmc: surface[%d].state=%d\n",i,surface_render[i].state); | |
795 return VO_FALSE; | 1366 return VO_FALSE; |
796 } | 1367 } |
797 | 1368 |
798 assert(surface_render[getsrf].start_mv_blocks_num == 0); | 1369 assert(rndr->start_mv_blocks_num == 0); |
799 assert(surface_render[getsrf].filled_mv_blocks_num == 0); | 1370 assert(rndr->filled_mv_blocks_num == 0); |
800 assert(surface_render[getsrf].next_free_data_block_num == 0); | 1371 assert(rndr->next_free_data_block_num == 0); |
801 | 1372 |
802 mpi->flags |= MP_IMGFLAG_DIRECT; | 1373 mpi->flags |= MP_IMGFLAG_DIRECT; |
803 //keep strides 0 to avoid field manipulations | 1374 //keep strides 0 to avoid field manipulations |
804 mpi->stride[0] = 0; | 1375 mpi->stride[0] = 0; |
805 mpi->stride[1] = 0; | 1376 mpi->stride[1] = 0; |
808 // these are shared!! so watch out | 1379 // these are shared!! so watch out |
809 // do call RenderSurface before overwriting | 1380 // do call RenderSurface before overwriting |
810 mpi->planes[0] = (char*)data_blocks.blocks; | 1381 mpi->planes[0] = (char*)data_blocks.blocks; |
811 mpi->planes[1] = (char*)mv_blocks.macro_blocks; | 1382 mpi->planes[1] = (char*)mv_blocks.macro_blocks; |
812 mpi->priv = | 1383 mpi->priv = |
813 mpi->planes[2] = (char*)&surface_render[getsrf]; | 1384 mpi->planes[2] = (char*)rndr; |
814 | 1385 |
815 surface_render[getsrf].picture_structure = 0; | 1386 rndr->picture_structure = 0; |
816 surface_render[getsrf].flags = 0; | 1387 rndr->flags = 0; |
817 surface_render[getsrf].state = 0; | 1388 rndr->state = 0; |
818 surface_render[getsrf].start_mv_blocks_num = 0; | 1389 rndr->start_mv_blocks_num = 0; |
819 surface_render[getsrf].filled_mv_blocks_num = 0; | 1390 rndr->filled_mv_blocks_num = 0; |
820 surface_render[getsrf].next_free_data_block_num = 0; | 1391 rndr->next_free_data_block_num = 0; |
821 | 1392 |
822 if( verbose > 3 ) | 1393 if( verbose > 3 ) |
823 printf("vo_xvmc: get_image: .rndr=%p surface[%d]=%p \n", | 1394 printf("vo_xvmc: get_image: rndr=%p (surface=%p) \n", |
824 mpi->priv,getsrf,surface_render[getsrf].p_surface); | 1395 rndr,rndr->p_surface); |
825 return VO_TRUE; | 1396 return VO_TRUE; |
826 } | 1397 } |
827 | 1398 |
828 static uint32_t control(uint32_t request, void *data, ... ) | 1399 static uint32_t control(uint32_t request, void *data, ... ) |
829 { | 1400 { |
840 case VOCTRL_FULLSCREEN: | 1411 case VOCTRL_FULLSCREEN: |
841 vo_x11_fullscreen(); | 1412 vo_x11_fullscreen(); |
842 case VOCTRL_GET_PANSCAN: | 1413 case VOCTRL_GET_PANSCAN: |
843 if ( !vo_config_count || !vo_fs ) return VO_FALSE; | 1414 if ( !vo_config_count || !vo_fs ) return VO_FALSE; |
844 return VO_TRUE; | 1415 return VO_TRUE; |
845 // indended, fallthrough to update panscan on fullscreen/windowed switch | 1416 // indended, fallthrough to update panscan on fullscreen/windowed switch |
846 case VOCTRL_SET_PANSCAN: | 1417 case VOCTRL_SET_PANSCAN: |
847 if ( ( vo_fs && ( vo_panscan != vo_panscan_amount ) ) || ( !vo_fs && vo_panscan_amount ) ) | 1418 if ( ( vo_fs && ( vo_panscan != vo_panscan_amount ) ) || ( !vo_fs && vo_panscan_amount ) ) |
848 { | 1419 { |
849 int old_y = vo_panscan_y; | 1420 int old_y = vo_panscan_y; |
850 panscan_calc(); | 1421 panscan_calc(); |
851 | 1422 |
852 if(old_y != vo_panscan_y) | 1423 if(old_y != vo_panscan_y) |
853 { | 1424 { |
854 XClearWindow(mDisplay, vo_window); | 1425 XClearWindow(mDisplay, vo_window); |
855 XFlush(mDisplay); | 1426 XFlush(mDisplay); |
856 } | 1427 } |
859 | 1430 |
860 case VOCTRL_SET_EQUALIZER: | 1431 case VOCTRL_SET_EQUALIZER: |
861 { | 1432 { |
862 va_list ap; | 1433 va_list ap; |
863 int value; | 1434 int value; |
864 | 1435 |
865 va_start(ap, data); | 1436 va_start(ap, data); |
866 value = va_arg(ap, int); | 1437 value = va_arg(ap, int); |
867 va_end(ap); | 1438 va_end(ap); |
868 | 1439 |
869 return(vo_xv_set_eq(xv_port, data, value)); | 1440 return(vo_xv_set_eq(xv_port, data, value)); |
870 } | 1441 } |
871 | 1442 |
872 case VOCTRL_GET_EQUALIZER: | 1443 case VOCTRL_GET_EQUALIZER: |
873 { | 1444 { |
874 va_list ap; | 1445 va_list ap; |
875 int *value; | 1446 int *value; |
876 | 1447 |
877 va_start(ap, data); | 1448 va_start(ap, data); |
878 value = va_arg(ap, int*); | 1449 value = va_arg(ap, int*); |
879 va_end(ap); | 1450 va_end(ap); |
880 | 1451 |
881 return(vo_xv_get_eq(xv_port, data, value)); | 1452 return(vo_xv_get_eq(xv_port, data, value)); |
882 } | 1453 } |
883 } | 1454 } |
884 return VO_NOTIMPL; | 1455 return VO_NOTIMPL; |
885 } | 1456 } |
886 |