2 vo_ggi.c - General Graphics Interface (GGI) Renderer for MPlayer
6 Uses libGGI - http://www.ggi-project.org/
9 * check on many devices
10 * implement gamma handling (VAA isn't obsoleted?)
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.
31 #include "video_out.h"
32 #include "video_out_internal.h"
34 #include "fastmemcpy.h"
41 static vo_info_t info
=
43 "General Graphics Interface (GGI) output",
51 static struct ggi_conf_s
{
57 /* source image format */
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
)
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 */
91 mode
.graphtype
= GT_8BIT
;
95 mode
.graphtype
= GT_15BIT
;
99 mode
.graphtype
= GT_16BIT
;
103 mode
.graphtype
= GT_24BIT
;
107 mode
.graphtype
= GT_32BIT
;
112 printf("[ggi] mode: ");
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");
125 if (ggiGetMode(ggi_conf
.vis
, &mode
))
127 mp_msg(MSGT_VO
, MSGL_ERR
, "[ggi] unable to get mode\n");
131 if ((mode
.graphtype
== GT_INVALID
) || (mode
.graphtype
== GT_AUTO
))
133 mp_msg(MSGT_VO
, MSGL_ERR
, "[ggi] not supported depth/bpp\n");
137 ggi_conf
.gmode
= mode
;
140 printf("[ggi] mode: ");
145 vo_depthonscreen
= GT_DEPTH(mode
.graphtype
);
146 vo_screenwidth
= mode
.visible
.x
;
147 vo_screenheight
= mode
.visible
.y
;
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
);
165 if (IMGFMT_IS_BGR(ggi_conf
.srcformat
))
167 ggi_conf
.srcdepth
= IMGFMT_BGR_DEPTH(ggi_conf
.srcformat
);
171 mp_msg(MSGT_VO
, MSGL_FATAL
, "[ggi] Unknown image format: %s\n",
172 vo_format_name(ggi_conf
.srcformat
));
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
)
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;
198 static uint32_t get_image(mp_image_t
*mpi
)
200 /* GGI DirectRendering supports (yet) only BGR/RGB modes */
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
)) ||
208 (mpi
->imgfmt
!= ggi_conf
.srcformat
) ||
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
)
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
;
226 if (ggi_conf
.voflags
& VOFLAG_FLIPPING
)
228 mpi
->stride
[0] = -mpi
->stride
[0];
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
);
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
,
257 ggiPutHLine(ggi_conf
.vis
, x
, y
, w
, src
[0]);
261 static uint32_t query_format(uint32_t format
)
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
))
286 mode
.graphtype
= GT_8BIT
;
290 mode
.graphtype
= GT_15BIT
;
294 mode
.graphtype
= GT_16BIT
;
298 mode
.graphtype
= GT_24BIT
;
302 mode
.graphtype
= GT_32BIT
;
305 if (ggiCheckMode(ggi_conf
.vis
, &mode
))
311 return(VFCAP_CSP_SUPPORTED
);
318 static uint32_t preinit(const char *arg
)
322 mp_msg(MSGT_VO
, MSGL_FATAL
, "[ggi] unable to initialize GGI\n");
327 ggi_conf
.driver
= strdup(arg
);
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
);
339 mp_msg(MSGT_VO
, MSGL_V
, "[ggi] using '%s' output\n",
340 (ggi_conf
.driver
== NULL
) ? "default" : ggi_conf
.driver
);
345 static void uninit(void)
348 free(ggi_conf
.driver
);
349 ggiClose(ggi_conf
.vis
);
353 static uint32_t control(uint32_t request
, void *data
, ...)
357 case VOCTRL_QUERY_FORMAT
:
358 return query_format(*((uint32_t*)data
));
359 case VOCTRL_GET_IMAGE
:
360 return get_image(data
);
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};
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 */
387 mplayer_put_key('*');
391 mplayer_put_key('/');
395 mplayer_put_key('+');
399 mplayer_put_key('-');
403 mplayer_put_key('o');
407 mplayer_put_key('g');
411 mplayer_put_key('z');
415 mplayer_put_key('x');
419 mplayer_put_key('m');
423 mplayer_put_key('d');
427 mplayer_put_key('q');
431 mplayer_put_key('h');
435 mplayer_put_key('l');
440 mplayer_put_key('p');
443 mplayer_put_key(KEY_UP
);
446 mplayer_put_key(KEY_DOWN
);
449 mplayer_put_key(KEY_LEFT
);
452 mplayer_put_key(KEY_RIGHT
);
455 mplayer_put_key(KEY_PAGE_UP
);
458 mplayer_put_key(KEY_PAGE_DOWN
);