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