2 #include "fastmemcpy.h"
4 #include "postproc/swscale.h"
5 #include "postproc/rgb2rgb.h"
6 #include "libmpcodecs/vf_scale.h"
10 // mga_vid drawing functions
11 static void set_window( void ); /* forward declaration to kill warnings */
13 static void mDrawColorKey( void ); /* forward declaration to kill warnings */
15 extern int xinerama_screen
;
19 static int mga_next_frame
=0;
21 static mga_vid_config_t mga_vid_config
;
22 static uint8_t *vid_data
, *frames
[4];
25 static uint32_t drwX
,drwY
,drwWidth
,drwHeight
;
27 static uint32_t drwBorderWidth
,drwDepth
;
29 static uint32_t drwcX
,drwcY
,dwidth
,dheight
;
31 static void draw_alpha(int x0
,int y0
, int w
,int h
, unsigned char* src
, unsigned char *srca
, int stride
){
32 uint32_t bespitch
= (mga_vid_config
.src_width
+ 31) & ~31;
33 x0
+=mga_vid_config
.src_width
*(vo_panscan_x
>>1)/(vo_dwidth
+vo_panscan_x
);
34 switch(mga_vid_config
.format
){
35 case MGA_VID_FORMAT_YV12
:
36 case MGA_VID_FORMAT_IYUV
:
37 case MGA_VID_FORMAT_I420
:
38 vo_draw_alpha_yv12(w
,h
,src
,srca
,stride
,vid_data
+bespitch
*y0
+x0
,bespitch
);
40 case MGA_VID_FORMAT_YUY2
:
41 vo_draw_alpha_yuy2(w
,h
,src
,srca
,stride
,vid_data
+2*(bespitch
*y0
+x0
),2*bespitch
);
43 case MGA_VID_FORMAT_UYVY
:
44 vo_draw_alpha_yuy2(w
,h
,src
,srca
,stride
,vid_data
+2*(bespitch
*y0
+x0
)+1,2*bespitch
);
49 static void draw_osd(void)
51 // vo_draw_text(mga_vid_config.src_width,mga_vid_config.src_height,draw_alpha);
52 vo_draw_text(mga_vid_config
.src_width
-mga_vid_config
.src_width
*vo_panscan_x
/(vo_dwidth
+vo_panscan_x
),mga_vid_config
.src_height
,draw_alpha
);
57 //write_slice_g200(uint8_t *y,uint8_t *cr, uint8_t *cb,uint32_t slice_num)
60 draw_slice_g200(uint8_t *image
[], int stride
[], int width
,int height
,int x
,int y
)
63 uint32_t bespitch
= (mga_vid_config
.src_width
+ 31) & ~31;
65 dest
= vid_data
+ bespitch
*y
+ x
;
66 mem2agpcpy_pic(dest
, image
[0], width
, height
, bespitch
, stride
[0]);
68 width
/=2;height
/=2;x
/=2;y
/=2;
70 dest
= vid_data
+ bespitch
*mga_vid_config
.src_height
+ bespitch
*y
+ 2*x
;
72 interleaveBytes(image
[1],image
[2],dest
,
74 stride
[1], stride
[2], bespitch
);
78 draw_slice_g400(uint8_t *image
[], int stride
[], int w
,int h
,int x
,int y
)
82 uint32_t bespitch
,bespitch2
;
84 bespitch
= (mga_vid_config
.src_width
+ 31) & ~31;
85 bespitch2
= bespitch
/2;
87 dest
= vid_data
+ bespitch
* y
+ x
;
88 mem2agpcpy_pic(dest
, image
[0], w
, h
, bespitch
, stride
[0]);
92 dest
= vid_data
+ bespitch
*mga_vid_config
.src_height
+ bespitch2
* y
+ x
;
93 dest2
= dest
+ bespitch2
*mga_vid_config
.src_height
/ 2;
95 if(mga_vid_config
.format
==MGA_VID_FORMAT_YV12
){
96 // mga_vid's YV12 assumes Y,U,V order (insteda of Y,V,U) :(
97 mem2agpcpy_pic(dest
, image
[1], w
, h
, bespitch2
, stride
[1]);
98 mem2agpcpy_pic(dest2
,image
[2], w
, h
, bespitch2
, stride
[2]);
100 mem2agpcpy_pic(dest
, image
[2], w
, h
, bespitch2
, stride
[2]);
101 mem2agpcpy_pic(dest2
,image
[1], w
, h
, bespitch2
, stride
[1]);
107 draw_slice(uint8_t *src
[], int stride
[], int w
,int h
,int x
,int y
)
111 printf("vo: %p/%d %p/%d %p/%d %dx%d/%d;%d \n",
118 if (mga_vid_config
.card_type
== MGA_G200
)
119 draw_slice_g200(src
,stride
,w
,h
,x
,y
);
121 draw_slice_g400(src
,stride
,w
,h
,x
,y
);
126 vo_mga_flip_page(void)
129 // printf("-- flip to %d --\n",mga_next_frame);
132 ioctl(f
,MGA_VID_FSEL
,&mga_next_frame
);
133 mga_next_frame
=(mga_next_frame
+1)%mga_vid_config
.num_frames
;
134 vid_data
=frames
[mga_next_frame
];
140 draw_frame(uint8_t *src
[])
142 mp_msg(MSGT_VO
,MSGL_WARN
,"!!! mga::draw_frame() called !!!\n");
146 static uint32_t get_image(mp_image_t
*mpi
){
147 uint32_t bespitch
= (mga_vid_config
.src_width
+ 31) & ~31;
148 uint32_t bespitch2
= bespitch
/2;
149 // printf("mga: get_image() called\n");
150 if(mpi
->type
==MP_IMGTYPE_STATIC
&& mga_vid_config
.num_frames
>1) return VO_FALSE
; // it is not static
151 if(mpi
->flags
&MP_IMGFLAG_READABLE
) return VO_FALSE
; // slow video ram
152 if(mga_vid_config
.card_type
== MGA_G200
&& mpi
->flags
&MP_IMGFLAG_PLANAR
) return VO_FALSE
;
153 // printf("width=%d vs. bespitch=%d, flags=0x%X \n",mpi->width,bespitch,mpi->flags);
154 if((mpi
->width
==bespitch
) ||
155 (mpi
->flags
&(MP_IMGFLAG_ACCEPT_STRIDE
|MP_IMGFLAG_ACCEPT_WIDTH
))){
156 // we're lucky or codec accepts stride => ok, let's go!
157 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
158 mpi
->planes
[0]=vid_data
;
159 if(mpi
->flags
&MP_IMGFLAG_SWAPPED
){
160 mpi
->planes
[1]=vid_data
+ bespitch
*mga_vid_config
.src_height
;
161 mpi
->planes
[2]=mpi
->planes
[1] + bespitch2
*mga_vid_config
.src_height
/2;
163 mpi
->planes
[2]=vid_data
+ bespitch
*mga_vid_config
.src_height
;
164 mpi
->planes
[1]=mpi
->planes
[2] + bespitch2
*mga_vid_config
.src_height
/2;
166 mpi
->width
=mpi
->stride
[0]=bespitch
;
167 mpi
->stride
[1]=mpi
->stride
[2]=bespitch2
;
169 mpi
->planes
[0]=vid_data
;
171 mpi
->stride
[0]=mpi
->width
*(mpi
->bpp
/8);
173 mpi
->flags
|=MP_IMGFLAG_DIRECT
;
174 // printf("mga: get_image() SUCCESS -> Direct Rendering ENABLED\n");
181 draw_image(mp_image_t
*mpi
){
182 uint32_t bespitch
= (mga_vid_config
.src_width
+ 31) & ~31;
184 // if -dr or -slices then do nothing:
185 if(mpi
->flags
&(MP_IMGFLAG_DIRECT
|MP_IMGFLAG_DRAW_CALLBACK
)) return VO_TRUE
;
187 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
189 draw_slice(mpi
->planes
,mpi
->stride
,mpi
->w
,mpi
->h
,mpi
->x
,mpi
->y
);
192 mem2agpcpy_pic(vid_data
, mpi
->planes
[0], // dst,src
193 mpi
->w
*(mpi
->bpp
/8), mpi
->h
, // w,h
194 bespitch
*2, mpi
->stride
[0]); // dstride,sstride
200 query_format(uint32_t format
)
208 return VFCAP_CSP_SUPPORTED
| VFCAP_CSP_SUPPORTED_BY_HW
| VFCAP_OSD
|VFCAP_HWSCALE_UP
|VFCAP_HWSCALE_DOWN
|VFCAP_ACCEPT_STRIDE
;
213 static void mga_fullscreen()
218 w
=vo_screenwidth
; h
=vo_screenheight
;
219 aspect(&w
,&h
,A_ZOOM
);
222 w
=vo_dwidth
; h
=vo_dheight
;
223 aspect(&w
,&h
,A_NOZOOM
);
225 mga_vid_config
.dest_width
= w
;
226 mga_vid_config
.dest_height
= h
;
227 mga_vid_config
.x_org
=(vo_screenwidth
-w
)/2;
228 mga_vid_config
.y_org
=(vo_screenheight
-h
)/2;
229 if ( ioctl( f
,MGA_VID_CONFIG
,&mga_vid_config
) )
230 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_MGA_ErrorInConfigIoctl
);
233 static int control(uint32_t request
, void *data
, ...)
236 case VOCTRL_QUERY_FORMAT
:
237 return query_format(*((uint32_t*)data
));
238 case VOCTRL_GET_IMAGE
:
239 return get_image(data
);
240 case VOCTRL_DRAW_IMAGE
:
241 return draw_image(data
);
242 case VOCTRL_SET_EQUALIZER
:
248 if ( strcmp( data
,"brightness" ) && strcmp( data
,"contrast" ) ) return VO_FALSE
;
250 if (ioctl(f
,MGA_VID_GET_LUMA
,&prev
)) {
251 perror("Error in mga_vid_config ioctl()");
252 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_MGA_CouldNotGetLumaValuesFromTheKernelModule
);
256 // printf("GET: 0x%4X 0x%4X \n",(prev>>16),(prev&0xffff));
259 value
= va_arg(ap
, int);
262 // printf("value: %d -> ",value);
263 value
=((value
+100)*255)/200-128; // maps -100=>-128 and +100=>127
264 // printf("%d \n",value);
266 if(!strcmp(data
,"contrast"))
267 luma
= (prev
&0xFFFF0000)|(value
&0xFFFF);
269 luma
= (prev
&0xFFFF)|(value
<<16);
271 if (ioctl(f
,MGA_VID_SET_LUMA
,luma
)) {
272 perror("Error in mga_vid_config ioctl()");
273 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_MGA_CouldNotSetLumaValuesFromTheKernelModule
);
280 case VOCTRL_GET_EQUALIZER
:
287 if ( strcmp( data
,"brightness" ) && strcmp( data
,"contrast" ) ) return VO_FALSE
;
289 if (ioctl(f
,MGA_VID_GET_LUMA
,&luma
)) {
290 perror("Error in mga_vid_config ioctl()");
291 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_MGA_CouldNotGetLumaValuesFromTheKernelModule
);
295 if ( !strcmp( data
,"contrast" ) )
301 value
= va_arg(ap
, int*);
304 *value
= (val
*200)/255;
310 case VOCTRL_FULLSCREEN
:
311 if (vo_screenwidth
&& vo_screenheight
)
314 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_MGA_ScreenWidthHeightUnknown
);
316 case VOCTRL_GET_PANSCAN
:
317 if ( !vo_fs
) return VO_FALSE
;
321 #if defined( VO_XMGA ) && defined( HAVE_NEW_GUI )
322 case VOCTRL_GUISUPPORT
:
330 case VOCTRL_GET_PANSCAN
:
331 if ( !inited
|| !vo_fs
) return VO_FALSE
;
333 case VOCTRL_FULLSCREEN
:
336 /* indended, fallthrough to update panscan on fullscreen/windowed switch */
338 case VOCTRL_SET_PANSCAN
:
339 if ( vo_fs
&& ( vo_panscan
!= vo_panscan_amount
) ) // || ( !vo_fs && vo_panscan_amount ) )
341 // int old_y = vo_panscan_y;
343 // if ( old_y != vo_panscan_y )
352 static int mga_init(int width
,int height
,unsigned int format
){
356 width
+=width
&1;height
+=height
&1;
357 mga_vid_config
.frame_size
= ((width
+ 31) & ~31) * height
+ (((width
+ 31) & ~31) * height
) / 2;
358 mga_vid_config
.format
=MGA_VID_FORMAT_I420
; break;
361 width
+=width
&1;height
+=height
&1;
362 mga_vid_config
.frame_size
= ((width
+ 31) & ~31) * height
+ (((width
+ 31) & ~31) * height
) / 2;
363 mga_vid_config
.format
=MGA_VID_FORMAT_YV12
; break;
365 mga_vid_config
.frame_size
= ((width
+ 31) & ~31) * height
* 2;
366 mga_vid_config
.format
=MGA_VID_FORMAT_YUY2
; break;
368 mga_vid_config
.frame_size
= ((width
+ 31) & ~31) * height
* 2;
369 mga_vid_config
.format
=MGA_VID_FORMAT_UYVY
; break;
371 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_MGA_InvalidOutputFormat
,format
);
375 mga_vid_config
.src_width
= width
;
376 mga_vid_config
.src_height
= height
;
377 if(!mga_vid_config
.dest_width
)
378 mga_vid_config
.dest_width
= width
;
379 if(!mga_vid_config
.dest_height
)
380 mga_vid_config
.dest_height
= height
;
382 mga_vid_config
.colkey_on
=0;
384 mga_vid_config
.num_frames
=(vo_directrendering
&& !vo_doublebuffering
)?1:3;
385 mga_vid_config
.version
=MGA_VID_VERSION
;
386 if (ioctl(f
,MGA_VID_CONFIG
,&mga_vid_config
))
388 perror("Error in mga_vid_config ioctl()");
389 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_MGA_IncompatibleDriverVersion
);
393 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_MGA_UsingBuffers
,mga_vid_config
.num_frames
);
395 frames
[0] = (char*)mmap(0,mga_vid_config
.frame_size
*mga_vid_config
.num_frames
,PROT_WRITE
,MAP_SHARED
,f
,0);
396 frames
[1] = frames
[0] + 1*mga_vid_config
.frame_size
;
397 frames
[2] = frames
[0] + 2*mga_vid_config
.frame_size
;
398 frames
[3] = frames
[0] + 3*mga_vid_config
.frame_size
;
400 vid_data
= frames
[mga_next_frame
];
403 memset(frames
[0],0x80,mga_vid_config
.frame_size
*mga_vid_config
.num_frames
);
406 ioctl(f
,MGA_VID_ON
,0);
412 static int mga_uninit(){
414 ioctl( f
,MGA_VID_OFF
,0 );
415 munmap(frames
[0],mga_vid_config
.frame_size
*mga_vid_config
.num_frames
);
422 static int preinit(const char *vo_subdevice
)
424 const char *devname
=vo_subdevice
?vo_subdevice
:"/dev/mga_vid";
425 sws_rgb2rgb_init(get_sws_cpuflags());
427 f
= open(devname
,O_RDWR
);
431 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_MGA_CouldntOpen
,devname
);
445 static void set_window( void ){
450 XGetGeometry( mDisplay
,vo_window
,&mRoot
,&drwX
,&drwY
,&drwWidth
,&drwHeight
,&drwBorderWidth
,&drwDepth
);
451 mp_msg(MSGT_VO
,MSGL_V
,"[xmga] x: %d y: %d w: %d h: %d\n",drwX
,drwY
,drwWidth
,drwHeight
);
453 XTranslateCoordinates( mDisplay
,vo_window
,mRoot
,0,0,&drwcX
,&drwcY
,&mRoot
);
454 mp_msg(MSGT_VO
,MSGL_V
,"[xmga] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",drwcX
,drwcY
,drwX
,drwY
,drwWidth
,drwHeight
);
459 { drwX
=drwcX
=vo_dx
; drwY
=drwcY
=vo_dy
; drwWidth
=vo_dwidth
; drwHeight
=vo_dheight
; }
461 aspect(&dwidth
,&dheight
,A_NOZOOM
);
464 aspect(&dwidth
,&dheight
,A_ZOOM
);
465 drwX
=( vo_screenwidth
- (dwidth
> vo_screenwidth
?vo_screenwidth
:dwidth
) ) / 2;
467 drwY
=( vo_screenheight
- (dheight
> vo_screenheight
?vo_screenheight
:dheight
) ) / 2;
469 drwWidth
=(dwidth
> vo_screenwidth
?vo_screenwidth
:dwidth
);
470 drwHeight
=(dheight
> vo_screenheight
?vo_screenheight
:dheight
);
471 mp_msg(MSGT_VO
,MSGL_V
,"[xmga-fs] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",drwcX
,drwcY
,drwX
,drwY
,drwWidth
,drwHeight
);
473 vo_dwidth
=drwWidth
; vo_dheight
=drwHeight
;
477 if(XineramaIsActive(mDisplay
))
479 XineramaScreenInfo
*screens
;
483 screens
= XineramaQueryScreens(mDisplay
,&num_screens
);
485 /* find the screen we are on */
487 while(i
<num_screens
&&
488 ((screens
[i
].x_org
< drwcX
) ||
489 (screens
[i
].y_org
< drwcY
) ||
490 (screens
[i
].x_org
+ screens
[i
].width
>= drwcX
) ||
491 (screens
[i
].y_org
+ screens
[i
].height
>= drwcY
)))
498 /* save the screen we are on */
501 /* oops.. couldnt find the screen we are on
502 * because the upper left corner left the
503 * visual range. assume we are still on the
509 /* set drwcX and drwcY to the right values */
510 drwcX
= drwcX
- screens
[i
].x_org
;
511 drwcY
= drwcY
- screens
[i
].y_org
;
520 mga_vid_config
.x_org
=drwcX
;
521 mga_vid_config
.y_org
=drwcY
;
522 mga_vid_config
.dest_width
=drwWidth
;
523 mga_vid_config
.dest_height
=drwHeight
;
524 if ( vo_panscan
> 0.0f
&& vo_fs
)
526 drwX
-=vo_panscan_x
>>1;
527 drwY
-=vo_panscan_y
>>1;
528 drwWidth
+=vo_panscan_x
;
529 drwHeight
+=vo_panscan_y
;
531 mga_vid_config
.x_org
-=vo_panscan_x
>>1;
532 mga_vid_config
.y_org
-=vo_panscan_y
>>1;
533 mga_vid_config
.dest_width
=drwWidth
;
534 mga_vid_config
.dest_height
=drwHeight
;
539 if ( ioctl( f
,MGA_VID_CONFIG
,&mga_vid_config
) ) mp_msg(MSGT_VO
,MSGL_WARN
,"Error in mga_vid_config ioctl (wrong mga_vid.o version?)" );