configure: Enable joystick support on FreeBSD
[mplayer.git] / libvo / vo_tdfx_vid.c
blobb49c2a85df3312c7e3b6e6bc741438e0ade70de3
1 /*
2 * copyright (C) 2003 Alban Bedel
4 * This file is part of MPlayer.
6 * MPlayer is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * MPlayer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <sys/ioctl.h>
30 #include <sys/mman.h>
31 #include "config.h"
32 #include "video_out.h"
33 #include "video_out_internal.h"
34 #include "aspect.h"
35 #include "mp_msg.h"
37 #include "fastmemcpy.h"
38 #include "drivers/tdfx_vid.h"
41 static const vo_info_t info =
43 "tdfx vid",
44 "tdfx_vid",
45 "Albeu",
49 //#define VERBOSE
51 const LIBVO_EXTERN(tdfx_vid)
53 static tdfx_vid_config_t tdfx_cfg;
55 static unsigned char* agp_mem = NULL;
56 static int tdfx_fd = -1;
58 static uint32_t img_fmt; // The real input format
59 static uint32_t src_width, src_height, src_fmt, src_bpp, src_stride;
60 static uint32_t dst_width, dst_height, dst_fmt, dst_bpp, dst_stride;
62 static uint32_t tdfx_page;
63 static uint32_t front_buffer;
64 static uint32_t back_buffer;
65 static uint8_t num_buffer = 3;
66 static uint32_t buffer_size; // Max size
67 static uint8_t current_buffer = 0;
68 static uint8_t current_ip_buf = 0;
69 static uint32_t buffer_stride[3];
71 static int use_overlay = 1;
72 static tdfx_vid_overlay_t tdfx_ov;
74 // FIXME
75 #if 0
76 static void clear_screen(void) {
77 tdfx_vid_agp_move_t mov;
79 memset(agp_mem,0,tdfx_cfg.screen_width*dst_bpp*tdfx_cfg.screen_height);
81 mov.move2 = TDFX_VID_MOVE_2_PACKED;
82 mov.width = tdfx_cfg.screen_width*dst_bpp;
83 mov.height = tdfx_cfg.screen_height;
84 mov.src = 0;
85 mov.src_stride = tdfx_cfg.screen_width*dst_bpp;
86 mov.dst = front_buffer;
87 mov.dst_stride = tdfx_cfg.screen_stride;
89 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_TDXVID] Move %d(%d) x %d => %d.\n", mov.width,mov.src_stride,mov.height,mov.dst_stride);
91 if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov))
92 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] AGP move failed to clear the screen.\n");
95 #endif
97 static int draw_slice(uint8_t *image[], int stride[], int w,int h,int x,int y)
99 uint8_t* ptr[3];
101 #ifdef VERBOSE
102 printf("Draw slices %d\n",current_buffer);
103 #endif
104 switch(img_fmt) {
105 case IMGFMT_YUY2:
106 case IMGFMT_UYVY:
107 case IMGFMT_BGR8:
108 case IMGFMT_BGR16:
109 case IMGFMT_BGR24:
110 case IMGFMT_BGR32:
111 // copy :( to agp_mem
112 // still faster than tdfxfb wich directly copy to the video mem :)
113 mem2agpcpy_pic(agp_mem + current_buffer * buffer_size +
114 y*buffer_stride[0] + x * src_bpp,
115 image[0],
116 src_bpp*w,h,buffer_stride[0],stride[0]);
117 return 0;
119 case IMGFMT_YV12:
120 case IMGFMT_I420:
121 // Copy to agp mem
122 ptr[0] = agp_mem + current_buffer * buffer_size;
123 mem2agpcpy_pic(ptr[0] + y * buffer_stride[0] + x,image[0],w,h,
124 buffer_stride[0],stride[0]);
125 ptr[1] = ptr[0] + (src_height*src_width);
126 mem2agpcpy_pic(ptr[1] + y/2 * buffer_stride[1] + x/2,image[1],w/2,h/2,
127 buffer_stride[1],stride[1]);
128 ptr[2] = ptr[1] + (src_height*src_width/4);
129 mem2agpcpy_pic(ptr[2] + y/2 * buffer_stride[2] + x/2,image[2],w/2,h/2,
130 buffer_stride[2],stride[2]);
131 return 0;
134 return 1;
137 static void draw_osd(void)
141 static void
142 flip_page(void)
144 tdfx_vid_blit_t blit;
145 //return;
146 // Scale convert
147 #ifdef VERBOSE
148 printf("Flip\n");
149 #endif
150 if(use_overlay) {
151 // TDFX_VID_OVERLAY_ON does nothing if the overlay is already on
152 if(!ioctl(tdfx_fd,TDFX_VID_OVERLAY_ON)) { // X11 killed the overlay :(
153 if(ioctl(tdfx_fd,TDFX_VID_SET_OVERLAY,&tdfx_ov))
154 mp_msg(MSGT_VO, MSGL_ERR, "tdfx_vid: set_overlay failed\n");
156 // These formats need conversion
157 switch(src_fmt) {
158 case IMGFMT_BGR8:
159 case IMGFMT_BGR24:
160 case IMGFMT_BGR32:
161 memset(&blit,0,sizeof(tdfx_vid_blit_t));
162 blit.src = back_buffer;
163 blit.src_stride = src_stride;
164 blit.src_x = 0;
165 blit.src_y = 0;
166 blit.src_w = src_width;
167 blit.src_h = src_height;
168 blit.src_format = src_fmt;
170 blit.dst = front_buffer;
171 blit.dst_stride = dst_stride;
172 blit.dst_x = 0;
173 blit.dst_y = 0;
174 blit.dst_w = src_width;
175 blit.dst_h = src_height;
176 blit.dst_format = IMGFMT_BGR16;
177 if(ioctl(tdfx_fd,TDFX_VID_BLIT,&blit))
178 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Blit failed.\n");
180 return;
182 memset(&blit,0,sizeof(tdfx_vid_blit_t));
183 blit.src = back_buffer;
184 blit.src_stride = src_stride;
185 blit.src_x = 0;
186 blit.src_y = 0;
187 blit.src_w = src_width;
188 blit.src_h = src_height;
189 blit.src_format = src_fmt;
191 blit.dst = front_buffer;
192 blit.dst_stride = dst_stride;
193 blit.dst_x = 0;
194 blit.dst_y = 0;
195 blit.dst_w = dst_width;
196 blit.dst_h = dst_height;
197 blit.dst_format = dst_fmt;
199 if(ioctl(tdfx_fd,TDFX_VID_BLIT,&blit))
200 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Blit failed.\n");
203 static int
204 draw_frame(uint8_t *src[])
206 int stride[] = { src_stride, 0, 0};
207 return draw_slice(src,stride,src_width, src_height,0,0);
210 static int
211 query_format(uint32_t format)
213 switch(format) {
214 case IMGFMT_BGR8:
215 if(tdfx_cfg.screen_format == TDFX_VID_FORMAT_BGR8)
216 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
217 return 0;
218 case IMGFMT_YUY2:
219 case IMGFMT_UYVY:
220 case IMGFMT_BGR15:
221 case IMGFMT_BGR16:
222 case IMGFMT_BGR24:
223 case IMGFMT_BGR32:
224 case IMGFMT_YV12:
225 case IMGFMT_I420:
226 if(tdfx_cfg.screen_format == TDFX_VID_FORMAT_BGR8)
227 return 0;
228 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
230 return 0;
233 static int
234 config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format)
237 if(tdfx_fd < 0)
238 return 1;
239 // When we are run as sub vo we must follow the size gaven to us
240 if(!(flags & VOFLAG_XOVERLAY_SUB_VO)) {
241 if(!vo_screenwidth)
242 vo_screenwidth = tdfx_cfg.screen_width;
243 if(!vo_screenheight)
244 vo_screenheight = tdfx_cfg.screen_height;
246 aspect_save_orig(width,height);
247 aspect_save_prescale(d_width,d_height);
248 aspect_save_screenres(vo_screenwidth,vo_screenheight);
250 if(flags&VOFLAG_FULLSCREEN) { /* -fs */
251 aspect(&d_width,&d_height,A_ZOOM);
252 vo_fs = VO_TRUE;
253 } else {
254 aspect(&d_width,&d_height,A_NOZOOM);
255 vo_fs = VO_FALSE;
258 src_width = width;
259 src_height = height;
260 buffer_size = 0;
261 buffer_stride[0] = 0;
262 src_fmt = 0;
263 switch(format) {
264 case IMGFMT_BGR8:
265 case IMGFMT_BGR24:
266 case IMGFMT_BGR32:
267 if(use_overlay)
268 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_TDFXVID] Non-native overlay format needs conversion.\n");
269 case IMGFMT_BGR15:
270 case IMGFMT_BGR16:
271 src_bpp = ((format & 0x3F)+7)/8;
272 break;
273 case IMGFMT_YV12:
274 case IMGFMT_I420:
275 buffer_size = src_width * src_height * 3 / 2;
276 buffer_stride[0] = ((src_width+1)/2)*2;
277 buffer_stride[1] = buffer_stride[2] = buffer_stride[0]/2;
278 src_fmt = TDFX_VID_FORMAT_YUY2;
279 case IMGFMT_YUY2:
280 case IMGFMT_UYVY:
281 src_bpp = 2;
282 break;
283 default:
284 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Unsupported input format 0x%x.\n",format);
285 return 1;
288 img_fmt = format;
289 src_stride = src_width*src_bpp;
290 // The overlay need a 4 bytes aligned stride
291 if(use_overlay)
292 src_stride = ((src_stride+3)/4)*4;
293 if(!src_fmt)
294 src_fmt = format;
295 if(!buffer_size)
296 buffer_size = src_stride*src_height;
297 if(!buffer_stride[0])
298 buffer_stride[0] = src_stride;
300 dst_fmt = tdfx_cfg.screen_format;
301 dst_bpp = ((dst_fmt & 0x3F)+7)/8;
302 dst_width = d_width;
303 dst_height = d_height;
304 dst_stride = tdfx_cfg.screen_stride;
306 tdfx_page = tdfx_cfg.screen_stride*tdfx_cfg.screen_height;
307 front_buffer = tdfx_cfg.screen_start;
308 back_buffer = front_buffer + tdfx_page;
310 while(use_overlay) {
311 tdfx_vid_overlay_t ov;
312 uint32_t ov_fmt = src_fmt, ov_stride = src_stride;
313 // Align the buffer
314 back_buffer = (((back_buffer+3)/4)*4);
315 // With the overlay the front buffer is not on the screen
316 // so we take the back buffer
317 front_buffer = back_buffer;
318 switch(src_fmt) {
319 case IMGFMT_BGR8:
320 case IMGFMT_BGR24:
321 case IMGFMT_BGR32:
322 back_buffer = front_buffer + 2*(src_stride*src_height);
323 ov_stride = dst_stride = src_width<<1;
324 ov_fmt = IMGFMT_BGR16;
325 break;
327 ov.src[0] = front_buffer;
328 ov.src[1] = front_buffer + (src_stride*src_height);
329 ov.src_width = src_width;
330 ov.src_height = src_height;
331 ov.src_stride = ov_stride;
332 ov.format = ov_fmt;
333 ov.dst_width = dst_width;
334 ov.dst_height = dst_height;
335 ov.dst_x = vo_dx;
336 ov.dst_y = vo_dy;
337 ov.use_colorkey = 0;
339 if(ioctl(tdfx_fd,TDFX_VID_SET_OVERLAY,&ov)) {
340 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Overlay setup failed.\n");
341 use_overlay = 0;
342 break;
344 tdfx_ov = ov;
345 if(use_overlay == 1) {
346 if(ioctl(tdfx_fd,TDFX_VID_OVERLAY_ON)) {
347 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Overlay on failed.\n");
348 use_overlay = 0;
349 break;
351 use_overlay++;
354 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_TDFXVID] Overlay ready: %d(%d) x %d @ %d => %d(%d) x %d @ %d.\n",
355 src_width,src_stride,src_height,src_bpp,
356 dst_width,dst_stride,dst_height,dst_bpp);
357 break;
360 if(!use_overlay)
361 mp_tmsg(MSGT_VO,MSGL_INFO, "[VO_TDFXVID] Texture blit ready: %d(%d) x %d @ %d => %d(%d) x %d @ %d.\n",
362 src_width,src_stride,src_height,src_bpp,
363 dst_width,dst_stride,dst_height,dst_bpp);
365 return 0;
368 static void
369 uninit(void)
371 if(use_overlay == 2) {
372 if(ioctl(tdfx_fd,TDFX_VID_OVERLAY_OFF))
373 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Overlay off failed\n");
374 use_overlay--;
376 close(tdfx_fd);
377 tdfx_fd = -1;
381 static void check_events(void)
385 static int preinit(const char *arg)
388 tdfx_fd = open(arg ? arg : "/dev/tdfx_vid", O_RDWR);
389 if(tdfx_fd < 0) {
390 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Can't open %s: %s.\n",arg ? arg : "/dev/tdfx_vid",
391 strerror(errno));
392 return 1;
395 if(ioctl(tdfx_fd,TDFX_VID_GET_CONFIG,&tdfx_cfg)) {
396 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Can't get current configuration: %s.\n",strerror(errno));
397 return 1;
400 mp_msg(MSGT_VO,MSGL_INFO, "tdfx_vid version %d\n"
401 " Ram: %d\n"
402 " Screen: %d x %d\n"
403 " Format: %c%c%c%d\n",
404 tdfx_cfg.version,
405 tdfx_cfg.ram_size,
406 tdfx_cfg.screen_width, tdfx_cfg.screen_height,
407 tdfx_cfg.screen_format>>24,(tdfx_cfg.screen_format>>16)&0xFF,
408 (tdfx_cfg.screen_format>>8)&0xFF,tdfx_cfg.screen_format&0xFF);
410 // For now just allocate more than i ever need
411 agp_mem = mmap( NULL, 1024*768*4, PROT_READ | PROT_WRITE, MAP_SHARED,
412 tdfx_fd, 0);
414 if(agp_mem == MAP_FAILED) {
415 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Memmap failed !!!!!\n");
416 return 1;
419 memset(agp_mem,0,1024*768*4);
421 return 0;
424 static uint32_t get_image(mp_image_t *mpi) {
425 int buf = 0;
427 #ifdef VERBOSE
428 printf("Get image %d\n",buf);
429 #endif
431 // Currently read are too slow bcs we read from the
432 // agp aperture and not the memory directly
433 //if(mpi->flags&MP_IMGFLAG_READABLE) return VO_FALSE;
435 if(mpi->flags&MP_IMGFLAG_READABLE &&
436 (mpi->type==MP_IMGTYPE_IPB || mpi->type==MP_IMGTYPE_IP)){
437 // reference (I/P) frame of IP or IPB:
438 if(num_buffer<2) return VO_FALSE; // not enough
439 current_ip_buf^=1;
440 // for IPB with 2 buffers we can DR only one of the 2 P frames:
441 if(mpi->type==MP_IMGTYPE_IPB && num_buffer<3 && current_ip_buf) return VO_FALSE;
442 buf=current_ip_buf;
443 if(mpi->type==MP_IMGTYPE_IPB) ++buf; // preserve space for B
446 switch(mpi->imgfmt) {
447 case IMGFMT_YUY2:
448 case IMGFMT_UYVY:
449 case IMGFMT_BGR8:
450 case IMGFMT_BGR15:
451 case IMGFMT_BGR16:
452 case IMGFMT_BGR24:
453 case IMGFMT_BGR32:
454 mpi->planes[0] = agp_mem + buf * buffer_size;
455 mpi->stride[0] = src_stride;
456 break;
457 case IMGFMT_YV12:
458 case IMGFMT_I420:
459 mpi->planes[0] = agp_mem + buf * buffer_size;
460 mpi->stride[0] = mpi->width;
461 mpi->planes[1] = mpi->planes[0] + mpi->stride[0]*mpi->height;
462 mpi->stride[1] = mpi->chroma_width;
463 mpi->planes[2] = mpi->planes[1] + mpi->stride[1]*mpi->chroma_height;
464 mpi->stride[2] = mpi->chroma_width;
465 break;
466 default:
467 mp_tmsg(MSGT_VO,MSGL_WARN, "Get image todo.\n");
468 return VO_FALSE;
470 mpi->flags |= MP_IMGFLAG_DIRECT;
471 mpi->priv = (void*)buf;
473 return VO_TRUE;
476 static uint32_t start_slice(mp_image_t *mpi){
477 int buf = 0;
479 #ifdef VERBOSE
480 printf("Start slices %d\n",buf);
481 #endif
483 if(mpi->flags & MP_IMGFLAG_DIRECT)
484 buf = (int)mpi->priv;
485 current_buffer = buf;
487 return VO_TRUE;
490 static uint32_t draw_image(mp_image_t *mpi){
491 int buf = 0;
492 tdfx_vid_agp_move_t mov;
493 tdfx_vid_yuv_t yuv;
494 int p;
495 uint8_t* planes[3];
497 #ifdef VERBOSE
498 printf("Draw image %d\n",buf);
499 #endif
501 if(mpi->flags & MP_IMGFLAG_DIRECT)
502 buf = (int)mpi->priv;
504 switch(mpi->imgfmt) {
505 case IMGFMT_YUY2:
506 case IMGFMT_UYVY:
507 case IMGFMT_BGR8:
508 case IMGFMT_BGR15:
509 case IMGFMT_BGR16:
510 case IMGFMT_BGR24:
511 case IMGFMT_BGR32:
512 if(!(mpi->flags&(MP_IMGFLAG_DIRECT|MP_IMGFLAG_DRAW_CALLBACK))) {
513 // copy to agp_mem
514 #ifdef VERBOSE
515 printf("Memcpy\n");
516 #endif
517 planes[0] = agp_mem + buf * buffer_size;
518 mem2agpcpy_pic(planes[0],mpi->planes[0],src_bpp*mpi->width,mpi->height,
519 buffer_stride[0],mpi->stride[0]);
520 } else
521 planes[0] = agp_mem + buf * buffer_size;
523 mov.move2 = TDFX_VID_MOVE_2_PACKED;
524 mov.width = mpi->width*((mpi->bpp+7)/8);
525 mov.height = mpi->height;
526 mov.src = planes[0] - agp_mem;
527 mov.src_stride = buffer_stride[0];
529 mov.dst = back_buffer;
530 mov.dst_stride = src_stride;
532 if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov))
533 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] AGP move failed.\n");
534 break;
536 case IMGFMT_YV12:
537 case IMGFMT_I420:
538 if(!(mpi->flags&(MP_IMGFLAG_DIRECT|MP_IMGFLAG_DRAW_CALLBACK))) {
539 // Copy to agp mem
540 #ifdef VERBOSE
541 printf("Memcpy\n");
542 #endif
543 planes[0] = agp_mem + buf * buffer_size;
544 memcpy_pic(planes[0],mpi->planes[0],mpi->width,mpi->height,
545 buffer_stride[0],mpi->stride[0]);
546 planes[1] = planes[0] + (mpi->height*mpi->stride[0]);
547 memcpy_pic(planes[1],mpi->planes[1],mpi->chroma_width,mpi->chroma_height,
548 buffer_stride[1],mpi->stride[1]);
549 planes[2] = planes[1] + (mpi->chroma_height*mpi->stride[1]);
550 memcpy_pic(planes[2],mpi->planes[2],mpi->chroma_width,mpi->chroma_height,
551 buffer_stride[2],mpi->stride[2]);
552 } else {
553 planes[0] = agp_mem + buf * buffer_size;
554 planes[1] = planes[0] + buffer_stride[0] * src_height;
555 planes[2] = planes[1] + buffer_stride[1] * src_height/2;
558 // Setup the yuv thing
559 yuv.base = back_buffer;
560 yuv.stride = src_stride;
561 if(ioctl(tdfx_fd,TDFX_VID_SET_YUV,&yuv)) {
562 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] Set YUV failed.\n");
563 break;
567 // Now agp move that
568 // Y
569 mov.move2 = TDFX_VID_MOVE_2_YUV;
570 mov.width = mpi->width;
571 mov.height = mpi->height;
572 mov.src = planes[0] - agp_mem;
573 mov.src_stride = buffer_stride[0];
574 mov.dst = 0x0;
575 mov.dst_stride = TDFX_VID_YUV_STRIDE;
577 if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) {
578 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] AGP move failed on Y plane.\n");
579 break;
581 //return 0;
582 // U
583 p = mpi->imgfmt == IMGFMT_YV12 ? 1 : 2;
584 mov.width = mpi->chroma_width;
585 mov.height = mpi->chroma_height;
586 mov.src = planes[p] - agp_mem;
587 mov.src_stride = buffer_stride[p];
588 mov.dst += TDFX_VID_YUV_PLANE_SIZE;
589 if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) {
590 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] AGP move failed on U plane.\n");
591 break;
593 // V
594 p = mpi->imgfmt == IMGFMT_YV12 ? 2 : 1;
595 mov.src = planes[p] - agp_mem;
596 mov.src_stride = buffer_stride[p];
597 mov.dst += TDFX_VID_YUV_PLANE_SIZE;
598 if(ioctl(tdfx_fd,TDFX_VID_AGP_MOVE,&mov)) {
599 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] AGP move failed on V plane.\n");
600 break;
602 break;
603 default:
604 mp_tmsg(MSGT_VO,MSGL_WARN, "[VO_TDFXVID] unknown format: 0x%x.\n",mpi->imgfmt);
605 return VO_TRUE;
608 return VO_TRUE;
611 static uint32_t fullscreen(void) {
612 vo_fs ^= 1;
613 aspect(&dst_width,&dst_height,vo_fs ? A_ZOOM : A_NOZOOM);
614 // This does not work :((
615 //clear_screen();
616 return VO_TRUE;
619 static uint32_t set_window(mp_win_t* w) {
620 if(!use_overlay) return VO_FALSE;
622 tdfx_ov.dst_x = w->x;
623 tdfx_ov.dst_y = w->y;
624 tdfx_ov.dst_width = w->w;
625 tdfx_ov.dst_height = w->h;
627 if(ioctl(tdfx_fd,TDFX_VID_SET_OVERLAY,&tdfx_ov))
628 mp_msg(MSGT_VO, MSGL_V, "tdfx_vid: set window failed\n");
630 return VO_TRUE;
633 static uint32_t set_colorkey(mp_colorkey_t* colork) {
634 if(!use_overlay) return VO_FALSE;
636 tdfx_ov.colorkey[0] = tdfx_ov.colorkey[1] = colork->x11;
637 tdfx_ov.use_colorkey = 1;
638 tdfx_ov.invert_colorkey = 0;
640 if(ioctl(tdfx_fd,TDFX_VID_SET_OVERLAY,&tdfx_ov))
641 mp_msg(MSGT_VO, MSGL_V, "tdfx_vid: set colorkey failed\n");
643 return VO_TRUE;
646 static int control(uint32_t request, void *data)
648 switch (request) {
649 case VOCTRL_QUERY_FORMAT:
650 return query_format(*((uint32_t*)data));
651 case VOCTRL_GET_IMAGE:
652 return get_image(data);
653 case VOCTRL_DRAW_IMAGE:
654 return draw_image(data);
655 case VOCTRL_START_SLICE:
656 return start_slice(data);
657 case VOCTRL_FULLSCREEN:
658 return fullscreen();
659 case VOCTRL_XOVERLAY_SUPPORT:
660 return VO_TRUE;
661 case VOCTRL_XOVERLAY_SET_COLORKEY:
662 return set_colorkey(data);
663 case VOCTRL_XOVERLAY_SET_WIN:
664 return set_window(data);
666 return VO_NOTIMPL;