2350
|
1 // uncomment this if you pached mplayer.c with mplayer_our_out_buffer_hack.diff
|
|
2 //#define VO_TDFXFB_METHOD 2
|
|
3 #define VO_TDFXFB_METHOD 1
|
|
4 // method: Host-to-Screen bitBLT-ing.
|
|
5 #define HWACCEL_OSD_M2
|
|
6 //#define YV12_CONV_METH
|
|
7 #define DONT_USE_FAST_MEMCPY
|
1979
|
8
|
|
9 /*
|
|
10 * video_out_tdfxfb.c
|
|
11 *
|
|
12 * Copyright (C) Zeljko Stevanovic 2001, <zsteva@ptt.yu>
|
|
13 *
|
|
14 * Most code rewrited, move from /dev/3dfx to /dev/fb0 (kernel 2.4.?)
|
|
15 * add support for YUY2 and BGR16 format, remove all X11 DGA code.
|
2350
|
16 * - add support for hardware accelerated OSD (buggy for now).
|
|
17 * work on BGR16 and YUY2 (VO_3DFX_METHOD == 2 only)
|
|
18 * [oct2001]
|
|
19 * - added hardware acceleration for OSD (does not look nice, but is faster)
|
|
20 * (for YV12 don't fork.)
|
|
21 * - fixed YV12 support for ffdivx, but on my cpu this is sllower of yuv2rgb()
|
|
22 * try to uncommenting '#define YV12_CONV_METH'
|
|
23 * - fast_memcpy() is sllower of memcpy() (why, i don't know)
|
|
24 *
|
1979
|
25 *
|
|
26 * Copyright (C) Colin Cross Apr 2000
|
|
27 *
|
|
28 * This file heavily based off of video_out_mga.c of Aaron Holtzman's
|
|
29 * mpeg2dec
|
|
30 *
|
|
31 * mpeg2dec is free software; you can redistribute it and/or modify
|
|
32 * it under the terms of the GNU General Public License as published by
|
|
33 * the Free Software Foundation; either version 2, or (at your option)
|
|
34 * any later version.
|
|
35 *
|
|
36 * mpeg2dec is distributed in the hope that it will be useful,
|
|
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
39 * GNU General Public License for more details.
|
|
40 *
|
|
41 * You should have received a copy of the GNU General Public License
|
|
42 * along with GNU Make; see the file COPYING. If not, write to
|
|
43 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
44 *
|
|
45 */
|
|
46
|
|
47 #include <stdio.h>
|
|
48 #include <stdlib.h>
|
|
49 #include <string.h>
|
|
50
|
|
51 #include "config.h"
|
|
52 #include "video_out.h"
|
|
53 #include "video_out_internal.h"
|
|
54
|
|
55 LIBVO_EXTERN(tdfxfb)
|
|
56
|
|
57 #include <sys/ioctl.h>
|
|
58 #include <unistd.h>
|
|
59 #include <fcntl.h>
|
|
60 #include <sys/mman.h>
|
|
61 #include <errno.h>
|
|
62 #include <wchar.h>
|
|
63 #include <signal.h>
|
|
64
|
|
65 #include <linux/fb.h>
|
|
66
|
|
67 extern int verbose;
|
|
68
|
|
69 //#define LOG(x) syslog(LOG_USER | LOG_DEBUG,x)
|
|
70 #define LOG(x)
|
|
71
|
|
72 #include "drivers/3dfx.h"
|
|
73
|
2350
|
74 // fast_memcpy() is slower of memcpy(), why? i dont know...
|
|
75 #ifndef DONT_USE_FAST_MEMCPY
|
1979
|
76 #include "fastmemcpy.h"
|
2350
|
77 #endif
|
|
78
|
|
79 #ifdef YV12_CONV_METH
|
2732
|
80 #include "../postproc/rgb2rgb.h"
|
2350
|
81 #endif
|
1979
|
82
|
|
83 static vo_info_t vo_info =
|
|
84 {
|
|
85 "tdfxfb (/dev/fb?)",
|
|
86 "tdfxfb",
|
2350
|
87 "Zeljko Stevanovic <zsteva@ptt.yu>",
|
1979
|
88 ""
|
|
89 };
|
|
90
|
|
91 static char *fb_devname = NULL;
|
|
92 static int fb_fd = -1;
|
|
93 static struct fb_fix_screeninfo fb_finfo;
|
|
94 static struct fb_var_screeninfo fb_vinfo;
|
|
95
|
|
96 static uint32_t in_width;
|
|
97 static uint32_t in_height;
|
|
98 static uint32_t in_format;
|
|
99 static uint32_t in_bytepp;
|
|
100
|
|
101 static uint32_t in_banshee_format,
|
|
102 in_banshee_size;
|
|
103
|
|
104 static uint32_t screenwidth;
|
|
105 static uint32_t screenheight;
|
|
106 static uint32_t screendepth;
|
|
107 static uint32_t vidwidth, vidheight; // resize on screen to ... for ration expect...
|
|
108 static uint32_t vidx=0, vidy=0; // for centring on screen.
|
|
109
|
|
110 static uint32_t vid_banshee_xy,
|
|
111 vid_banshee_format,
|
|
112 vid_banshee_size;
|
|
113
|
|
114 static void (*draw_alpha_p)(int w, int h, unsigned char *src,
|
|
115 unsigned char *srca, int stride, unsigned char *dst,
|
|
116 int dstride);
|
|
117
|
|
118 static uint32_t *vidpage0;
|
|
119 static uint32_t *vidpage1;
|
|
120 static uint32_t *in_page0;
|
|
121
|
|
122 static uint32_t vidpage0offset;
|
|
123 static uint32_t vidpage1offset;
|
|
124 static uint32_t in_page0_offset;
|
|
125
|
|
126 // Current pointer into framebuffer where display is located
|
|
127 static uint32_t targetoffset;
|
|
128
|
|
129 static uint32_t page_space;
|
|
130
|
|
131 static uint32_t *tdfx_iobase;
|
|
132
|
|
133 static voodoo_io_reg *reg_IO;
|
|
134 static voodoo_2d_reg *reg_2d;
|
|
135 static voodoo_yuv_reg *reg_YUV;
|
|
136 static voodoo_yuv_fb *fb_YUV;
|
|
137
|
|
138 static uint32_t *memBase0, *memBase1;
|
|
139 //static uint32_t baseAddr0, baseAddr1;
|
|
140
|
|
141 //#define BANSHEE_SCREEN_MEMORY (8*1024*1024)
|
2350
|
142 static uint32_t tdfx_free_offset = 0;
|
1979
|
143
|
|
144 /*- ----------------------------------------------------------------- -*/
|
|
145
|
|
146 /* code get from linux kernel tdfxfb.c by Hannu Mallat */
|
|
147
|
|
148 typedef uint32_t u32;
|
|
149
|
|
150 static inline u32 tdfx_inl(unsigned int reg) {
|
|
151 return *((volatile uint32_t *)(tdfx_iobase + reg));
|
|
152 }
|
|
153
|
|
154 static inline void tdfx_outl(unsigned int reg, u32 val) {
|
|
155 *((volatile uint32_t *)(tdfx_iobase + reg)) = val;
|
|
156 }
|
|
157
|
|
158 static inline void banshee_make_room(int size) {
|
|
159 while((tdfx_inl(STATUS) & 0x1f) < size);
|
|
160 }
|
|
161
|
|
162 static inline void banshee_wait_idle(void)
|
|
163 {
|
|
164 int i = 0;
|
|
165
|
|
166 banshee_make_room(1);
|
|
167 tdfx_outl(COMMAND_3D, COMMAND_3D_NOP);
|
|
168
|
|
169 while(1) {
|
|
170 i = (tdfx_inl(STATUS) & STATUS_BUSY) ? 0 : i + 1;
|
|
171 if(i == 3) break;
|
|
172 }
|
|
173 }
|
|
174
|
|
175
|
|
176 /*- ----------------------------------------------------------------- -*/
|
|
177
|
|
178 static void
|
|
179 restore_regs(voodoo_2d_reg *regs)
|
|
180 {
|
|
181 reg_2d->commandExtra = regs->commandExtra;
|
|
182 reg_2d->clip0Min = regs->clip0Min;
|
|
183 reg_2d->clip0Max = regs->clip0Max;
|
|
184
|
|
185 reg_2d->srcBaseAddr = regs->srcBaseAddr;
|
|
186 reg_2d->srcXY = regs->srcXY;
|
|
187 reg_2d->srcFormat = regs->srcFormat;
|
|
188 reg_2d->srcSize = regs->srcSize;
|
|
189
|
|
190 reg_2d->dstBaseAddr = regs->dstBaseAddr;
|
|
191 reg_2d->dstXY = regs->dstXY;
|
|
192 reg_2d->dstFormat = regs->dstFormat;
|
2350
|
193 reg_2d->dstSize = regs->dstSize;
|
1979
|
194
|
|
195 reg_2d->command = 0;
|
|
196 }
|
|
197
|
|
198
|
|
199 static void
|
|
200 restore(void)
|
|
201 {
|
2350
|
202 reg_IO->vidDesktopStartAddr = vidpage0offset;
|
1979
|
203 //XF86DGADirectVideo(display,0,0);
|
|
204 }
|
|
205
|
|
206 static void
|
|
207 sighup(int foo)
|
|
208 {
|
2350
|
209 reg_IO->vidDesktopStartAddr = vidpage0offset;
|
1979
|
210 //XF86DGADirectVideo(display,0,0);
|
|
211 exit(0);
|
|
212 }
|
|
213
|
2350
|
214 #if 0
|
1979
|
215 static void
|
|
216 dump_yuv_planar(void *y, void *u, void *v,
|
|
217 uint32_t to, uint32_t px, uint32_t py, uint32_t width, uint32_t height)
|
|
218 {
|
|
219 uint32_t j;
|
2350
|
220 uint32_t *YUV_U, *YUV_V, *YUV_Y;
|
|
221 uint32_t width2 = width >> 1;
|
|
222 uint32_t height2 = height >> 1;
|
1979
|
223
|
|
224 reg_YUV->yuvBaseAddr = to + in_width * 2 * py;
|
2350
|
225 reg_YUV->yuvStride = width << 1;
|
1979
|
226
|
2350
|
227 YUV_U = &fb_YUV->U[0];
|
|
228 YUV_V = &fb_YUV->V[0];
|
|
229 YUV_Y = &fb_YUV->Y[0];
|
|
230 for (j = 0; j < height2; j++)
|
1979
|
231 {
|
2350
|
232 memcpy(YUV_U, u, width2);
|
|
233 memcpy(YUV_V, v, width2);
|
|
234 memcpy(YUV_Y, y, width); YUV_Y += VOODOO_YUV_STRIDE; y += width;
|
|
235 memcpy(YUV_Y, y, width); YUV_Y += VOODOO_YUV_STRIDE; y += width;
|
|
236 YUV_U += VOODOO_YUV_STRIDE; u += width2;
|
|
237 YUV_V += VOODOO_YUV_STRIDE; v += width2;
|
1979
|
238 }
|
|
239 }
|
|
240 #endif
|
|
241
|
2350
|
242 #define S2S_BLT(cmd, to, dXY, dFmt, dSize, from, sXY, sFmt, sSize, extCmd) \
|
1979
|
243 do { \
|
|
244 voodoo_2d_reg saved_regs = *reg_2d; \
|
|
245 \
|
2350
|
246 reg_2d->commandExtra = (extCmd); \
|
1979
|
247 reg_2d->clip0Min = 0; \
|
|
248 reg_2d->clip0Max = 0xffffffff; \
|
|
249 \
|
|
250 reg_2d->srcBaseAddr = (from); \
|
|
251 reg_2d->srcXY = (sXY); \
|
|
252 reg_2d->srcFormat = (sFmt); \
|
|
253 reg_2d->srcSize = (sSize); \
|
|
254 \
|
|
255 reg_2d->dstBaseAddr = (to); \
|
|
256 reg_2d->dstXY = (dXY); \
|
|
257 reg_2d->dstFormat = (dFmt); \
|
|
258 reg_2d->dstSize = (dSize); \
|
|
259 \
|
|
260 reg_2d->command = (cmd); \
|
|
261 \
|
2350
|
262 banshee_wait_idle(); \
|
1979
|
263 restore_regs(&saved_regs); \
|
|
264 } while (0)
|
|
265
|
|
266
|
|
267 /*- ----------------------------------------------------------------- -*/
|
|
268
|
|
269 static uint32_t draw_slice_YV12(uint8_t *image[], int stride[], int w,int h,int x,int y);
|
|
270 static uint32_t draw_frame_YV12(uint8_t *src[]);
|
|
271 static void flip_page_YV12(void);
|
|
272 static void draw_osd_YV12(void);
|
|
273
|
|
274 static uint32_t draw_slice_YUY2_BGR16(uint8_t *image[], int stride[], int w,int h,int x,int y);
|
|
275 static uint32_t draw_frame_YUY2_BGR16(uint8_t *src[]);
|
2350
|
276 static void flip_page_vidpage10(void);
|
|
277 static void draw_osd(void);
|
1979
|
278
|
|
279 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
|
|
280 unsigned char *srca, int stride);
|
2350
|
281 #ifdef HWACCEL_OSD_M2
|
|
282 static void my_draw_alpha_accel(int x0, int y0, int w, int h, unsigned char *src,
|
|
283 unsigned char *srca, int stride);
|
|
284 #endif
|
1979
|
285
|
|
286 static void
|
|
287 update_target(void)
|
|
288 {
|
|
289 }
|
|
290
|
2350
|
291 #ifndef VO_TDFXFB_METHOD
|
|
292 #define VO_TDFXFB_METHOD 1
|
1979
|
293 #endif
|
|
294
|
|
295
|
2350
|
296 #if VO_TDFXFB_METHOD == 2
|
1979
|
297 extern void **our_out_buffer;
|
|
298 #endif
|
|
299
|
|
300 static uint32_t
|
4433
|
301 config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height,
|
|
302 uint32_t fullscreen, char *title, uint32_t format,const vo_tune_info_t *info)
|
1979
|
303 {
|
|
304
|
2350
|
305 if (verbose) {
|
1979
|
306 printf("vo_3dfx->init( width = %d, height = %d, "
|
|
307 "d_width = %d, d_height = %d, format = %d)\n",
|
|
308 width, height, d_width, d_height, format);
|
|
309 printf("vo_3dfx->init( format => %s )\n", vo_format_name(format));
|
|
310 printf("vo_3dfx: vo_depthonscreen => %d, vo_screenwidth => %d, "
|
|
311 "vo_screenhight => %d\n", vo_depthonscreen, vo_screenwidth, vo_screenheight);
|
|
312 printf("vo_3dfx->init() vo_dwidth => %d, vo_dheight => %d, vo_dbpp => %d\n",
|
|
313 vo_dwidth, vo_dheight, vo_dbpp);
|
|
314 }
|
|
315
|
|
316 if (!fb_devname && !(fb_devname = getenv("FRAMEBUFFER")))
|
|
317 fb_devname = "/dev/fb0";
|
|
318
|
2350
|
319 if (verbose)
|
1979
|
320 printf("vo_3dfx->init(): fbdev ==> %s\n", fb_devname);
|
|
321
|
|
322 if ((fb_fd = open(fb_devname, O_RDWR)) == -1) {
|
|
323 printf("vo_3dfx->init(): can't open %s, %s\n", fb_devname, strerror(errno));
|
|
324 return -1;
|
|
325 }
|
|
326
|
|
327 if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_finfo)) {
|
|
328 printf("vo_3dfx->init(): problem with ioctl(fb_fd, FBITGET_FSCREENINFO.., %s\n",
|
|
329 strerror(errno));
|
|
330 return -1;
|
|
331 }
|
|
332
|
|
333 if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &fb_vinfo)) {
|
|
334 printf("vo_3dfx->init(): problem with ioctl(fb_fd, FBITGET_VSCREENINFO.., %s\n",
|
|
335 strerror(errno));
|
|
336 return -1;
|
|
337 }
|
|
338
|
|
339 if (verbose) {
|
|
340 printf("fb_finfo:\n");
|
|
341 printf(" id: %s\n", fb_finfo.id);
|
|
342 printf(" frame bufer at %x len %x (%d)\n", fb_finfo.smem_start, fb_finfo.smem_len,
|
|
343 fb_finfo.smem_len);
|
|
344 printf(" mem io at %x len %x\n", fb_finfo.mmio_start, fb_finfo.mmio_len);
|
|
345
|
|
346 printf("fb_vinfo:\n");
|
|
347 printf(" resolution: %dx%d\n", fb_vinfo.xres, fb_vinfo.yres);
|
|
348 printf(" virtual res: %dx%d\n", fb_vinfo.xres_virtual, fb_vinfo.yres_virtual);
|
|
349 printf(" virt offset: %dx%d\n", fb_vinfo.xoffset, fb_vinfo.yoffset);
|
|
350 }
|
|
351
|
|
352 if (fb_finfo.accel != FB_ACCEL_3DFX_BANSHEE) {
|
|
353 printf("vo_3dfx->init(): this driver made only for 3dfx banshee... sorry...\n");
|
|
354 return -1;
|
|
355 }
|
|
356 if (fb_vinfo.bits_per_pixel != 16) {
|
|
357 printf("vo_3dfx->init(): for now fork only in 16 bits mode. use fbset -depth 16 <mode>\n");
|
|
358 return -1;
|
|
359 }
|
|
360 //return -1;
|
|
361
|
|
362
|
|
363 screenwidth = fb_vinfo.xres;
|
|
364 screenheight = fb_vinfo.yres;
|
|
365 screendepth = 2;
|
|
366 // Store sizes for later
|
|
367 in_width = width;
|
|
368 in_height = height;
|
|
369 in_format = format;
|
|
370
|
2350
|
371 if (fullscreen) {
|
1979
|
372 double exrat;
|
2350
|
373
|
|
374 if (verbose)
|
|
375 printf("vo_tdfxfb->init(): fullscreen mode...\n");
|
|
376
|
|
377 vidwidth = screenwidth;
|
|
378 vidheight = screenheight;
|
1979
|
379
|
|
380 exrat = (double)in_width / in_height;
|
|
381 if (verbose)
|
|
382 printf("vo_3dfx->init(): in_width / in_height => %f\n", exrat);
|
|
383 if (screenwidth / exrat <= screenheight)
|
|
384 vidheight = (double)screenwidth / exrat;
|
|
385 else
|
|
386 vidwidth = (double)screenheight * exrat;
|
|
387
|
|
388 vidx = (screenwidth - vidwidth) / 2;
|
|
389 vidy = (screenheight - vidheight) / 2;
|
|
390
|
|
391 if (verbose) {
|
|
392 printf("vo_3dfx->init(): vidwidth => %d\n", vidwidth);
|
|
393 printf("vo_3dfx->init(): vidheight => %d\n", vidheight);
|
|
394 printf("vo_3dfx->init(): vidx => %d\n", vidx);
|
|
395 printf("vo_3dfx->init(): vidy => %d\n", vidy);
|
|
396 }
|
2350
|
397 } else {
|
|
398 if (in_width > screenwidth || in_height > screenheight) {
|
|
399 printf("vo_tdfxfb->init(): your resolution is small for play move...\n");
|
|
400 return -1;
|
|
401 } else {
|
|
402 vidwidth = in_width;
|
|
403 vidheight = in_height;
|
|
404 vidx = (screenwidth - in_width) / 2;
|
|
405 vidy = (screenheight - in_height) / 2;
|
|
406 }
|
1979
|
407 }
|
|
408
|
|
409 signal(SIGALRM,sighup);
|
|
410 //alarm(120);
|
|
411
|
|
412
|
|
413 // access to 3dfx hardware....
|
|
414 memBase1 = mmap(0, fb_finfo.smem_len, PROT_READ | PROT_WRITE,
|
|
415 MAP_SHARED, fb_fd, 0);
|
|
416 memBase0 = mmap(0, fb_finfo.mmio_len, PROT_READ | PROT_WRITE,
|
|
417 MAP_SHARED, fb_fd, fb_finfo.smem_len);
|
|
418
|
|
419 if (memBase0 == (uint32_t *)0xFFFFFFFF ||
|
|
420 memBase1 == (uint32_t *)0xFFFFFFFF)
|
|
421 {
|
|
422 printf("Couldn't map 3dfx memory areas: %p, %p, %d\n",
|
|
423 memBase0, memBase1, errno);
|
|
424 }
|
|
425
|
|
426
|
|
427 tdfx_iobase = (void *)memBase0 + VOODOO_IO_REG_OFFSET;
|
|
428
|
|
429 // Set up global pointers
|
|
430 reg_IO = (void *)memBase0 + VOODOO_IO_REG_OFFSET;
|
|
431 reg_2d = (void *)memBase0 + VOODOO_2D_REG_OFFSET;
|
|
432 reg_YUV = (void *)memBase0 + VOODOO_YUV_REG_OFFSET;
|
|
433 fb_YUV = (void *)memBase0 + VOODOO_YUV_PLANE_OFFSET;
|
|
434
|
|
435 vidpage0offset = 0;
|
|
436 vidpage1offset = screenwidth * screenheight * screendepth;
|
|
437 in_page0_offset = vidpage1offset + screenwidth * screenheight * screendepth;
|
|
438
|
|
439 vidpage0 = (void *)memBase1 + (unsigned long int)vidpage0offset;
|
|
440 vidpage1 = (void *)memBase1 + (unsigned long int)vidpage1offset;
|
|
441 in_page0 = (void *)memBase1 + (unsigned long int)in_page0_offset;
|
|
442
|
|
443 vid_banshee_xy = XYREG(vidx, vidy);
|
|
444 vid_banshee_format = screenwidth*2 | VOODOO_BLT_FORMAT_16;
|
|
445 vid_banshee_size = XYREG(vidwidth, vidheight);
|
|
446
|
|
447 in_banshee_size = XYREG(in_width, in_height);
|
|
448
|
2350
|
449 //video_out_3dfx.flip_page = flip_page_all;
|
|
450 draw_alpha_p = vo_draw_alpha_rgb16;
|
1979
|
451
|
|
452 switch (in_format) {
|
|
453 case IMGFMT_YV12:
|
|
454 video_out_tdfxfb.draw_slice = draw_slice_YV12;
|
|
455 video_out_tdfxfb.draw_frame = draw_frame_YV12;
|
|
456 video_out_tdfxfb.flip_page = flip_page_YV12;
|
|
457 video_out_tdfxfb.draw_osd = draw_osd_YV12;
|
2350
|
458 draw_alpha_p = vo_draw_alpha_yuy2;
|
1979
|
459 in_banshee_format = in_width * 2 | VOODOO_BLT_FORMAT_YUYV;
|
2350
|
460 #ifdef YV12_CONV_METH
|
|
461 yuv2rgb_init(16, MODE_RGB);
|
|
462 in_banshee_format = in_width * 2 | VOODOO_BLT_FORMAT_16;
|
|
463 draw_alpha_p = vo_draw_alpha_rgb16;
|
|
464 #endif
|
1979
|
465 break;
|
|
466 case IMGFMT_YUY2:
|
|
467 video_out_tdfxfb.draw_slice = draw_slice_YUY2_BGR16;
|
|
468 video_out_tdfxfb.draw_frame = draw_frame_YUY2_BGR16;
|
2350
|
469 video_out_tdfxfb.flip_page = flip_page_vidpage10;
|
1979
|
470
|
|
471 in_banshee_format = in_width * 2 | VOODOO_BLT_FORMAT_YUYV;
|
|
472 in_bytepp = 2;
|
2350
|
473 #if VO_TDFXFB_METHOD == 2
|
|
474 *our_out_buffer = in_page0;
|
|
475 #endif
|
|
476
|
1979
|
477 break;
|
|
478 case IMGFMT_BGR|16:
|
|
479 video_out_tdfxfb.draw_slice = draw_slice_YUY2_BGR16;
|
|
480 video_out_tdfxfb.draw_frame = draw_frame_YUY2_BGR16;
|
2350
|
481 video_out_tdfxfb.flip_page = flip_page_vidpage10;
|
|
482
|
1979
|
483 in_banshee_format = in_width * 2 | VOODOO_BLT_FORMAT_16;
|
|
484 in_bytepp = 2;
|
2350
|
485 #if VO_TDFXFB_METHOD == 2
|
|
486 *our_out_buffer = in_page0;
|
|
487 #endif
|
1979
|
488 break;
|
|
489 }
|
|
490
|
|
491
|
|
492 // Clear pages 1,2,3
|
|
493 // leave page 0, that belongs to X.
|
|
494 // So does part of 1. Oops.
|
|
495 memset(vidpage0, 0x00, screenwidth * screenheight * screendepth);
|
|
496 memset(vidpage1, 0x00, screenwidth * screenheight * screendepth);
|
|
497 memset(in_page0, 0x00, in_width * in_height * in_bytepp);
|
|
498
|
|
499 // Show page 0 (unblanked)
|
|
500 reg_IO->vidDesktopStartAddr = vidpage0offset;
|
|
501 //banshee_make_room(1);
|
|
502 //tdfx_outl(VIDDESKSTART, vidpage1offset);
|
|
503
|
|
504 /* fd is deliberately not closed - if it were, mmaps might be released??? */
|
|
505
|
|
506 atexit(restore);
|
|
507
|
2350
|
508 printf("(display) tdfxfb initialized %p/%p\n",memBase0,memBase1);
|
1979
|
509 return 0;
|
|
510 }
|
|
511
|
|
512 static const vo_info_t*
|
|
513 get_info(void)
|
|
514 {
|
|
515 return &vo_info;
|
|
516 }
|
|
517
|
|
518 // -------------------------------------------------------------------
|
|
519 // YV12 fork fine. but only on vcd, with ffmpeg codec for DivX don't given corect picture.
|
|
520
|
|
521 static uint32_t
|
|
522 draw_frame_YV12(uint8_t *src[])
|
|
523 {
|
|
524 return 0;
|
|
525 }
|
|
526
|
2350
|
527 #ifndef YV12_CONV_METH
|
|
528
|
1979
|
529 static uint32_t
|
|
530 draw_slice_YV12(uint8_t *image[], int stride[], int w,int h,int x,int y)
|
|
531 {
|
2350
|
532 void *img_y = image[0];
|
|
533 void *img_u = image[1];
|
|
534 void *img_v = image[2];
|
|
535 uint32_t j;
|
|
536 uint32_t *YUV_U = &fb_YUV->U[0],
|
|
537 *YUV_V = &fb_YUV->V[0],
|
|
538 *YUV_Y = &fb_YUV->Y[0];
|
|
539 uint32_t height2 = h >> 1;
|
|
540
|
|
541 #if 0
|
|
542 printf("stride[0] => %d\n", stride[0]);
|
|
543 printf("stride[1] => %d\n", stride[1]);
|
|
544 printf("stride[2] => %d\n", stride[2]);
|
|
545 printf("w => %d, h => %d, x => %d, y => %d\n", w, h, x, y);
|
|
546 #endif
|
|
547 #if 0
|
1979
|
548 dump_yuv_planar((uint32_t *)image[0], (uint32_t *)image[1],
|
|
549 (uint32_t *)image[2], in_page0_offset, x, y, w, h);
|
2350
|
550 #endif
|
|
551
|
|
552 //reg_YUV->yuvBaseAddr = to + mystride * 2 * py;
|
|
553 reg_YUV->yuvBaseAddr = in_page0_offset + w * 2 * y;
|
|
554 reg_YUV->yuvStride = w << 1;
|
|
555
|
|
556 for (j = 0; j < height2; j++)
|
|
557 {
|
|
558 memcpy(YUV_U, img_u, stride[1]);
|
|
559 memcpy(YUV_V, img_v, stride[2]);
|
|
560 memcpy(YUV_Y, img_y, stride[0]); YUV_Y += VOODOO_YUV_STRIDE; img_y += stride[0];
|
|
561 memcpy(YUV_Y, img_y, stride[0]); YUV_Y += VOODOO_YUV_STRIDE; img_y += stride[0];
|
|
562 YUV_U += VOODOO_YUV_STRIDE; img_u += stride[1];
|
|
563 YUV_V += VOODOO_YUV_STRIDE; img_v += stride[2];
|
|
564 }
|
|
565
|
1979
|
566 return 0;
|
|
567 }
|
|
568
|
2350
|
569 #else /* !YV12_CONV_METH */
|
|
570 // -------------------------------------------------------------------
|
|
571 // YV12 with converting support
|
|
572
|
|
573 static uint32_t
|
|
574 draw_slice_YV12(uint8_t *image[], int stride[], int w,int h,int x,int y)
|
|
575 {
|
|
576 uint8_t *dest = (uint8_t *)(in_page0) + (in_width * y + x) * 2;
|
|
577 //dump_yuv_planar((uint32_t *)image[0], (uint32_t *)image[1],
|
|
578 // (uint32_t *)image[2], in_page0_offset, x, y, w, h);
|
|
579 yuv2rgb(dest, image[0], image[1], image[2], w, h, in_width * 2,
|
|
580 stride[0], stride[1]);
|
|
581 return 0;
|
|
582 }
|
|
583
|
|
584 #endif /* else ! YV12_CONV_METH */
|
|
585
|
1979
|
586 static void
|
|
587 flip_page_YV12(void)
|
|
588 {
|
|
589 S2S_BLT(2 | 1 << 8 | 0xcc << 24, // 2 | 1<<8 | 0xcc<<24,
|
|
590 vidpage0offset, vid_banshee_xy,
|
|
591 vid_banshee_format, vid_banshee_size,
|
|
592 in_page0_offset, 0,
|
2350
|
593 in_banshee_format, in_banshee_size, 0);
|
|
594
|
1979
|
595 }
|
|
596
|
|
597 static void draw_alpha_YV12(int x0, int y0, int w, int h, unsigned char *src,
|
|
598 unsigned char *srca, int stride)
|
|
599 {
|
2350
|
600 unsigned char *dst = (void *)in_page0 + (in_width * (0+y0) + 0+x0) * 2; // 2 <= bpp
|
1979
|
601 uint32_t dstride = in_width * 2; // 2 <= bpp
|
2350
|
602 //printf("draw_alpha: x0,y0 = %d,%d; w,h = %d,%d; stride=%d;\n", x0, y0, w, h, stride);
|
|
603 (*draw_alpha_p)(w, h, src, srca, stride, dst, dstride);
|
1979
|
604 }
|
|
605
|
|
606
|
|
607 static void draw_osd_YV12(void)
|
|
608 {
|
2350
|
609 #ifndef HWACCEL_OSD_M2
|
|
610 //vo_draw_text(vidwidth, vidheight, draw_alpha);
|
|
611 #else
|
|
612 //vo_draw_text(vidwidth, vidheight, my_draw_alpha_accel);
|
|
613 #endif /* else ! HWACCEL_OSD_M2 */
|
1979
|
614 vo_draw_text(in_width, in_height, draw_alpha_YV12);
|
|
615 }
|
|
616
|
|
617
|
2350
|
618
|
1979
|
619 // -------------------------------------------------------------------
|
|
620 // YUYV & BGR16 support
|
|
621
|
|
622 static uint32_t
|
|
623 draw_frame_YUY2_BGR16(uint8_t *src[])
|
|
624 {
|
2350
|
625 #if VO_TDFXFB_METHOD == 1
|
1979
|
626 memcpy(in_page0, src[0], in_width * in_height * in_bytepp);
|
|
627 #endif
|
|
628 // blt to offscreen page.
|
|
629 S2S_BLT(2 | 1 << 8 | 0xcc << 24, // 2 | 1<<8 | 0xcc<<24,
|
|
630 vidpage1offset, vid_banshee_xy,
|
|
631 vid_banshee_format, vid_banshee_size,
|
|
632 in_page0_offset, 0,
|
2350
|
633 in_banshee_format, in_banshee_size, 0);
|
1979
|
634 banshee_wait_idle();
|
|
635 return 0;
|
|
636 }
|
|
637
|
|
638 static uint32_t
|
2350
|
639 draw_frame_YUY2_BGR16_h2s_bitblt(uint8_t *src[])
|
|
640 {
|
|
641 uint32_t i, len;
|
|
642 uint32_t *launch = (uint32_t *)®_2d->launchArea[0];
|
|
643 uint32_t *src32 = (uint32_t *)src[0];
|
|
644 voodoo_2d_reg saved_regs = *reg_2d;
|
|
645
|
|
646 reg_2d->commandExtra = 0;
|
|
647 reg_2d->clip0Min = 0;
|
|
648 reg_2d->clip0Max = 0xffffffff;
|
|
649
|
|
650 reg_2d->colorFore = 0;
|
|
651 reg_2d->colorBack = 0;
|
|
652
|
|
653 reg_2d->srcXY = 0;
|
|
654 //reg_2d->srcBaseAddr = (from);
|
|
655
|
|
656 // reg_2d->srcFormat = 0x00400000 | BIT(20); // byte allignment + byte swizzle...
|
|
657 // YUYV + dword packet
|
|
658 reg_2d->srcFormat = in_width*2 | VOODOO_BLT_FORMAT_YUYV; // | (2 << 22);
|
|
659 reg_2d->dstXY = vid_banshee_xy;
|
|
660 reg_2d->dstSize = vid_banshee_size;
|
|
661 reg_2d->dstBaseAddr = vidpage1offset;
|
|
662 reg_2d->dstFormat = vid_banshee_format;
|
|
663
|
|
664 // host-to-screen blting + tranpasparent
|
|
665 //reg_2d->command = 3 | (1 << 16)| (ROP_COPY << 24);
|
|
666 reg_2d->command = 3 | (ROP_COPY << 24);
|
|
667
|
|
668 i = 0;
|
|
669 len = in_width * in_height * 2; /* 2 => 16 bit */
|
|
670 len >>= 2; /* / 4 */
|
|
671 for (;;) {
|
|
672 if (i == len) break; launch[0] = src32[i]; i++;
|
|
673 if (i == len) break; launch[1] = src32[i]; i++;
|
|
674 if (i == len) break; launch[2] = src32[i]; i++;
|
|
675 if (i == len) break; launch[3] = src32[i]; i++;
|
|
676 }
|
|
677 banshee_wait_idle();
|
|
678 restore_regs(&saved_regs);
|
|
679 return;
|
|
680 }
|
|
681
|
|
682 static uint32_t
|
1979
|
683 draw_slice_YUY2_BGR16(uint8_t *image[], int stride[], int w,int h,int x,int y)
|
|
684 {
|
|
685 return 0;
|
|
686 }
|
|
687
|
|
688 static void
|
2350
|
689 flip_page_vidpage10(void)
|
1979
|
690 {
|
|
691 uint32_t o;
|
|
692 void *p;
|
|
693
|
|
694 // flip screen pages.
|
|
695 o = vidpage0offset; vidpage0offset = vidpage1offset; vidpage1offset = o;
|
|
696 p = vidpage0; vidpage0 = vidpage1; vidpage1 = p;
|
|
697
|
|
698 reg_IO->vidDesktopStartAddr = vidpage0offset;
|
|
699 }
|
|
700
|
2350
|
701 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src,
|
1979
|
702 unsigned char *srca, int stride)
|
|
703 {
|
|
704 unsigned char *dst = (void *)vidpage1 + (screenwidth * (vidy+y0) + vidx+x0) * 2; // 2 <= bpp
|
|
705 uint32_t dstride = screenwidth * 2; // 2 <= bpp
|
2350
|
706 //printf("draw_alpha: x0,y0 = %d,%d; w,h = %d,%d; stride=%d;\n", x0, y0, w, h, stride);
|
1979
|
707 (*draw_alpha_p)(w, h, src, srca, stride, dst, dstride);
|
|
708 }
|
|
709
|
2350
|
710 static void draw_osd(void)
|
1979
|
711 {
|
2350
|
712 #ifndef HWACCEL_OSD_M2
|
|
713 vo_draw_text(vidwidth, vidheight, draw_alpha);
|
|
714 #else
|
|
715 vo_draw_text(vidwidth, vidheight, my_draw_alpha_accel);
|
|
716 #endif /* else ! HWACCEL_OSD_M2 */
|
1979
|
717 }
|
|
718
|
|
719 // -------------------------------------------------------------------
|
|
720
|
|
721 static uint32_t
|
|
722 draw_frame(uint8_t *src[])
|
|
723 {
|
|
724 /* dummy */
|
|
725 return 0;
|
|
726 }
|
|
727
|
|
728 static uint32_t
|
|
729 draw_slice(uint8_t *image[], int stride[], int w,int h,int x,int y)
|
|
730 {
|
|
731 /* dummy */
|
|
732 return 0;
|
|
733 }
|
|
734
|
|
735 static void
|
|
736 flip_page(void)
|
|
737 {
|
|
738 /* dummy */
|
|
739 }
|
|
740
|
2350
|
741 /*- ----------------------------------------------------------------- -*/
|
1979
|
742
|
|
743 static uint32_t
|
|
744 query_format(uint32_t format)
|
|
745 {
|
|
746 switch(format){
|
|
747 case IMGFMT_YV12:
|
|
748 return 4|2; // 4|2;
|
|
749 case IMGFMT_YUY2:
|
|
750 if (verbose) printf("query_format: IMGFMT_YUY2\n");
|
2350
|
751 return 4|2; //4|2;
|
1979
|
752 case IMGFMT_BGR|16:
|
2350
|
753 if (verbose) printf("query_format: IMGFMT_BGR|16\n");
|
|
754 return 4|2; // 4|2; /* osd + ????? */
|
1979
|
755 }
|
|
756 return 0;
|
|
757 }
|
|
758
|
|
759 static void
|
|
760 uninit(void)
|
|
761 {
|
2350
|
762 reg_IO->vidDesktopStartAddr = vidpage0offset;
|
1979
|
763 }
|
|
764
|
|
765
|
|
766 static void check_events(void)
|
|
767 {
|
|
768 }
|
|
769
|
2350
|
770 #ifdef HWACCEL_OSD_M2
|
|
771
|
|
772 static void my_draw_alpha_accel(int x0, int y0, int w, int h, unsigned char *src,
|
1979
|
773 unsigned char *srca, int stride)
|
|
774 {
|
2350
|
775 int y, x;
|
|
776 uint32_t pbuf, pcnt;
|
|
777 uint32_t *launch = (uint32_t *)®_2d->launchArea[0];
|
|
778 voodoo_2d_reg saved_regs = *reg_2d;
|
|
779
|
|
780 reg_2d->commandExtra = 0;
|
|
781 reg_2d->clip0Min = 0;
|
|
782 reg_2d->clip0Max = 0xffffffff;
|
1979
|
783
|
2350
|
784 reg_2d->colorFore = 0xffff;
|
|
785 reg_2d->colorBack = 0;
|
|
786
|
|
787 reg_2d->srcXY = 0;
|
|
788 //reg_2d->srcBaseAddr = (from);
|
|
789
|
|
790 reg_2d->srcFormat = 0x00400000 | BIT(20); // byte allignment + byte swizzle...
|
|
791 //reg_2d->srcSize = XYREG(w, h);
|
|
792 reg_2d->dstSize = XYREG(w, h);
|
|
793
|
|
794 reg_2d->dstBaseAddr = vidpage1offset;
|
|
795 reg_2d->dstXY = XYREG(vidx+x0, vidy+y0);
|
|
796 reg_2d->dstFormat = vid_banshee_format;
|
1979
|
797
|
2350
|
798 // host-to-screen blting + tranpasparent
|
|
799 reg_2d->command = 3 | (1 << 16)| (ROP_COPY << 24);
|
|
800
|
|
801 pcnt = 0;
|
|
802 pbuf = 0;
|
|
803 for (y = 0; y < h; y++) {
|
|
804 for (x = 0; x < w; x++) {
|
|
805 pbuf = (pbuf << 1) | (((src[x] > 150) ? 1 : 0));
|
|
806 if (++pcnt == 32) { launch[0] = pbuf; pcnt = 0; pbuf = 0; }
|
|
807 }
|
|
808
|
|
809 if ((pcnt % 8) != 0) {
|
|
810 pbuf <<= 8 - (pcnt % 8);
|
|
811 pcnt += 8 - (pcnt % 8);
|
|
812 if (pcnt == 32) { launch[0] = pbuf; pcnt = 0; pbuf = 0; }
|
|
813 }
|
|
814
|
|
815 src += stride;
|
|
816 srca += stride;
|
|
817 }
|
|
818 if (pcnt != 0) launch[0] = pbuf;
|
|
819
|
1979
|
820 banshee_wait_idle();
|
2350
|
821 restore_regs(&saved_regs);
|
|
822 return;
|
1979
|
823 }
|
2350
|
824 #endif /* ! HWACCEL_OSD_M2 */
|
1979
|
825
|
4352
|
826 static uint32_t preinit(const char *arg)
|
|
827 {
|
|
828 return 0;
|
|
829 }
|
1979
|
830
|
4352
|
831 static void query_vaa(vo_vaa_t *vaa)
|
|
832 {
|
|
833 memset(vaa,0,sizeof(vo_vaa_t));
|
|
834 }
|