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.
34 #include "video_out.h"
35 #include "video_out_internal.h"
37 #include <sys/ioctl.h>
41 #include <linux/videodev.h>
43 #include "drivers/syncfb/syncfb.h"
45 #include "fastmemcpy.h"
47 static vo_info_t info
=
49 "Matrox G200/G400 Synchronous framebuffer (/dev/syncfb)",
51 "Matthias Oelmann <mao@well.com>",
57 /* deinterlacing on? looks only good in 50 Hz(PAL) or 60 Hz(NTSC) modes */
58 static int vo_conf_deinterlace
= 0;
60 /* 72/75 Hz Monitor frequency for progressive output */
61 static int vo_conf_cinemode
= 0;
64 static syncfb_config_t _config
;
65 static syncfb_capability_t sfb_caps
;
67 static syncfb_buffer_info_t bufinfo
;
69 static uint_8
*vid_data
;
70 static uint_8
*frame_mem
;
72 static int debug_skip_first
= 250;
73 static int dbg_singleframe
= 0;
75 static int conf_palette
;
82 it seems that mpeg2dec never calls
83 draw_frame, so i could not test it....
87 write_frame_YUV422(uint_8
*y
,uint_8
*cr
, uint_8
*cb
)
94 bespitch
= _config
.src_pitch
;
95 dest32
= (uint_32
*)vid_data
;
97 for(h
=0; h
< _config
.src_height
/2; h
++)
101 for(w
=0; w
< _config
.src_width
/2; w
++)
103 *dest32
++ = (*y
) + ((*cr
)<<8) + ((*(y
+1))<<16) + ((*cb
)<<24);
104 y
++; y
++; cb
++; cr
++;
106 dest32
+= (bespitch
- _config
.src_width
) / 2;
108 for(w
=0; w
< _config
.src_width
/2; w
++)
110 *dest32
++ = (*y
) + ((*crp
)<<8) + ((*(y
+1))<<16) + ((*cbp
)<<24);
111 y
++; y
++; cbp
++; crp
++;
113 dest32
+= (bespitch
- _config
.src_width
) / 2;
119 write_frame_YUV420P2(uint_8
*y
,uint_8
*cr
, uint_8
*cb
)
122 uint_32 bespitch
,h
,w
;
124 bespitch
= _config
.src_pitch
;
125 dest
= frame_mem
+ bufinfo
.offset
;
127 for(h
=0; h
< _config
.src_height
; h
++)
129 memcpy(dest
, y
, _config
.src_width
);
130 y
+= _config
.src_width
;
134 dest
= frame_mem
+ bufinfo
.offset_p2
;
135 for(h
=0; h
< _config
.src_height
/2; h
++)
138 for(w
=0; w
< _config
.src_width
/2; w
++)
148 write_frame_YUV420P3(uint_8
*y
,uint_8
*cr
, uint_8
*cb
)
153 write_slice_YUV420P2(uint_8
*y
,uint_8
*cr
, uint_8
*cb
,uint_32 slice_num
)
156 uint_32 bespitch
,h
,w
;
158 bespitch
= _config
.src_pitch
;
159 dest
= frame_mem
+ bufinfo
.offset
+ (bespitch
* 16 * slice_num
);
161 for(h
=0; h
< 16; h
++)
163 memcpy(dest
, y
, _config
.src_width
);
164 y
+= _config
.src_width
;
168 dest
= frame_mem
+ bufinfo
.offset_p2
+ (bespitch
* 16 * slice_num
) /2;
172 for(w
=0; w
< _config
.src_width
/2; w
++)
182 write_slice_YUV420P3(uint_8
*y
,uint_8
*cr
, uint_8
*cb
,int stride
[],uint_32 ypos
,uint_32 xsize
,uint_32 ysize
)
187 bespitch
= _config
.src_pitch
;
189 dest
= frame_mem
+ bufinfo
.offset
+ (bespitch
* ypos
);
190 for(h
=0; h
< ysize
; h
++)
192 memcpy(dest
, y
, xsize
);
200 dest
= frame_mem
+ bufinfo
.offset_p2
+ (bespitch
* ypos
)/4;
201 for(h
=0; h
< ysize
; h
++)
203 memcpy(dest
, cr
, xsize
);
208 dest
= frame_mem
+ bufinfo
.offset_p3
+ (bespitch
* ypos
)/4;
209 for(h
=0; h
< ysize
; h
++)
211 memcpy(dest
, cb
, xsize
);
221 write_slice_YUV422(uint_8
*y
,uint_8
*cr
, uint_8
*cb
,uint_32 slice_num
)
225 uint_32 bespitch
,h
,w
;
228 bespitch
= _config
.src_pitch
;
229 dest32
= (uint_32
*)(vid_data
+ (bespitch
* 16 * slice_num
) * 2);
235 for(w
=0; w
< _config
.src_width
/2; w
++)
237 *dest32
++ = (*y
) + ((*cr
)<<8) + ((*(y
+1))<<16) + ((*cb
)<<24);
238 y
++; y
++; cb
++; cr
++;
240 dest32
+= (bespitch
- _config
.src_width
) / 2;
242 for(w
=0; w
< _config
.src_width
/2; w
++)
244 *dest32
++ = (*y
) + ((*crp
)<<8) + ((*(y
+1))<<16) + ((*cbp
)<<24);
245 y
++; y
++; cbp
++; crp
++;
247 dest32
+= (bespitch
- _config
.src_width
) / 2;
251 //static uint32_t draw_slice(uint8_t *src[], uint32_t slice_num)
253 draw_slice(uint8_t *src
[], int stride
[], int w
,int h
,int x
,int y
)
256 if ( vid_data
== NULL
) return 0;
258 write_slice_YUV420P3(src
[0],src
[1], src
[2],stride
,y
,w
,h
);
260 //printf("sorry, not syncfb/draw_slice() implemented yet...\n");
264 if ( conf_palette
== VIDEO_PALETTE_YUV422
) {
265 write_slice_YUV422(src
[0],src
[1], src
[2],slice_num
);
266 } else if ( conf_palette
== VIDEO_PALETTE_YUV420P2
) {
267 write_slice_YUV420P2(src
[0],src
[1], src
[2],slice_num
);
268 } else if ( conf_palette
== VIDEO_PALETTE_YUV420P3
) {
269 write_slice_YUV420P3(src
[0],src
[1], src
[2],slice_num
);
276 static void draw_osd(void)
284 // memset(frame_mem + bufinfo.offset_p2, 0x80, _config.src_width*config.src_height);
285 ioctl(f
,SYNCFB_COMMIT_BUFFER
,&bufinfo
);
287 if ( dbg_singleframe
) {
288 if ( debug_skip_first
== 0 ) {
289 printf( "Press 'anykey' for field 1\n" );
291 ioctl(f
,SYNCFB_VBI
,0);
294 if ( debug_skip_first
> 0 ) {
296 // debug_skip_first = 0;
297 if ( debug_skip_first
== 0 ) {
298 ioctl(f
,SYNCFB_VBI
,0);
299 ioctl(f
,SYNCFB_VBI
,0);
300 ioctl(f
,SYNCFB_VBI
,0);
304 if ( debug_skip_first
== 0 ) {
305 printf( "Press 'anykey' for field 2\n" );
307 ioctl(f
,SYNCFB_VBI
,0);
311 ioctl(f
,SYNCFB_REQUEST_BUFFER
,&bufinfo
);
312 if ( bufinfo
.id
== -1 ) printf( "Got buffer #%d\n", bufinfo
.id
);
314 vid_data
= (uint_8
*)(frame_mem
+ bufinfo
.offset
);
315 if ( bufinfo
.id
== -1 ) {
316 //vid_data = frame_mem;
319 // printf("Flip %d\n", bufinfo.offset);
323 static uint32_t draw_frame(uint8_t *src
[])
325 printf("DRAW FRAME!!!\n");
326 if ( conf_palette
== VIDEO_PALETTE_YUV422
) {
327 write_frame_YUV422(src
[0],src
[1], src
[2]);
328 } else if ( conf_palette
== VIDEO_PALETTE_YUV420P2
) {
329 write_frame_YUV420P2(src
[0],src
[1], src
[2]);
330 } else if ( conf_palette
== VIDEO_PALETTE_YUV420P3
) {
331 write_frame_YUV420P3(src
[0],src
[1], src
[2]);
339 query_format(uint32_t format
)
343 // case IMGFMT_RGB|24:
344 // case IMGFMT_BGR|24:
345 return VFCAP_CSP_SUPPORTED
;
350 static uint32_t config(uint32_t width
, uint32_t height
, uint32_t d_width
, uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
354 f
= open("/dev/syncfb",O_RDWR
);
358 f
= open("/dev/mga_vid",O_RDWR
);
361 printf("Couldn't open /dev/syncfb or /dev/mga_vid\n");
366 if (ioctl(f
,SYNCFB_GET_CAPS
,&sfb_caps
)) perror("Error in mga_vid_config ioctl");
367 if (ioctl(f
,SYNCFB_GET_CONFIG
,&config
)) perror("Error in mga_vid_config ioctl");
369 if (sfb_caps
.palettes
& (1<<VIDEO_PALETTE_YUV420P3
) ) {
370 _config
.src_palette
= VIDEO_PALETTE_YUV420P3
;
371 printf("using palette yuv420p3\n");
372 }else if ( sfb_caps
.palettes
& (1<<VIDEO_PALETTE_YUV420P2
) ) {
373 _config
.src_palette
= VIDEO_PALETTE_YUV420P2
;
374 printf("using palette yuv420p2\n");
375 } else if ( sfb_caps
.palettes
& (1<<VIDEO_PALETTE_YUV422
) ) {
376 _config
.src_palette
= VIDEO_PALETTE_YUV422
;
377 printf("using palette yuv422\n");
379 printf("no supported palette found\n");
383 // _config.src_palette= VIDEO_PALETTE_YUV422;
385 if ( vo_conf_cinemode
) {
386 _config
.default_repeat
= 3;
388 _config
.default_repeat
= 2;
391 conf_palette
= _config
.src_palette
;
392 if ( vo_conf_deinterlace
) {
393 _config
.syncfb_mode
= SYNCFB_FEATURE_SCALE
| SYNCFB_FEATURE_BLOCK_REQUEST
| SYNCFB_FEATURE_DEINTERLACE
;
394 _config
.default_repeat
= 1;
396 _config
.syncfb_mode
= SYNCFB_FEATURE_SCALE
| SYNCFB_FEATURE_BLOCK_REQUEST
;
399 _config
.fb_screen_size
= (RAM_SIZE
-4)*0x100000; //(1280 * 1024 * 32) / 8;
400 _config
.src_width
= width
;
401 _config
.src_height
= height
;
403 _config
.image_width
= d_width
;
404 _config
.image_height
= d_height
;
405 //_config.image_width = 1024;
406 //_config.image_height= 576;
408 _config
.image_xorg
= 0;
409 _config
.image_yorg
= 0;
412 printf ("BES Sourcer size: %d x %d\n", width
, height
);
414 ioctl(f
,SYNCFB_ON
,0);
415 if (ioctl(f
,SYNCFB_SET_CONFIG
,&_config
)) perror("Error in mga_vid_config ioctl");
417 printf ("Framebuffer memory: %ld in %ld buffers\n", sfb_caps
.memory_size
, _config
.buffers
);
419 frame_size
= ((width
+ 31) & ~31) * height
+ (((width
+ 31) & ~31) * height
) / 2;
420 frame_mem
= (uint_8
*)mmap(0,sfb_caps
.memory_size
,PROT_WRITE
,MAP_SHARED
,f
,0);
422 printf( "Requesting first buffer #%d\n", bufinfo
.id
);
423 ioctl(f
,SYNCFB_REQUEST_BUFFER
,&bufinfo
);
424 printf( "Got first buffer #%d\n", bufinfo
.id
);
427 vid_data
= (uint_8
*)(frame_mem
+ bufinfo
.offset
);
430 // memset(frame_mem,0x80,frame_size*2);
438 if (ioctl(f
,SYNCFB_OFF
,0)) perror("Error in OFF ioctl");
442 static void check_events(void)
446 static uint32_t preinit(const char *arg
)
450 printf("vo_syncfb: Unknown subdevice: %s\n",arg
);
456 static uint32_t control(uint32_t request
, void *data
, ...)
459 case VOCTRL_QUERY_FORMAT
:
460 return query_format(*((uint32_t*)data
));