2 // How many MegaBytes of RAM is on your G200/G400 card?
8 * Copyright (C) Aaron Holtzman - Aug 1999
10 * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
12 * mpeg2dec is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * mpeg2dec is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with GNU Make; see the file COPYING. If not, write to
24 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
36 #include "video_out.h"
37 #include "video_out_internal.h"
39 #include <sys/ioctl.h>
43 #include <linux/videodev.h>
45 #include "drivers/syncfb/syncfb.h"
47 #include "fastmemcpy.h"
49 static vo_info_t info
=
51 "Matrox G200/G400 Synchronous framebuffer (/dev/syncfb)",
53 "Matthias Oelmann <mao@well.com>",
59 /* deinterlacing on? looks only good in 50 Hz(PAL) or 60 Hz(NTSC) modes */
60 static int vo_conf_deinterlace
= 0;
62 /* 72/75 Hz Monitor frequency for progressive output */
63 static int vo_conf_cinemode
= 0;
66 static syncfb_config_t _config
;
67 static syncfb_capability_t sfb_caps
;
69 static syncfb_buffer_info_t bufinfo
;
71 static uint_8
*vid_data
;
72 static uint_8
*frame_mem
;
74 static int debug_skip_first
= 250;
75 static int dbg_singleframe
= 0;
77 static int conf_palette
;
84 it seems that mpeg2dec never calls
85 draw_frame, so i could not test it....
89 write_frame_YUV422(uint_8
*y
,uint_8
*cr
, uint_8
*cb
)
96 bespitch
= _config
.src_pitch
;
97 dest32
= (uint_32
*)vid_data
;
99 for(h
=0; h
< _config
.src_height
/2; h
++)
103 for(w
=0; w
< _config
.src_width
/2; w
++)
105 *dest32
++ = (*y
) + ((*cr
)<<8) + ((*(y
+1))<<16) + ((*cb
)<<24);
106 y
++; y
++; cb
++; cr
++;
108 dest32
+= (bespitch
- _config
.src_width
) / 2;
110 for(w
=0; w
< _config
.src_width
/2; w
++)
112 *dest32
++ = (*y
) + ((*crp
)<<8) + ((*(y
+1))<<16) + ((*cbp
)<<24);
113 y
++; y
++; cbp
++; crp
++;
115 dest32
+= (bespitch
- _config
.src_width
) / 2;
121 write_frame_YUV420P2(uint_8
*y
,uint_8
*cr
, uint_8
*cb
)
124 uint_32 bespitch
,h
,w
;
126 bespitch
= _config
.src_pitch
;
127 dest
= frame_mem
+ bufinfo
.offset
;
129 for(h
=0; h
< _config
.src_height
; h
++)
131 memcpy(dest
, y
, _config
.src_width
);
132 y
+= _config
.src_width
;
136 dest
= frame_mem
+ bufinfo
.offset_p2
;
137 for(h
=0; h
< _config
.src_height
/2; h
++)
140 for(w
=0; w
< _config
.src_width
/2; w
++)
150 write_frame_YUV420P3(uint_8
*y
,uint_8
*cr
, uint_8
*cb
)
155 write_slice_YUV420P2(uint_8
*y
,uint_8
*cr
, uint_8
*cb
,uint_32 slice_num
)
158 uint_32 bespitch
,h
,w
;
160 bespitch
= _config
.src_pitch
;
161 dest
= frame_mem
+ bufinfo
.offset
+ (bespitch
* 16 * slice_num
);
163 for(h
=0; h
< 16; h
++)
165 memcpy(dest
, y
, _config
.src_width
);
166 y
+= _config
.src_width
;
170 dest
= frame_mem
+ bufinfo
.offset_p2
+ (bespitch
* 16 * slice_num
) /2;
174 for(w
=0; w
< _config
.src_width
/2; w
++)
184 write_slice_YUV420P3(uint_8
*y
,uint_8
*cr
, uint_8
*cb
,int stride
[],uint_32 ypos
,uint_32 xsize
,uint_32 ysize
)
189 bespitch
= _config
.src_pitch
;
191 dest
= frame_mem
+ bufinfo
.offset
+ (bespitch
* ypos
);
192 for(h
=0; h
< ysize
; h
++)
194 memcpy(dest
, y
, xsize
);
202 dest
= frame_mem
+ bufinfo
.offset_p2
+ (bespitch
* ypos
)/4;
203 for(h
=0; h
< ysize
; h
++)
205 memcpy(dest
, cr
, xsize
);
210 dest
= frame_mem
+ bufinfo
.offset_p3
+ (bespitch
* ypos
)/4;
211 for(h
=0; h
< ysize
; h
++)
213 memcpy(dest
, cb
, xsize
);
223 write_slice_YUV422(uint_8
*y
,uint_8
*cr
, uint_8
*cb
,uint_32 slice_num
)
227 uint_32 bespitch
,h
,w
;
230 bespitch
= _config
.src_pitch
;
231 dest32
= (uint_32
*)(vid_data
+ (bespitch
* 16 * slice_num
) * 2);
237 for(w
=0; w
< _config
.src_width
/2; w
++)
239 *dest32
++ = (*y
) + ((*cr
)<<8) + ((*(y
+1))<<16) + ((*cb
)<<24);
240 y
++; y
++; cb
++; cr
++;
242 dest32
+= (bespitch
- _config
.src_width
) / 2;
244 for(w
=0; w
< _config
.src_width
/2; w
++)
246 *dest32
++ = (*y
) + ((*crp
)<<8) + ((*(y
+1))<<16) + ((*cbp
)<<24);
247 y
++; y
++; cbp
++; crp
++;
249 dest32
+= (bespitch
- _config
.src_width
) / 2;
253 //static uint32_t draw_slice(uint8_t *src[], uint32_t slice_num)
255 draw_slice(uint8_t *src
[], int stride
[], int w
,int h
,int x
,int y
)
258 if ( vid_data
== NULL
) return 0;
260 write_slice_YUV420P3(src
[0],src
[1], src
[2],stride
,y
,w
,h
);
262 //printf("sorry, not syncfb/draw_slice() implemented yet...\n");
266 if ( conf_palette
== VIDEO_PALETTE_YUV422
) {
267 write_slice_YUV422(src
[0],src
[1], src
[2],slice_num
);
268 } else if ( conf_palette
== VIDEO_PALETTE_YUV420P2
) {
269 write_slice_YUV420P2(src
[0],src
[1], src
[2],slice_num
);
270 } else if ( conf_palette
== VIDEO_PALETTE_YUV420P3
) {
271 write_slice_YUV420P3(src
[0],src
[1], src
[2],slice_num
);
278 static void draw_osd(void)
286 // memset(frame_mem + bufinfo.offset_p2, 0x80, _config.src_width*config.src_height);
287 ioctl(f
,SYNCFB_COMMIT_BUFFER
,&bufinfo
);
289 if ( dbg_singleframe
) {
290 if ( debug_skip_first
== 0 ) {
291 mp_msg(MSGT_VO
,MSGL_INFO
, "Press 'anykey' for field 1\n" );
293 ioctl(f
,SYNCFB_VBI
,0);
296 if ( debug_skip_first
> 0 ) {
298 // debug_skip_first = 0;
299 if ( debug_skip_first
== 0 ) {
300 ioctl(f
,SYNCFB_VBI
,0);
301 ioctl(f
,SYNCFB_VBI
,0);
302 ioctl(f
,SYNCFB_VBI
,0);
306 if ( debug_skip_first
== 0 ) {
307 mp_msg(MSGT_VO
,MSGL_INFO
, "Press 'anykey' for field 2\n" );
309 ioctl(f
,SYNCFB_VBI
,0);
313 ioctl(f
,SYNCFB_REQUEST_BUFFER
,&bufinfo
);
314 if ( bufinfo
.id
== -1 ) mp_msg(MSGT_VO
,MSGL_INFO
, "Got buffer #%d\n", bufinfo
.id
);
316 vid_data
= (uint_8
*)(frame_mem
+ bufinfo
.offset
);
317 if ( bufinfo
.id
== -1 ) {
318 //vid_data = frame_mem;
321 // printf("Flip %d\n", bufinfo.offset);
325 static int draw_frame(uint8_t *src
[])
327 mp_msg(MSGT_VO
,MSGL_INFO
, "DRAW FRAME!!!\n");
328 if ( conf_palette
== VIDEO_PALETTE_YUV422
) {
329 write_frame_YUV422(src
[0],src
[1], src
[2]);
330 } else if ( conf_palette
== VIDEO_PALETTE_YUV420P2
) {
331 write_frame_YUV420P2(src
[0],src
[1], src
[2]);
332 } else if ( conf_palette
== VIDEO_PALETTE_YUV420P3
) {
333 write_frame_YUV420P3(src
[0],src
[1], src
[2]);
341 query_format(uint32_t format
)
345 // case IMGFMT_RGB|24:
346 // case IMGFMT_BGR|24:
347 return VFCAP_CSP_SUPPORTED
;
352 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
, uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
356 f
= open("/dev/syncfb",O_RDWR
);
360 f
= open("/dev/mga_vid",O_RDWR
);
363 mp_msg(MSGT_VO
,MSGL_ERR
, MSGTR_LIBVO_SYNCFB_CouldntOpen
);
368 if (ioctl(f
,SYNCFB_GET_CAPS
,&sfb_caps
)) perror("Error in mga_vid_config ioctl");
369 if (ioctl(f
,SYNCFB_GET_CONFIG
,&config
)) perror("Error in mga_vid_config ioctl");
371 if (sfb_caps
.palettes
& (1<<VIDEO_PALETTE_YUV420P3
) ) {
372 _config
.src_palette
= VIDEO_PALETTE_YUV420P3
;
373 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_SYNCFB_UsingPaletteYuv420p3
);
374 }else if ( sfb_caps
.palettes
& (1<<VIDEO_PALETTE_YUV420P2
) ) {
375 _config
.src_palette
= VIDEO_PALETTE_YUV420P2
;
376 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_SYNCFB_UsingPaletteYuv420p2
);
377 } else if ( sfb_caps
.palettes
& (1<<VIDEO_PALETTE_YUV422
) ) {
378 _config
.src_palette
= VIDEO_PALETTE_YUV422
;
379 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_SYNCFB_UsingPaletteYuv420
);
381 mp_msg(MSGT_VO
,MSGL_ERR
, MSGTR_LIBVO_SYNCFB_NoSupportedPaletteFound
);
385 // _config.src_palette= VIDEO_PALETTE_YUV422;
387 if ( vo_conf_cinemode
) {
388 _config
.default_repeat
= 3;
390 _config
.default_repeat
= 2;
393 conf_palette
= _config
.src_palette
;
394 if ( vo_conf_deinterlace
) {
395 _config
.syncfb_mode
= SYNCFB_FEATURE_SCALE
| SYNCFB_FEATURE_BLOCK_REQUEST
| SYNCFB_FEATURE_DEINTERLACE
;
396 _config
.default_repeat
= 1;
398 _config
.syncfb_mode
= SYNCFB_FEATURE_SCALE
| SYNCFB_FEATURE_BLOCK_REQUEST
;
401 _config
.fb_screen_size
= (RAM_SIZE
-4)*0x100000; //(1280 * 1024 * 32) / 8;
402 _config
.src_width
= width
;
403 _config
.src_height
= height
;
405 _config
.image_width
= d_width
;
406 _config
.image_height
= d_height
;
407 //_config.image_width = 1024;
408 //_config.image_height= 576;
410 _config
.image_xorg
= 0;
411 _config
.image_yorg
= 0;
414 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_SYNCFB_BesSourcerSize
, width
, height
);
416 ioctl(f
,SYNCFB_ON
,0);
417 if (ioctl(f
,SYNCFB_SET_CONFIG
,&_config
)) perror("Error in mga_vid_config ioctl");
419 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_SYNCFB_FramebufferMemory
, sfb_caps
.memory_size
, _config
.buffers
);
421 frame_size
= ((width
+ 31) & ~31) * height
+ (((width
+ 31) & ~31) * height
) / 2;
422 frame_mem
= (uint_8
*)mmap(0,sfb_caps
.memory_size
,PROT_WRITE
,MAP_SHARED
,f
,0);
424 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_SYNCFB_RequestingFirstBuffer
, bufinfo
.id
);
425 ioctl(f
,SYNCFB_REQUEST_BUFFER
,&bufinfo
);
426 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_SYNCFB_GotFirstBuffer
, bufinfo
.id
);
429 vid_data
= (uint_8
*)(frame_mem
+ bufinfo
.offset
);
432 // memset(frame_mem,0x80,frame_size*2);
440 if (ioctl(f
,SYNCFB_OFF
,0)) perror("Error in OFF ioctl");
444 static void check_events(void)
448 static int preinit(const char *arg
)
452 mp_msg(MSGT_VO
,MSGL_ERR
, MSGTR_LIBVO_SYNCFB_UnknownSubdevice
,arg
);
458 static int control(uint32_t request
, void *data
, ...)
461 case VOCTRL_QUERY_FORMAT
:
462 return query_format(*((uint32_t*)data
));