Mercurial > mplayer.hg
annotate libvo/vo_3dfx.c @ 9593:e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
Syntax is we decided, so you can give the nomes or not with both
vop and vf. vf take precedence over vop.
author | albeu |
---|---|
date | Sat, 15 Mar 2003 18:01:02 +0000 |
parents | 5b39e79af5fe |
children | fb0b7fe53645 |
rev | line source |
---|---|
1 | 1 /* |
2 * video_out_3dfx.c | |
3 * | |
4 * Copyright (C) Colin Cross Apr 2000 | |
5 * | |
6 * This file heavily based off of video_out_mga.c of Aaron Holtzman's | |
7 * mpeg2dec | |
8 * | |
9 * mpeg2dec is free software; you can redistribute it and/or modify | |
10 * it under the terms of the GNU General Public License as published by | |
11 * the Free Software Foundation; either version 2, or (at your option) | |
12 * any later version. | |
13 * | |
14 * mpeg2dec is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 * GNU General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU General Public License | |
20 * along with GNU Make; see the file COPYING. If not, write to | |
21 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 * | |
23 */ | |
24 | |
25 #include <stdio.h> | |
26 #include <stdlib.h> | |
27 #include <string.h> | |
28 | |
29 #include "config.h" | |
30 #include "video_out.h" | |
31 #include "video_out_internal.h" | |
32 | |
33 #include <sys/ioctl.h> | |
34 #include <unistd.h> | |
35 #include <fcntl.h> | |
36 #include <sys/mman.h> | |
37 #include <errno.h> | |
38 #include <wchar.h> | |
39 #include <signal.h> | |
40 | |
41 #include <X11/Xlib.h> | |
42 #include <X11/extensions/xf86dga.h> | |
43 #include <X11/Xutil.h> | |
44 | |
45 //#define LOG(x) syslog(LOG_USER | LOG_DEBUG,x) | |
46 #define LOG(x) | |
47 | |
48 #include "drivers/3dfx.h" | |
49 | |
354 | 50 #include "fastmemcpy.h" |
350 | 51 |
8148
5b39e79af5fe
removed get_info, using the same sheme as in libmpcodecs instead
alex
parents:
7124
diff
changeset
|
52 static vo_info_t info = |
1 | 53 { |
54 "3dfx (/dev/3dfx)", | |
55 "3dfx", | |
56 "Colin Cross <colin@MIT.EDU>", | |
57 "" | |
58 }; | |
59 | |
8148
5b39e79af5fe
removed get_info, using the same sheme as in libmpcodecs instead
alex
parents:
7124
diff
changeset
|
60 LIBVO_EXTERN(3dfx) |
5b39e79af5fe
removed get_info, using the same sheme as in libmpcodecs instead
alex
parents:
7124
diff
changeset
|
61 |
1 | 62 static uint32_t is_fullscreen = 1; |
63 | |
64 static uint32_t vidwidth; | |
65 static uint32_t vidheight; | |
66 | |
67 static uint32_t screenwidth; | |
68 static uint32_t screenheight; | |
69 static uint32_t screendepth = 2; //Only 16bpp supported right now | |
70 | |
71 static uint32_t dispwidth = 1280; // You can change these to whatever you want | |
72 static uint32_t dispheight = 720; // 16:9 screen ratio?? | |
73 static uint32_t dispx; | |
74 static uint32_t dispy; | |
75 | |
76 static uint32_t *vidpage0; | |
77 static uint32_t *vidpage1; | |
78 static uint32_t *vidpage2; | |
79 | |
80 static uint32_t vidpage0offset; | |
81 static uint32_t vidpage1offset; | |
82 static uint32_t vidpage2offset; | |
83 | |
84 // Current pointer into framebuffer where display is located | |
85 static uint32_t targetoffset; | |
86 | |
87 static uint32_t page_space; | |
88 | |
89 static voodoo_io_reg *reg_IO; | |
90 static voodoo_2d_reg *reg_2d; | |
91 static voodoo_yuv_reg *reg_YUV; | |
92 static voodoo_yuv_fb *fb_YUV; | |
93 | |
94 static uint32_t *memBase0, *memBase1; | |
95 static uint32_t baseAddr0, baseAddr1; | |
96 | |
97 | |
98 /* X11 related variables */ | |
99 static Display *display; | |
100 static Window mywindow; | |
101 static int bpp; | |
102 static XWindowAttributes attribs; | |
103 static int X_already_started = 0; | |
104 | |
105 | |
106 static void | |
107 restore(void) | |
108 { | |
109 //reg_IO->vidDesktopStartAddr = vidpage0offset; | |
110 XF86DGADirectVideo(display,0,0); | |
111 } | |
112 | |
113 static void | |
114 sighup(int foo) | |
115 { | |
116 //reg_IO->vidDesktopStartAddr = vidpage0offset; | |
117 XF86DGADirectVideo(display,0,0); | |
118 exit(0); | |
119 } | |
120 | |
121 static void | |
122 restore_regs(voodoo_2d_reg *regs) | |
123 { | |
124 reg_2d->commandExtra = regs->commandExtra; | |
125 reg_2d->clip0Min = regs->clip0Min; | |
126 reg_2d->clip0Max = regs->clip0Max; | |
127 | |
128 reg_2d->srcBaseAddr = regs->srcBaseAddr; | |
129 reg_2d->srcXY = regs->srcXY; | |
130 reg_2d->srcFormat = regs->srcFormat; | |
131 reg_2d->srcSize = regs->srcSize; | |
132 | |
133 reg_2d->dstBaseAddr = regs->dstBaseAddr; | |
134 reg_2d->dstXY = regs->dstXY; | |
135 reg_2d->dstFormat = regs->dstFormat; | |
136 | |
137 reg_2d->dstSize = regs->dstSize; | |
138 reg_2d->command = 0; | |
139 } | |
140 | |
141 static uint32_t | |
142 create_window(Display *display) | |
143 { | |
144 int screen; | |
145 unsigned int fg, bg; | |
146 char *hello = "I hate X11"; | |
147 XSizeHints hint; | |
148 XVisualInfo vinfo; | |
149 XEvent xev; | |
150 | |
151 Colormap theCmap; | |
152 XSetWindowAttributes xswa; | |
153 unsigned long xswamask; | |
154 | |
155 if (X_already_started) | |
156 return -1; | |
157 | |
158 screen = DefaultScreen(display); | |
159 | |
160 hint.x = 0; | |
161 hint.y = 10; | |
162 hint.width = dispwidth; | |
163 hint.height = dispheight; | |
164 hint.flags = PPosition | PSize; | |
165 | |
166 bg = WhitePixel(display, screen); | |
167 fg = BlackPixel(display, screen); | |
168 | |
169 XGetWindowAttributes(display, DefaultRootWindow(display), &attribs); | |
170 bpp = attribs.depth; | |
171 if (bpp != 16) | |
172 { | |
614 | 173 printf("Only 16bpp supported!"); |
1 | 174 exit(-1); |
175 } | |
176 | |
177 XMatchVisualInfo(display,screen,bpp,TrueColor,&vinfo); | |
178 printf("visual id is %lx\n",vinfo.visualid); | |
179 | |
180 theCmap = XCreateColormap(display, RootWindow(display,screen), | |
181 vinfo.visual, AllocNone); | |
182 | |
183 xswa.background_pixel = 0; | |
184 xswa.border_pixel = 1; | |
185 xswa.colormap = theCmap; | |
186 xswamask = CWBackPixel | CWBorderPixel |CWColormap; | |
187 | |
188 | |
189 mywindow = XCreateWindow(display, RootWindow(display,screen), | |
190 hint.x, hint.y, hint.width, hint.height, 4, bpp,CopyFromParent,vinfo.visual,xswamask,&xswa); | |
1137
4c7b219e126c
patch: some X11 compliance fixed: set ClassHint and better fullscreen mode
arpi_esp
parents:
614
diff
changeset
|
191 vo_x11_classhint( display,mywindow,"3dfx" ); |
1 | 192 |
193 XSelectInput(display, mywindow, StructureNotifyMask); | |
194 | |
195 /* Tell other applications about this window */ | |
196 | |
197 XSetStandardProperties(display, mywindow, hello, hello, None, NULL, 0, &hint); | |
198 | |
199 /* Map window. */ | |
200 | |
201 XMapWindow(display, mywindow); | |
202 | |
203 /* Wait for map. */ | |
204 do | |
205 { | |
206 XNextEvent(display, &xev); | |
207 } | |
208 while (xev.type != MapNotify || xev.xmap.event != mywindow); | |
209 | |
210 XSelectInput(display, mywindow, NoEventMask); | |
211 | |
212 XFlush(display); | |
213 XSync(display, False); | |
214 | |
215 X_already_started++; | |
216 return 0; | |
217 } | |
218 | |
219 static void | |
220 dump_yuv_planar(uint32_t *y, uint32_t *u, uint32_t *v, uint32_t to, uint32_t width, uint32_t height) | |
221 { | |
222 // YUV conversion works like this: | |
223 // | |
224 // We write the Y, U, and V planes separately into 3dfx YUV Planar memory | |
225 // region. The nice chip then takes these and packs them into the YUYV | |
226 // format in the regular frame buffer, starting at yuvBaseAddr, page 2 here. | |
227 // Then we tell the 3dfx to do a Screen to Screen Stretch BLT to copy all | |
228 // of the data on page 2 onto page 1, converting it to 16 bpp RGB as it goes. | |
229 // The result is a nice image on page 1 ready for display. | |
230 | |
231 uint32_t j; | |
232 uint32_t y_imax, uv_imax, jmax; | |
233 | |
234 reg_YUV->yuvBaseAddr = to; | |
235 reg_YUV->yuvStride = screenwidth*2; | |
236 | |
237 LOG("video_out_3dfx: starting planar dump\n"); | |
238 jmax = height>>1; // vidheight/2, height of U and V planes | |
239 y_imax = width; // Y plane is twice as wide as U and V planes | |
240 uv_imax = width>>1; // vidwidth/2/4, width of U and V planes in 32-bit words | |
241 | |
242 for (j=0;j<jmax;j++) | |
243 { | |
244 //XXX this should be hand-rolled 32 bit memcpy for safeness. | |
245 memcpy(fb_YUV->U + (uint32_t) VOODOO_YUV_STRIDE* j ,((uint8_t*) u) + uv_imax* j , uv_imax); | |
246 memcpy(fb_YUV->V + (uint32_t) VOODOO_YUV_STRIDE* j ,((uint8_t*) v) + uv_imax* j , uv_imax); | |
247 memcpy(fb_YUV->Y + (uint32_t) VOODOO_YUV_STRIDE* (j<<1) ,((uint8_t*) y) + y_imax * (j<<1) , y_imax); | |
248 memcpy(fb_YUV->Y + (uint32_t) VOODOO_YUV_STRIDE*((j<<1)+1),((uint8_t*) y) + y_imax *((j<<1)+1), y_imax); | |
249 } | |
250 LOG("video_out_3dfx: done planar dump\n"); | |
251 } | |
252 | |
253 static void | |
254 screen_to_screen_stretch_blt(uint32_t to, uint32_t from, uint32_t width, uint32_t height) | |
255 { | |
256 //FIXME - this function should be called by a show_frame function that | |
257 // uses a series of blts to show only those areas not covered | |
258 // by another window | |
259 voodoo_2d_reg saved_regs; | |
260 | |
261 LOG("video_out_3dfx: saving registers\n"); | |
262 // Save VGA regs (so X kinda works when we're done) | |
263 saved_regs = *reg_2d; | |
264 | |
265 /* The following lines set up the screen to screen stretch blt from page2 to | |
266 page 1 | |
267 */ | |
268 | |
269 LOG("video_out_3dfx: setting blt registers\n"); | |
270 reg_2d->commandExtra = 4; //disable colorkeying, enable wait for v-refresh (0100b) | |
271 reg_2d->clip0Min = 0; | |
272 reg_2d->clip0Max = 0xFFFFFFFF; //no clipping | |
273 | |
274 reg_2d->srcBaseAddr = from; | |
275 reg_2d->srcXY = 0; | |
276 reg_2d->srcFormat = screenwidth*2 | VOODOO_BLT_FORMAT_YUYV; // | 1<<21; | |
277 reg_2d->srcSize = vidwidth | (vidheight << 16); | |
278 | |
279 reg_2d->dstBaseAddr = to; | |
280 reg_2d->dstXY = 0; | |
281 reg_2d->dstFormat = screenwidth*2 | VOODOO_BLT_FORMAT_16; | |
282 | |
283 reg_2d->dstSize = width | (height << 16); | |
284 | |
285 LOG("video_out_3dfx: starting blt\n"); | |
286 // Executes screen to screen stretch blt | |
287 reg_2d->command = 2 | 1<<8 | 0xCC<<24; | |
288 | |
289 LOG("video_out_3dfx: restoring regs\n"); | |
290 restore_regs(&saved_regs); | |
291 | |
292 LOG("video_out_3dfx: done blt\n"); | |
293 } | |
294 | |
295 static void | |
296 update_target(void) | |
297 { | |
298 uint32_t xp, yp, w, h, b, d; | |
299 Window root; | |
300 | |
301 XGetGeometry(display,mywindow,&root,&xp,&yp,&w,&h,&b,&d); | |
302 XTranslateCoordinates(display,mywindow,root,0,0,&xp,&yp,&root); | |
303 dispx = (uint32_t) xp; | |
304 dispy = (uint32_t) yp; | |
305 dispwidth = (uint32_t) w; | |
306 dispheight = (uint32_t) h; | |
307 | |
308 if (is_fullscreen) | |
309 targetoffset = vidpage0offset + (screenheight - dispheight)/2*screenwidth*screendepth + (screenwidth-dispwidth)/2*screendepth; | |
310 else | |
311 targetoffset = vidpage0offset + (dispy*screenwidth + dispx)*screendepth; | |
312 } | |
313 | |
314 static uint32_t | |
7124
eca7dbad0166
finally removed query_vaa, bes_da and vo_tune_info - the obsoleted libvo api
alex
parents:
6207
diff
changeset
|
315 config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format) |
1 | 316 { |
317 int fd; | |
318 char *name = ":0.0"; | |
319 pioData data; | |
320 uint32_t retval; | |
321 | |
322 if(getenv("DISPLAY")) | |
323 name = getenv("DISPLAY"); | |
324 display = XOpenDisplay(name); | |
325 | |
326 screenwidth = XDisplayWidth(display,0); | |
327 screenheight = XDisplayHeight(display,0); | |
328 | |
329 page_space = screenwidth*screenheight*screendepth; | |
330 vidpage0offset = 0; | |
331 vidpage1offset = page_space; // Use third and fourth pages | |
332 vidpage2offset = page_space*2; | |
333 | |
334 signal(SIGALRM,sighup); | |
335 //alarm(120); | |
336 | |
337 // Open driver device | |
338 if ( (fd = open("/dev/3dfx",O_RDWR) ) == -1) | |
339 { | |
614 | 340 printf("Couldn't open /dev/3dfx\n"); |
1 | 341 exit(1); |
342 } | |
343 | |
344 // Store sizes for later | |
345 vidwidth = width; | |
346 vidheight = height; | |
347 | |
348 is_fullscreen = fullscreen = 0; | |
349 if (!is_fullscreen) | |
350 create_window(display); | |
351 | |
352 // Ask 3dfx driver for base memory address 0 | |
353 data.port = 0x10; // PCI_BASE_ADDRESS_0_LINUX; | |
354 data.size = 4; | |
355 data.value = &baseAddr0; | |
356 data.device = 0; | |
357 if ((retval = ioctl(fd,_IOC(_IOC_READ,'3',3,0),&data)) < 0) | |
358 { | |
359 printf("Error: %d\n",retval); | |
360 //return -1; | |
361 } | |
362 | |
363 // Ask 3dfx driver for base memory address 1 | |
364 data.port = 0x14; // PCI_BASE_ADDRESS_1_LINUX; | |
365 data.size = 4; | |
366 data.value = &baseAddr1; | |
367 data.device = 0; | |
368 if ((retval = ioctl(fd,_IOC(_IOC_READ,'3',3,0),&data)) < 0) | |
369 { | |
370 printf("Error: %d\n",retval); | |
371 //return -1; | |
372 } | |
373 | |
374 // Map all 3dfx memory areas | |
375 memBase0 = mmap(0,0x1000000,PROT_READ | PROT_WRITE,MAP_SHARED,fd,baseAddr0); | |
376 memBase1 = mmap(0,3*page_space,PROT_READ | PROT_WRITE,MAP_SHARED,fd,baseAddr1); | |
377 if (memBase0 == (uint32_t *) 0xFFFFFFFF || memBase1 == (uint32_t *) 0xFFFFFFFF) | |
378 { | |
379 printf("Couldn't map 3dfx memory areas: %p,%p,%d\n", | |
380 memBase0,memBase1,errno); | |
381 } | |
382 | |
383 // Set up global pointers | |
384 reg_IO = (void *)memBase0 + VOODOO_IO_REG_OFFSET; | |
385 reg_2d = (void *)memBase0 + VOODOO_2D_REG_OFFSET; | |
386 reg_YUV = (void *)memBase0 + VOODOO_YUV_REG_OFFSET; | |
387 fb_YUV = (void *)memBase0 + VOODOO_YUV_PLANE_OFFSET; | |
388 | |
389 vidpage0 = (void *)memBase1 + (unsigned long int)vidpage0offset; | |
390 vidpage1 = (void *)memBase1 + (unsigned long int)vidpage1offset; | |
391 vidpage2 = (void *)memBase1 + (unsigned long int)vidpage2offset; | |
392 | |
393 // Clear pages 1,2,3 | |
394 // leave page 0, that belongs to X. | |
395 // So does part of 1. Oops. | |
396 memset(vidpage1,0x00,page_space); | |
397 memset(vidpage2,0x00,page_space); | |
398 | |
399 if (is_fullscreen) | |
400 memset(vidpage0,0x00,page_space); | |
401 | |
402 | |
403 #ifndef VOODOO_DEBUG | |
404 // Show page 0 (unblanked) | |
405 reg_IO->vidDesktopStartAddr = vidpage0offset; | |
406 | |
407 /* Stop X from messing with my video registers! | |
408 Find a better way to do this? | |
409 Currently I use DGA to tell XF86 to not screw with registers, but I can't really use it | |
410 to do FB stuff because I need to know the absolute FB position and offset FB position | |
411 to feed to BLT command | |
412 */ | |
413 //XF86DGADirectVideo(display,0,XF86DGADirectGraphics); //| XF86DGADirectMouse | XF86DGADirectKeyb); | |
414 #endif | |
415 | |
416 /* fd is deliberately not closed - if it were, mmaps might be released??? */ | |
417 | |
418 atexit(restore); | |
419 | |
420 printf("(display) 3dfx initialized %p\n",memBase1); | |
421 return 0; | |
422 } | |
423 | |
424 static uint32_t | |
425 draw_frame(uint8_t *src[]) | |
426 { | |
427 LOG("video_out_3dfx: starting display_frame\n"); | |
428 | |
429 // Put packed data onto page 2 | |
430 dump_yuv_planar((uint32_t *)src[0],(uint32_t *)src[1],(uint32_t *)src[2], | |
431 vidpage2offset,vidwidth,vidheight); | |
432 | |
433 LOG("video_out_3dfx: done display_frame\n"); | |
434 return 0; | |
435 } | |
436 | |
437 static uint32_t | |
1978 | 438 //draw_slice(uint8_t *src[], uint32_t slice_num) |
439 draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y) | |
1 | 440 { |
441 uint32_t target; | |
442 | |
1978 | 443 target = vidpage2offset + (screenwidth*2 * y); |
444 dump_yuv_planar((uint32_t *)src[0],(uint32_t *)src[1],(uint32_t *)src[2],target,vidwidth,h); | |
1 | 445 return 0; |
446 } | |
447 | |
1501
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1137
diff
changeset
|
448 static void draw_osd(void) |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1137
diff
changeset
|
449 { |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1137
diff
changeset
|
450 } |
d40f2b686846
changes according to -utf8 option, draw_osd() function added
atlka
parents:
1137
diff
changeset
|
451 |
1 | 452 static void |
453 flip_page(void) | |
454 { | |
455 //FIXME - update_target() should be called by event handler when window | |
456 // is resized or moved | |
457 update_target(); | |
458 LOG("video_out_3dfx: calling blt function\n"); | |
459 screen_to_screen_stretch_blt(targetoffset, vidpage2offset, dispwidth, dispheight); | |
460 } | |
461 | |
462 static uint32_t | |
463 query_format(uint32_t format) | |
464 { | |
6207 | 465 /* does this supports scaling? up & down? */ |
1 | 466 switch(format){ |
467 case IMGFMT_YV12: | |
468 // case IMGFMT_YUY2: | |
469 // case IMGFMT_RGB|24: | |
470 // case IMGFMT_BGR|24: | |
6207 | 471 return VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW; |
1 | 472 } |
473 return 0; | |
474 } | |
475 | |
476 static void | |
477 uninit(void) | |
478 { | |
479 } | |
480 | |
481 | |
31 | 482 static void check_events(void) |
483 { | |
484 } | |
485 | |
4352 | 486 static uint32_t preinit(const char *arg) |
487 { | |
4737
32e1f5042f65
I don't like such reports: '-vo dga:vidix or -vo x11:vidix works fine for me'
nick
parents:
4596
diff
changeset
|
488 if(arg) |
32e1f5042f65
I don't like such reports: '-vo dga:vidix or -vo x11:vidix works fine for me'
nick
parents:
4596
diff
changeset
|
489 { |
32e1f5042f65
I don't like such reports: '-vo dga:vidix or -vo x11:vidix works fine for me'
nick
parents:
4596
diff
changeset
|
490 printf("vo_3dfx: Unknown subdevice: %s\n",arg); |
32e1f5042f65
I don't like such reports: '-vo dga:vidix or -vo x11:vidix works fine for me'
nick
parents:
4596
diff
changeset
|
491 return ENOSYS; |
32e1f5042f65
I don't like such reports: '-vo dga:vidix or -vo x11:vidix works fine for me'
nick
parents:
4596
diff
changeset
|
492 } |
32e1f5042f65
I don't like such reports: '-vo dga:vidix or -vo x11:vidix works fine for me'
nick
parents:
4596
diff
changeset
|
493 return 0; |
4352 | 494 } |
31 | 495 |
4596 | 496 static uint32_t control(uint32_t request, void *data, ...) |
4352 | 497 { |
4592
5fbfd8545c3b
query_ stuff replaced by new control() - patch by David Holm
arpi
parents:
4433
diff
changeset
|
498 switch (request) { |
5fbfd8545c3b
query_ stuff replaced by new control() - patch by David Holm
arpi
parents:
4433
diff
changeset
|
499 case VOCTRL_QUERY_FORMAT: |
5fbfd8545c3b
query_ stuff replaced by new control() - patch by David Holm
arpi
parents:
4433
diff
changeset
|
500 return query_format(*((uint32_t*)data)); |
5fbfd8545c3b
query_ stuff replaced by new control() - patch by David Holm
arpi
parents:
4433
diff
changeset
|
501 } |
5fbfd8545c3b
query_ stuff replaced by new control() - patch by David Holm
arpi
parents:
4433
diff
changeset
|
502 return VO_NOTIMPL; |
4352 | 503 } |