10l initial patch by Oded Shimon <ods15 at ods15.dyndns.org>
[mplayer/greg.git] / libvo / vo_ggi.c
blob46e7926f24a69ffa61a1e339f43906908b5b813f
1 /*
2 vo_ggi.c - General Graphics Interface (GGI) Renderer for MPlayer
4 (C) Alex Beregszaszi
6 Uses libGGI - http://www.ggi-project.org/
8 TODO:
9 * check on many devices
10 * implement gamma handling (VAA isn't obsoleted?)
12 BUGS:
13 * palettized playback has bad colors, probably swapped palette?
14 * fbdev & DR produces two downscaled images
15 * fbdev & FLIP (& DR) produces no image
17 Thanks to Andreas Beck for his patches.
19 Many thanks to Atmosfear, he hacked this driver to work with Planar
20 formats, and he fixed the RGB handling.
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
28 #include "mp_msg.h"
30 #include "config.h"
31 #include "video_out.h"
32 #include "video_out_internal.h"
34 #include "fastmemcpy.h"
36 #include <ggi/ggi.h>
38 /* maximum buffers */
39 #undef GGI_FLIP
41 static vo_info_t info =
43 "General Graphics Interface (GGI) output",
44 "ggi",
45 "Alex Beregszaszi",
46 "major"
49 LIBVO_EXTERN (ggi)
51 static struct ggi_conf_s {
52 char *driver;
54 ggi_visual_t vis;
55 ggi_mode gmode;
57 /* source image format */
58 int srcwidth;
59 int srcheight;
60 int srcformat;
61 int srcdepth;
62 int srcbpp;
64 /* destination */
65 int dstwidth;
66 int dstheight;
68 int async;
70 int voflags;
71 } ggi_conf;
73 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width,
74 uint32_t d_height, uint32_t flags, char *title, uint32_t format)
76 ggi_mode mode =
78 1, /* frames */
79 { width, height }, /* visible */
80 { GGI_AUTO, GGI_AUTO }, /* virt */
81 { GGI_AUTO, GGI_AUTO }, /* size */
82 GT_AUTO, /* graphtype */
83 { GGI_AUTO, GGI_AUTO } /* dots per pixel */
85 int i;
87 switch(format)
89 case IMGFMT_RGB|8:
90 case IMGFMT_BGR|8:
91 mode.graphtype = GT_8BIT;
92 break;
93 case IMGFMT_RGB|15:
94 case IMGFMT_BGR|15:
95 mode.graphtype = GT_15BIT;
96 break;
97 case IMGFMT_RGB|16:
98 case IMGFMT_BGR|16:
99 mode.graphtype = GT_16BIT;
100 break;
101 case IMGFMT_RGB|24:
102 case IMGFMT_BGR|24:
103 mode.graphtype = GT_24BIT;
104 break;
105 case IMGFMT_RGB|32:
106 case IMGFMT_BGR|32:
107 mode.graphtype = GT_32BIT;
108 break;
111 #if 0
112 printf("[ggi] mode: ");
113 ggiPrintMode(&mode);
114 printf("\n");
115 #endif
117 ggiCheckMode(ggi_conf.vis, &mode);
119 if (ggiSetMode(ggi_conf.vis, &mode))
121 mp_msg(MSGT_VO, MSGL_ERR, "[ggi] unable to set mode\n");
122 return(-1);
125 if (ggiGetMode(ggi_conf.vis, &mode))
127 mp_msg(MSGT_VO, MSGL_ERR, "[ggi] unable to get mode\n");
128 return(-1);
131 if ((mode.graphtype == GT_INVALID) || (mode.graphtype == GT_AUTO))
133 mp_msg(MSGT_VO, MSGL_ERR, "[ggi] not supported depth/bpp\n");
134 return(-1);
137 ggi_conf.gmode = mode;
139 #if 0
140 printf("[ggi] mode: ");
141 ggiPrintMode(&mode);
142 printf("\n");
143 #endif
145 vo_depthonscreen = GT_DEPTH(mode.graphtype);
146 vo_screenwidth = mode.visible.x;
147 vo_screenheight = mode.visible.y;
149 vo_dx = vo_dy = 0;
150 vo_dwidth = mode.virt.x;
151 vo_dheight = mode.virt.y;
152 vo_dbpp = GT_SIZE(mode.graphtype);
154 ggi_conf.srcwidth = width;
155 ggi_conf.srcheight = height;
156 ggi_conf.srcformat = format;
158 ggi_conf.voflags = flags;
160 if (IMGFMT_IS_RGB(ggi_conf.srcformat))
162 ggi_conf.srcdepth = IMGFMT_RGB_DEPTH(ggi_conf.srcformat);
164 else
165 if (IMGFMT_IS_BGR(ggi_conf.srcformat))
167 ggi_conf.srcdepth = IMGFMT_BGR_DEPTH(ggi_conf.srcformat);
169 else
171 mp_msg(MSGT_VO, MSGL_FATAL, "[ggi] Unknown image format: %s\n",
172 vo_format_name(ggi_conf.srcformat));
173 return(-1);
176 vo_dwidth = ggi_conf.dstwidth = ggi_conf.gmode.virt.x;
177 vo_dheight = ggi_conf.dstheight = ggi_conf.gmode.virt.y;
179 ggiSetFlags(ggi_conf.vis, GGIFLAG_ASYNC);
181 if (GT_SCHEME(mode.graphtype) == GT_PALETTE)
182 ggiSetColorfulPalette(ggi_conf.vis);
184 if (ggiGetFlags(ggi_conf.vis) & GGIFLAG_ASYNC)
185 ggi_conf.async = 1;
187 mp_msg(MSGT_VO, MSGL_INFO, "[ggi] input: %dx%dx%d, output: %dx%dx%d\n",
188 ggi_conf.srcwidth, ggi_conf.srcheight, ggi_conf.srcdepth,
189 vo_dwidth, vo_dheight, vo_dbpp);
190 mp_msg(MSGT_VO, MSGL_INFO, "[ggi] async mode: %s\n",
191 ggi_conf.async ? "yes" : "no");
193 ggi_conf.srcbpp = (ggi_conf.srcdepth+7)/8;
195 return(0);
198 static uint32_t get_image(mp_image_t *mpi)
200 /* GGI DirectRendering supports (yet) only BGR/RGB modes */
201 if (
202 #if 1
203 (IMGFMT_IS_RGB(mpi->imgfmt) &&
204 (IMGFMT_RGB_DEPTH(mpi->imgfmt) != vo_dbpp)) ||
205 (IMGFMT_IS_BGR(mpi->imgfmt) &&
206 (IMGFMT_BGR_DEPTH(mpi->imgfmt) != vo_dbpp)) ||
207 #else
208 (mpi->imgfmt != ggi_conf.srcformat) ||
209 #endif
210 ((mpi->type != MP_IMGTYPE_STATIC) && (mpi->type != MP_IMGTYPE_TEMP)) ||
211 (mpi->flags & MP_IMGFLAG_PLANAR) ||
212 (mpi->flags & MP_IMGFLAG_YUV) ||
213 (mpi->width != ggi_conf.srcwidth) ||
214 (mpi->height != ggi_conf.srcheight)
216 return(VO_FALSE);
218 mpi->planes[1] = mpi->planes[2] = NULL;
219 mpi->stride[1] = mpi->stride[2] = 0;
221 mpi->stride[0] = ggi_conf.srcwidth*ggi_conf.srcbpp;
222 mpi->planes[0] = NULL;
223 mpi->flags |= MP_IMGFLAG_DIRECT;
225 #ifdef GGI_FLIP
226 if (ggi_conf.voflags & VOFLAG_FLIPPING)
228 mpi->stride[0] = -mpi->stride[0];
230 #endif
232 return(VO_TRUE);
236 static uint32_t draw_frame(uint8_t *src[])
238 ggiPutBox(ggi_conf.vis, 0, 0, ggi_conf.dstwidth, ggi_conf.dstheight, src[0]);
239 ggiFlush(ggi_conf.vis);
241 return(0);
244 static void draw_osd(void)
249 static void flip_page(void)
251 ggiFlush(ggi_conf.vis);
254 static uint32_t draw_slice(uint8_t *src[], int stride[], int w, int h,
255 int x, int y)
257 ggiPutHLine(ggi_conf.vis, x, y, w, src[0]);
258 return(1);
261 static uint32_t query_format(uint32_t format)
263 ggi_mode mode;
265 if ((!vo_depthonscreen || !vo_dbpp) && ggi_conf.vis)
267 if (ggiGetMode(ggi_conf.vis, &mode) == 0)
269 vo_depthonscreen = GT_DEPTH(mode.graphtype);
270 vo_dbpp = GT_SIZE(mode.graphtype);
274 if ((IMGFMT_IS_BGR(format) && (IMGFMT_BGR_DEPTH(format) == vo_dbpp)) ||
275 (IMGFMT_IS_RGB(format) && (IMGFMT_RGB_DEPTH(format) == vo_dbpp)))
277 return(VFCAP_CSP_SUPPORTED|VFCAP_CSP_SUPPORTED_BY_HW);
280 if (IMGFMT_IS_BGR(format) || IMGFMT_IS_RGB(format))
282 switch(format)
284 case IMGFMT_RGB|8:
285 case IMGFMT_BGR|8:
286 mode.graphtype = GT_8BIT;
287 break;
288 case IMGFMT_RGB|15:
289 case IMGFMT_BGR|15:
290 mode.graphtype = GT_15BIT;
291 break;
292 case IMGFMT_RGB|16:
293 case IMGFMT_BGR|16:
294 mode.graphtype = GT_16BIT;
295 break;
296 case IMGFMT_RGB|24:
297 case IMGFMT_BGR|24:
298 mode.graphtype = GT_24BIT;
299 break;
300 case IMGFMT_RGB|32:
301 case IMGFMT_BGR|32:
302 mode.graphtype = GT_32BIT;
303 break;
305 if (ggiCheckMode(ggi_conf.vis, &mode))
307 return 0;
309 else
311 return(VFCAP_CSP_SUPPORTED);
315 return(0);
318 static uint32_t preinit(const char *arg)
320 if (ggiInit() != 0)
322 mp_msg(MSGT_VO, MSGL_FATAL, "[ggi] unable to initialize GGI\n");
323 return(-1);
326 if ((char *)arg)
327 ggi_conf.driver = strdup(arg);
328 else
329 ggi_conf.driver = NULL;
331 if ((ggi_conf.vis = ggiOpen(ggi_conf.driver)) == NULL)
333 mp_msg(MSGT_VO, MSGL_FATAL, "[ggi] unable to open '%s' output\n",
334 (ggi_conf.driver == NULL) ? "default" : ggi_conf.driver);
335 ggiExit();
336 return(-1);
339 mp_msg(MSGT_VO, MSGL_V, "[ggi] using '%s' output\n",
340 (ggi_conf.driver == NULL) ? "default" : ggi_conf.driver);
342 return 0;
345 static void uninit(void)
347 if (ggi_conf.driver)
348 free(ggi_conf.driver);
349 ggiClose(ggi_conf.vis);
350 ggiExit();
353 static uint32_t control(uint32_t request, void *data, ...)
355 switch(request)
357 case VOCTRL_QUERY_FORMAT:
358 return query_format(*((uint32_t*)data));
359 case VOCTRL_GET_IMAGE:
360 return get_image(data);
362 return VO_NOTIMPL;
365 /* EVENT handling */
366 #include "osdep/keycodes.h"
367 extern void mplayer_put_key(int code);
369 static void check_events(void)
371 struct timeval tv = {0, 0};
372 ggi_event event;
373 ggi_event_mask mask;
375 if ((mask = ggiEventPoll(ggi_conf.vis, emAll, &tv)))
376 if (ggiEventRead(ggi_conf.vis, &event, emAll) != 0)
378 mp_dbg(MSGT_VO, MSGL_DBG3, "type: %4x, origin: %4x, sym: %4x, label: %4x, button=%4x\n",
379 event.any.origin, event.any.type, event.key.sym, event.key.label, event.key.button);
381 if (event.key.type == evKeyPress)
383 switch(event.key.sym)
385 case GIIK_PAsterisk: /* PStar */
386 case GIIUC_Asterisk:
387 mplayer_put_key('*');
388 break;
389 case GIIK_PSlash:
390 case GIIUC_Slash:
391 mplayer_put_key('/');
392 break;
393 case GIIK_PPlus:
394 case GIIUC_Plus:
395 mplayer_put_key('+');
396 break;
397 case GIIK_PMinus:
398 case GIIUC_Minus:
399 mplayer_put_key('-');
400 break;
401 case GIIUC_o:
402 case GIIUC_O:
403 mplayer_put_key('o');
404 break;
405 case GIIUC_g:
406 case GIIUC_G:
407 mplayer_put_key('g');
408 break;
409 case GIIUC_z:
410 case GIIUC_Z:
411 mplayer_put_key('z');
412 break;
413 case GIIUC_x:
414 case GIIUC_X:
415 mplayer_put_key('x');
416 break;
417 case GIIUC_m:
418 case GIIUC_M:
419 mplayer_put_key('m');
420 break;
421 case GIIUC_d:
422 case GIIUC_D:
423 mplayer_put_key('d');
424 break;
425 case GIIUC_q:
426 case GIIUC_Q:
427 mplayer_put_key('q');
428 break;
429 case GIIUC_h:
430 case GIIUC_H:
431 mplayer_put_key('h');
432 break;
433 case GIIUC_l:
434 case GIIUC_L:
435 mplayer_put_key('l');
436 break;
437 case GIIUC_Space:
438 case GIIUC_p:
439 case GIIUC_P:
440 mplayer_put_key('p');
441 break;
442 case GIIK_Up:
443 mplayer_put_key(KEY_UP);
444 break;
445 case GIIK_Down:
446 mplayer_put_key(KEY_DOWN);
447 break;
448 case GIIK_Left:
449 mplayer_put_key(KEY_LEFT);
450 break;
451 case GIIK_Right:
452 mplayer_put_key(KEY_RIGHT);
453 break;
454 case GIIK_PageUp:
455 mplayer_put_key(KEY_PAGE_UP);
456 break;
457 case GIIK_PageDown:
458 mplayer_put_key(KEY_PAGE_DOWN);
459 break;
460 default:
461 break;
465 return;