Mercurial > mplayer.hg
annotate libvo/vo_fsdga.c @ 2613:156efe748b3d
new A-V sync correction and fps conversion stuff
author | arpi |
---|---|
date | Thu, 01 Nov 2001 21:47:28 +0000 |
parents | d40f2b686846 |
children | ae79207a3055 |
rev | line source |
---|---|
38 | 1 #define DISP |
2 | |
3 /* | |
4 * video_out_dga.c, X11 interface | |
5 * | |
6 * | |
7 * Copyright ( C ) 2001, Andreas Ackermann. All Rights Reserved. | |
8 * | |
9 * <acki@acki-netz.de> | |
10 * | |
11 * note well: | |
12 * | |
13 * o this is alpha | |
14 * o covers only common video card formats | |
15 * o works only on intel architectures | |
16 * | |
17 */ | |
18 | |
19 | |
20 | |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
23 #include <string.h> | |
24 | |
354 | 25 //#include "fastmemcpy.h" |
38 | 26 |
27 #include "linux/keycodes.h" | |
28 #include "config.h" | |
29 #include "video_out.h" | |
30 #include "video_out_internal.h" | |
31 #include "yuv2rgb.h" | |
32 | |
33 LIBVO_EXTERN( fsdga ) | |
34 | |
35 #include <X11/Xlib.h> | |
36 #include <X11/extensions/xf86dga.h> | |
37 | |
38 #include "x11_common.h" | |
39 | |
40 static vo_info_t vo_info = | |
41 { | |
42 "FullScreen DGA ( Direct Graphic Access )", | |
43 "fsdga", | |
44 "A'rpi/ESP-team & Andreas Ackermann <acki@acki-netz.de>", | |
45 "" | |
46 }; | |
47 | |
48 static int vo_dga_width; // bytes per line in framebuffer | |
49 static int vo_dga_vp_width; // visible pixels per line in framebuffer | |
50 static int vo_dga_vp_height; // visible lines in framebuffer | |
51 static int vo_dga_is_running = 0; | |
52 static int vo_dga_src_width; // width of video in pixels | |
53 static int vo_dga_src_height; // height of video in pixels | |
54 static int vo_dga_bpp; // bytes per pixel in framebuffer | |
55 static int vo_dga_src_offset=0; // offset in src | |
56 static int vo_dga_vp_offset=0; // offset in dest | |
57 static int vo_dga_bytes_per_line; // longwords per line to copy | |
58 static int vo_dga_src_skip; // bytes to skip after copying one line | |
59 // (not supported yet) in src | |
60 static int vo_dga_vp_skip; // dto. for dest | |
61 static int vo_dga_lines; // num of lines to copy | |
62 static int vo_dga_src_format; | |
63 | |
64 static unsigned char *vo_dga_base; | |
65 static Display *vo_dga_dpy; | |
66 | |
67 | |
68 #if defined (HAVE_SSE) || defined (HAVE_3DNOW) | |
69 #define movntq "movntq" // use this for processors that have SSE or 3Dnow | |
70 #else | |
71 #define movntq "movq" // for MMX-only processors | |
72 #endif | |
73 | |
74 | |
75 #define rep_movsl(dest, src, numwords, d_add, count) \ | |
76 __asm__ __volatile__( \ | |
77 " \ | |
78 xfer: \n\t\ | |
79 movl %%edx, %%ecx \n\t \ | |
80 cld\n\t \ | |
81 rep\n\t \ | |
82 movsl \n\t\ | |
83 add %%eax, %%edi \n\t\ | |
84 dec %%ebx \n\t\ | |
85 jnz xfer \n\t\ | |
86 " \ | |
87 : \ | |
88 : "a" (d_add), "b" (count), "S" (src), "D" (dest), "d" (numwords) \ | |
89 : "memory" ) | |
90 | |
91 #if 0 | |
92 : "S" (src), "D" (dest), "c" (numwords) \ | |
93 movq (%%eax), %%mm0 \n\t \ | |
94 add $64, %%edx \n\t \ | |
95 movq 8(%%eax), %%mm1 \n\t \ | |
96 add $64, %%eax \n\t \ | |
97 movq -48(%%eax), %%mm2 \n\t \ | |
98 movq %%mm0, -64(%%edx) \n\t \ | |
99 movq -40(%%eax), %%mm3 \n\t \ | |
100 movq %%mm1, -56(%%edx) \n\t \ | |
101 movq -32(%%eax), %%mm4 \n\t \ | |
102 movq %%mm2, -48(%%edx) \n\t \ | |
103 movq -24(%%eax), %%mm5 \n\t \ | |
104 movq %%mm3, -40(%%edx) \n\t \ | |
105 movq -16(%%eax), %%mm6 \n\t \ | |
106 movq %%mm4, -32(%%edx) \n\t \ | |
107 movq -8(%%eax), %%mm7 \n\t \ | |
108 movq %%mm5, -24(%%edx) \n\t \ | |
109 movq %%mm6, -16(%%edx) \n\t \ | |
110 dec %%ecx \n\t \ | |
111 movq %%mm7, -8(%%edx) \n\t \ | |
112 jnz xfer \n\t \ | |
113 | |
114 #endif | |
115 | |
116 #define mmx_movsl(dest, src, numwords) \ | |
117 __asm__ __volatile__( \ | |
118 " \ | |
119 \n\t \ | |
120 xfer: \n\t \ | |
121 movq (%%eax), %%mm0 \n\t \ | |
122 add $64, %%edx \n\t \ | |
123 movq 8(%%eax), %%mm1 \n\t \ | |
124 add $64, %%eax \n\t \ | |
125 movq -48(%%eax), %%mm2 \n\t \ | |
126 movq %%mm0, -64(%%edx) \n\t \ | |
127 movq -40(%%eax), %%mm3 \n\t \ | |
128 movq %%mm1, -56(%%edx) \n\t \ | |
129 movq -32(%%eax), %%mm4 \n\t \ | |
130 movq %%mm2, -48(%%edx) \n\t \ | |
131 movq -24(%%eax), %%mm5 \n\t \ | |
132 movq %%mm3, -40(%%edx) \n\t \ | |
133 movq -16(%%eax), %%mm6 \n\t \ | |
134 movq %%mm4, -32(%%edx) \n\t \ | |
135 movq -8(%%eax), %%mm7 \n\t \ | |
136 movq %%mm5, -24(%%edx) \n\t \ | |
137 movq %%mm6, -16(%%edx) \n\t \ | |
138 dec %%ecx \n\t \ | |
139 movq %%mm7, -8(%%edx) \n\t \ | |
140 jnz xfer \n\t \ | |
141 \ | |
142 " \ | |
143 : \ | |
144 : "a" (src), "d" (dest), "c" (numwords) \ | |
145 : "memory" ) | |
146 | |
147 // src <= eax | |
148 // dst <= edx | |
149 // num <= ecx | |
150 | |
151 static uint32_t draw_frame( uint8_t *src[] ){ | |
152 | |
153 int vp_skip = vo_dga_vp_skip; | |
154 int lpl = vo_dga_bytes_per_line >> 2; | |
155 int numlines = vo_dga_lines; | |
156 | |
157 char *s, *d; | |
158 | |
159 if( vo_dga_src_format==IMGFMT_YV12 ){ | |
160 // We'll never reach this point, because YV12 codecs always calls draw_slice | |
161 printf("vo_dga: draw_frame() doesn't support IMGFMT_YV12 (yet?)\n"); | |
162 }else{ | |
163 s = *src; | |
164 d = (&((char *)vo_dga_base)[vo_dga_vp_offset]); | |
165 rep_movsl(d, s, lpl, vo_dga_vp_skip, numlines ); | |
166 } | |
167 | |
168 return 0; | |
169 } | |
170 | |
171 static void check_events(void) | |
172 { | |
173 int e=vo_x11_check_events(vo_dga_dpy); | |
174 } | |
175 | |
1501
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
612
diff
changeset
|
176 static void draw_osd(void) |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
612
diff
changeset
|
177 { |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
612
diff
changeset
|
178 } |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
612
diff
changeset
|
179 |
38 | 180 static void flip_page( void ){ |
181 // printf("vo_dga: In flippage\n"); | |
182 } | |
183 | |
184 static unsigned int pix_buf_y[4][2048]; | |
185 static unsigned int pix_buf_uv[2][2048*2]; | |
186 static int dga_srcypos=0; | |
187 static int dga_ypos=0; | |
188 static int dga_last_ypos=-1; | |
189 static unsigned int dga_xinc,dga_yinc,dga_xinc2; | |
190 | |
191 static unsigned char clip_table[768]; | |
192 | |
193 static int yuvtab_2568[256]; | |
194 static int yuvtab_3343[256]; | |
195 static int yuvtab_0c92[256]; | |
196 static int yuvtab_1a1e[256]; | |
197 static int yuvtab_40cf[256]; | |
198 | |
199 | |
200 static uint32_t draw_slice( uint8_t *srcptr[],int stride[], | |
201 int w,int h,int x,int y ) | |
202 { | |
203 | |
204 if(y==0){ | |
205 dga_srcypos=-2*dga_yinc; | |
206 dga_ypos=-2; | |
207 dga_last_ypos=-2; | |
208 } // reset counters | |
209 | |
210 while(1){ | |
211 unsigned char *dest=vo_dga_base+(vo_dga_width * dga_ypos)*vo_dga_bpp; | |
212 int y0=2+(dga_srcypos>>16); | |
213 int y1=1+(dga_srcypos>>17); | |
214 int yalpha=(dga_srcypos&0xFFFF)>>8; | |
215 int yalpha1=yalpha^255; | |
216 int uvalpha=((dga_srcypos>>1)&0xFFFF)>>8; | |
217 int uvalpha1=uvalpha^255; | |
218 unsigned int *buf0=pix_buf_y[y0&3]; | |
219 unsigned int *buf1=pix_buf_y[((y0+1)&3)]; | |
220 unsigned int *uvbuf0=pix_buf_uv[y1&1]; | |
221 unsigned int *uvbuf1=pix_buf_uv[(y1&1)^1]; | |
222 int i; | |
223 | |
224 if(y0>=y+h) break; | |
225 | |
226 dga_ypos++; dga_srcypos+=dga_yinc; | |
227 | |
228 if(dga_last_ypos!=y0){ | |
229 unsigned char *src=srcptr[0]+(y0-y)*stride[0]; | |
230 unsigned int xpos=0; | |
231 dga_last_ypos=y0; | |
232 // this loop should be rewritten in MMX assembly!!!! | |
233 for(i=0;i<vo_dga_vp_width;i++){ | |
234 register unsigned int xx=xpos>>8; | |
235 register unsigned int xalpha=xpos&0xFF; | |
236 buf1[i]=(src[xx]*(xalpha^255)+src[xx+1]*xalpha); | |
237 xpos+=dga_xinc; | |
238 } | |
239 if(!(y0&1)){ | |
240 unsigned char *src1=srcptr[1]+(y1-y/2)*stride[1]; | |
241 unsigned char *src2=srcptr[2]+(y1-y/2)*stride[2]; | |
242 xpos=0; | |
243 // this loop should be rewritten in MMX assembly!!!! | |
244 for(i=0;i<vo_dga_vp_width;i++){ | |
245 register unsigned int xx=xpos>>8; | |
246 register unsigned int xalpha=xpos&0xFF; | |
247 uvbuf1[i]=(src1[xx]*(xalpha^255)+src1[xx+1]*xalpha); | |
248 uvbuf1[i+2048]=(src2[xx]*(xalpha^255)+src2[xx+1]*xalpha); | |
249 xpos+=dga_xinc2; | |
250 } | |
251 } | |
252 if(!y0) continue; | |
253 } | |
254 | |
255 // this loop should be rewritten in MMX assembly!!!! | |
256 for(i=0;i<vo_dga_vp_width;i++){ | |
257 // linear interpolation && yuv2rgb in a single step: | |
258 int Y=yuvtab_2568[((buf0[i]*yalpha1+buf1[i]*yalpha)>>16)]; | |
259 int U=((uvbuf0[i]*uvalpha1+uvbuf1[i]*uvalpha)>>16); | |
260 int V=((uvbuf0[i+2048]*uvalpha1+uvbuf1[i+2048]*uvalpha)>>16); | |
261 dest[0]=clip_table[((Y + yuvtab_3343[U]) >>13)]; | |
262 dest[1]=clip_table[((Y + yuvtab_0c92[V] + yuvtab_1a1e[U]) >>13)]; | |
263 dest[2]=clip_table[((Y + yuvtab_40cf[V]) >>13)]; | |
264 dest+=vo_dga_bpp; | |
265 } | |
266 | |
267 } | |
268 | |
269 | |
270 return 0; | |
271 }; | |
272 | |
273 static void Terminate_Display_Process( void ){ | |
274 | |
275 printf("vo_dga: Terminating display process\n"); | |
276 } | |
277 | |
278 static const vo_info_t* get_info( void ) | |
279 { return &vo_info; } | |
280 | |
281 static uint32_t query_format( uint32_t format ) | |
282 { | |
283 printf("vo_dga: query_format\n"); | |
284 | |
285 if( !vo_init() ) return 0; // Can't open X11 | |
612 | 286 printf("Format: %lx\n", (unsigned long) format); |
38 | 287 |
288 if( format==IMGFMT_YV12 ) return 1; | |
289 if( ( format&IMGFMT_BGR_MASK )==IMGFMT_BGR && | |
290 ( format&0xFF )==vo_depthonscreen ) return 1; | |
291 return 0; | |
292 } | |
293 | |
294 | |
295 static void | |
296 uninit(void) | |
297 { | |
298 | |
299 vo_dga_is_running = 0; | |
300 printf("vo_dga: in uninit\n"); | |
301 XUngrabPointer (vo_dga_dpy, CurrentTime); | |
302 XUngrabKeyboard (vo_dga_dpy, CurrentTime); | |
303 XF86DGADirectVideo (vo_dga_dpy, XDefaultScreen(vo_dga_dpy), 0); | |
304 XCloseDisplay(vo_dga_dpy); | |
305 } | |
306 | |
307 | |
308 | |
309 | |
310 static uint32_t init( uint32_t width, uint32_t height, | |
311 uint32_t d_width,uint32_t d_height, | |
312 uint32_t fullscreen,char *title,uint32_t format ) | |
313 { | |
314 | |
315 int bank, ram; | |
316 int x_off, y_off; | |
317 | |
318 if( vo_dga_is_running )return -1; | |
319 | |
320 if( !vo_init() ){ | |
321 printf("vo_dga: vo_init() failed!\n"); | |
322 return 0; | |
323 } | |
324 | |
325 if((vo_dga_dpy = XOpenDisplay(0))==NULL) | |
326 { | |
327 printf ("vo_dga: Can't open display\n"); | |
328 return 1; | |
329 } | |
330 | |
331 XF86DGAGetVideo (vo_dga_dpy, XDefaultScreen(vo_dga_dpy), | |
332 (char **)&vo_dga_base, &vo_dga_width, &bank, &ram); | |
333 XF86DGAGetViewPortSize (vo_dga_dpy, XDefaultScreen (vo_dga_dpy), | |
334 &vo_dga_vp_width, &vo_dga_vp_height); | |
335 | |
336 | |
337 // do some more checkings here ... | |
338 if( format==IMGFMT_YV12 ) | |
339 yuv2rgb_init( vo_depthonscreen, MODE_RGB ); | |
340 | |
341 vo_dga_src_format = format; | |
342 vo_dga_src_width = width; | |
343 vo_dga_src_height = height; | |
344 vo_dga_bpp = (vo_depthonscreen+7) >> 3; | |
345 | |
612 | 346 printf("vo_dga: bytes/line: %d, screen res: %dx%d, depth: %d, base: %p, bpp: %d\n", |
38 | 347 vo_dga_width, vo_dga_vp_width, |
348 vo_dga_vp_height, vo_depthonscreen, vo_dga_base, | |
349 vo_dga_bpp); | |
350 printf("vo_dga: video res: %dx%d\n", vo_dga_src_width, vo_dga_src_height); | |
351 | |
352 if(vo_dga_src_width > vo_dga_vp_width || | |
353 vo_dga_src_height > vo_dga_vp_height){ | |
354 printf("vo_dga: Sorry, video larger than viewport is not yet supported!\n"); | |
355 // ugly, do something nicer in the future ... | |
356 return 1; | |
357 } | |
358 | |
359 x_off = (vo_dga_vp_width - vo_dga_src_width)>>1; | |
360 y_off = (vo_dga_vp_height - vo_dga_src_height)>>1; | |
361 | |
362 vo_dga_bytes_per_line = vo_dga_src_width * vo_dga_bpp; // todo | |
363 vo_dga_lines = vo_dga_src_height; // todo | |
364 | |
365 | |
366 vo_dga_src_offset = 0; | |
367 vo_dga_vp_offset = (y_off * vo_dga_width + x_off ) * vo_dga_bpp; | |
368 | |
369 vo_dga_vp_skip = (vo_dga_width - vo_dga_src_width) * vo_dga_bpp; // todo | |
370 | |
371 printf("vo_dga: vp_off=%d, vp_skip=%d, bpl=%d\n", | |
372 vo_dga_vp_offset, vo_dga_vp_skip, vo_dga_bytes_per_line); | |
373 | |
374 | |
375 | |
376 XF86DGASetViewPort (vo_dga_dpy, XDefaultScreen(vo_dga_dpy), 0, 0); | |
377 XF86DGADirectVideo (vo_dga_dpy, XDefaultScreen(vo_dga_dpy), | |
378 XF86DGADirectGraphics | XF86DGADirectMouse | | |
379 XF86DGADirectKeyb); | |
380 | |
381 XGrabKeyboard (vo_dga_dpy, DefaultRootWindow(vo_dga_dpy), True, | |
382 GrabModeAsync,GrabModeAsync, CurrentTime); | |
383 XGrabPointer (vo_dga_dpy, DefaultRootWindow(vo_dga_dpy), True, | |
384 ButtonPressMask,GrabModeAsync, GrabModeAsync, | |
385 None, None, CurrentTime); | |
386 | |
387 // now clear screen | |
388 | |
389 memset(vo_dga_base, 0, vo_dga_width * vo_dga_vp_height * vo_dga_bpp); | |
390 | |
391 dga_yinc=(vo_dga_src_height<<16)/vo_dga_vp_height; | |
392 dga_xinc=(vo_dga_src_width<<8)/vo_dga_vp_width; | |
393 dga_xinc2=dga_xinc>>1; | |
394 | |
395 { int i; | |
396 for(i=0;i<256;i++){ | |
397 clip_table[i]=0; | |
398 clip_table[i+256]=i; | |
399 clip_table[i+512]=255; | |
400 yuvtab_2568[i]=(0x2568*(i-16))+(256<<13); | |
401 yuvtab_3343[i]=0x3343*(i-128); | |
402 yuvtab_0c92[i]=-0x0c92*(i-128); | |
403 yuvtab_1a1e[i]=-0x1a1e*(i-128); | |
404 yuvtab_40cf[i]=0x40cf*(i-128); | |
405 } | |
406 } | |
407 | |
408 vo_dga_is_running = 1; | |
409 return 0; | |
410 } | |
411 | |
412 #if 0 | |
413 int vo_dga_query_event(void){ | |
414 | |
415 XEvent myevent; | |
416 char text[10]; | |
417 KeySym mykey; | |
418 int retval = 0; | |
419 int i; | |
420 | |
421 if( vo_dga_is_running ){ | |
422 if(XPending(vo_dga_dpy)>0) | |
423 { | |
424 XNextEvent(vo_dga_dpy, &myevent); | |
425 switch (myevent.type) | |
426 { | |
427 case ButtonPress: | |
428 /* Reaktion auf Knopfdruck ---> Textausgabe an der | |
429 Mauscursorposition */ | |
430 | |
431 retval = 'q'; | |
432 break; | |
433 case KeyPress: | |
434 /* Reaktion auf Tastendruck --> Testen ob Taste == "q", | |
435 falls ja: Programmende */ | |
436 i=XLookupString(&myevent, text, 10, &mykey, 0); | |
437 | |
438 if (mykey&0xff00 != 0) mykey=mykey&0x00ff + 256; | |
439 | |
440 switch ( mykey ) | |
441 { | |
442 case wsLeft: retval=KEY_LEFT; break; | |
443 case wsRight: retval=KEY_RIGHT; break; | |
444 case wsUp: retval=KEY_UP; break; | |
445 case wsDown: retval=KEY_DOWN; break; | |
446 case wsSpace: retval=' '; break; | |
447 case wsEscape: retval=KEY_ESC; break; | |
448 case wsEnter: retval=KEY_ENTER; break; | |
449 case wsq: | |
450 case wsQ: retval='q'; break; | |
451 case wsp: | |
452 case wsP: retval='p'; break; | |
453 case wsMinus: | |
454 case wsGrayMinus: retval='-'; break; | |
455 case wsPlus: | |
456 case wsGrayPlus: retval='+'; break; | |
457 } | |
458 break; | |
459 } | |
460 } | |
461 } | |
462 return retval; | |
463 } | |
464 #endif | |
465 | |
466 | |
467 | |
468 | |
469 | |
470 |