10l for me
[mplayer/greg.git] / libvo / vo_syncfb.c
blob47a648e60cc0f247054686410f70cfeee68e7c1c
2 // How many MegaBytes of RAM is on your G200/G400 card?
3 #define RAM_SIZE 16
5 /*
6 * video_out_syncfb.c
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)
15 * any later version.
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.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
33 #include "config.h"
34 #include "video_out.h"
35 #include "video_out_internal.h"
37 #include <sys/ioctl.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <sys/mman.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)",
50 "syncfb",
51 "Matthias Oelmann <mao@well.com>",
55 LIBVO_EXTERN(syncfb)
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;
77 static int f;
82 it seems that mpeg2dec never calls
83 draw_frame, so i could not test it....
86 static void
87 write_frame_YUV422(uint_8 *y,uint_8 *cr, uint_8 *cb)
89 uint_8 *crp, *cbp;
90 uint_32 *dest32;
91 uint_32 bespitch,h,w;
94 bespitch = _config.src_pitch;
95 dest32 = (uint_32 *)vid_data;
97 for(h=0; h < _config.src_height/2; h++)
99 cbp = cb;
100 crp = cr;
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;
118 static void
119 write_frame_YUV420P2(uint_8 *y,uint_8 *cr, uint_8 *cb)
121 uint_8 *dest, *tmp;
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;
131 dest += bespitch;
134 dest = frame_mem + bufinfo.offset_p2;
135 for(h=0; h < _config.src_height/2; h++)
137 tmp = dest;
138 for(w=0; w < _config.src_width/2; w++)
140 *tmp++ = *cr++;
141 *tmp++ = *cb++;
143 dest += bespitch;
147 static void
148 write_frame_YUV420P3(uint_8 *y,uint_8 *cr, uint_8 *cb)
152 static void
153 write_slice_YUV420P2(uint_8 *y,uint_8 *cr, uint_8 *cb,uint_32 slice_num)
155 uint_8 *dest, *tmp;
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;
165 dest += bespitch;
168 dest = frame_mem + bufinfo.offset_p2 + (bespitch * 16 * slice_num) /2;
169 for(h=0; h < 8; h++)
171 tmp = dest;
172 for(w=0; w < _config.src_width/2; w++)
174 *tmp++ = *cr++;
175 *tmp++ = *cb++;
177 dest += bespitch;
181 static void
182 write_slice_YUV420P3(uint_8 *y,uint_8 *cr, uint_8 *cb,int stride[],uint_32 ypos,uint_32 xsize,uint_32 ysize)
184 uint_8 *dest;
185 uint_32 bespitch,h;
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);
193 y += stride[0];
194 dest += bespitch;
197 xsize/=2;
198 ysize/=2;
200 dest = frame_mem + bufinfo.offset_p2 + (bespitch * ypos)/4;
201 for(h=0; h < ysize; h++)
203 memcpy(dest, cr, xsize);
204 cr += stride[1];
205 dest += bespitch/2;
208 dest = frame_mem + bufinfo.offset_p3 + (bespitch * ypos)/4;
209 for(h=0; h < ysize; h++)
211 memcpy(dest, cb, xsize);
212 cb += stride[2];
213 dest += bespitch/2;
220 static void
221 write_slice_YUV422(uint_8 *y,uint_8 *cr, uint_8 *cb,uint_32 slice_num)
223 uint_8 *crp, *cbp;
224 uint_32 *dest32;
225 uint_32 bespitch,h,w;
228 bespitch = _config.src_pitch;
229 dest32 = (uint_32 *)(vid_data + (bespitch * 16 * slice_num) * 2);
231 for(h=0; h < 8; h++)
233 cbp = cb;
234 crp = cr;
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)
252 static uint32_t
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");
262 #if 0
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);
271 #endif
273 return 0;
276 static void draw_osd(void)
280 static void
281 flip_page(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" );
290 getchar();
291 ioctl(f,SYNCFB_VBI,0);
294 if ( debug_skip_first > 0 ) {
295 debug_skip_first--;
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" );
306 getchar();
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;
317 vid_data = NULL;
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]);
334 flip_page();
335 return 0;
338 static uint32_t
339 query_format(uint32_t format)
341 switch(format){
342 case IMGFMT_YV12:
343 // case IMGFMT_RGB|24:
344 // case IMGFMT_BGR|24:
345 return VFCAP_CSP_SUPPORTED;
347 return 0;
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)
352 uint_32 frame_size;
354 f = open("/dev/syncfb",O_RDWR);
356 if(f == -1)
358 f = open("/dev/mga_vid",O_RDWR);
359 if(f == -1)
361 printf("Couldn't open /dev/syncfb or /dev/mga_vid\n");
362 return(-1);
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");
378 } else {
379 printf("no supported palette found\n");
380 return -1;
383 // _config.src_palette= VIDEO_PALETTE_YUV422;
385 if ( vo_conf_cinemode ) {
386 _config.default_repeat = 3;
387 } else {
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;
395 } else {
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);
429 //clear the buffer
430 // memset(frame_mem,0x80,frame_size*2);
431 return 0;
435 static void
436 uninit(void)
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)
448 if(arg)
450 printf("vo_syncfb: Unknown subdevice: %s\n",arg);
451 return ENOSYS;
453 return 0;
456 static uint32_t control(uint32_t request, void *data, ...)
458 switch (request) {
459 case VOCTRL_QUERY_FORMAT:
460 return query_format(*((uint32_t*)data));
462 return VO_NOTIMPL;