2 * General Graphics Interface (GGI) vo driver
4 * copyright (C) 2001 Alex Beregszaszi
6 * Uses libGGI - http://www.ggi-project.org/
9 * * implement gamma handling (VAA isn't obsoleted?)
11 * Thanks to Andreas Beck for his patches.
13 * Many thanks to Atmosfear, he hacked this driver to work with planar
14 * formats, and he fixed the RGB handling.
16 * This file is part of MPlayer.
18 * MPlayer is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
23 * MPlayer is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License along
29 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
30 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
41 #include "video_out.h"
42 #include "video_out_internal.h"
55 static const vo_info_t info
=
57 "General Graphics Interface (GGI) output",
63 const LIBVO_EXTERN(ggi
)
66 static struct ggi_conf_s
{
72 /* source image format */
90 static void window_ontop(void)
92 mp_msg(MSGT_VO
, MSGL_V
, "[ggi] debug: window_ontop() called\n");
93 ggiWmhZOrder(ggi_conf
.vis
, ZO_TOP
);
99 static void set_graphtype(uint32_t format
, ggi_mode
*mode
)
103 mode
->graphtype
= GT_4BIT
;
106 mode
->graphtype
= GT_4BIT
;
107 GT_SETSUBSCHEME(mode
->graphtype
, GT_SUB_HIGHBIT_RIGHT
);
111 mode
->graphtype
= GT_8BIT
;
115 mode
->graphtype
= GT_15BIT
;
119 mode
->graphtype
= GT_16BIT
;
123 mode
->graphtype
= GT_24BIT
;
127 mode
->graphtype
= GT_32BIT
;
134 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
135 uint32_t d_height
, uint32_t flags
, char *title
,
140 {width
, height
}, /* visible */
141 {GGI_AUTO
, GGI_AUTO
}, /* virt */
142 {GGI_AUTO
, GGI_AUTO
}, /* size */
143 GT_AUTO
, /* graphtype */
144 {GGI_AUTO
, GGI_AUTO
} /* dots per pixel */
148 set_graphtype(format
, &mode
);
151 printf("[ggi] mode: ");
156 ggiCheckMode(ggi_conf
.vis
, &mode
);
158 if (ggiSetMode(ggi_conf
.vis
, &mode
) < 0) {
159 mp_msg(MSGT_VO
, MSGL_ERR
, "[ggi] unable to set display mode\n");
162 if (ggiGetMode(ggi_conf
.vis
, &mode
) < 0) {
163 mp_msg(MSGT_VO
, MSGL_ERR
, "[ggi] unable to get display mode\n");
166 if ((mode
.graphtype
== GT_INVALID
)
167 || (mode
.graphtype
== GT_AUTO
))
169 mp_msg(MSGT_VO
, MSGL_ERR
, "[ggi] not supported depth/bpp\n");
174 printf("[ggi] mode: ");
181 ggiWmhSetTitle(ggi_conf
.vis
, title
);
182 if (vo_ontop
) window_ontop();
185 ggiSetFlags(ggi_conf
.vis
, GGIFLAG_ASYNC
);
187 if (GT_SCHEME(mode
.graphtype
) == GT_PALETTE
)
188 ggiSetColorfulPalette(ggi_conf
.vis
);
190 if (GT_SCHEME(mode
.graphtype
) != GT_TRUECOLOR
) {
193 ggi_conf
.drawvis
= ggiOpen("display-memory", NULL
);
194 if (ggi_conf
.drawvis
== NULL
) {
195 mp_msg(MSGT_VO
, MSGL_ERR
,
196 "[ggi] unable to get backbuffer for conversion\n");
199 memcpy(&drawmode
, &mode
, sizeof(ggi_mode
));
200 drawmode
.graphtype
= GT_32BIT
;
201 drawmode
.size
.x
= GGI_AUTO
;
202 drawmode
.size
.y
= GGI_AUTO
;
203 ggiCheckMode(ggi_conf
.drawvis
, &drawmode
);
204 if (ggiSetMode(ggi_conf
.drawvis
, &drawmode
) < 0) {
205 mp_msg(MSGT_VO
, MSGL_ERR
,
206 "[ggi] unable to set backbuffer mode\n");
209 mode
.graphtype
= drawmode
.graphtype
;
211 ggiSetFlags(ggi_conf
.drawvis
, GGIFLAG_ASYNC
);
213 vo_depthonscreen
= GT_DEPTH(mode
.graphtype
);
214 vo_screenwidth
= mode
.virt
.x
;
215 vo_screenheight
= mode
.virt
.y
;
219 vo_dbpp
= GT_SIZE(mode
.graphtype
);
222 /* calculate top, left corner */
223 vo_dx
= (vo_screenwidth
- vo_dwidth
) / 2;
224 vo_dy
= (vo_screenheight
- vo_dheight
) / 2;
227 ggi_conf
.srcwidth
= width
;
228 ggi_conf
.srcheight
= height
;
229 ggi_conf
.srcformat
= format
;
231 ggi_conf
.voflags
= flags
;
233 if (IMGFMT_IS_RGB(ggi_conf
.srcformat
)) {
234 ggi_conf
.srcdepth
= IMGFMT_RGB_DEPTH(ggi_conf
.srcformat
);
235 } else if (IMGFMT_IS_BGR(ggi_conf
.srcformat
)) {
236 ggi_conf
.srcdepth
= IMGFMT_BGR_DEPTH(ggi_conf
.srcformat
);
238 mp_msg(MSGT_VO
, MSGL_FATAL
, "[ggi] Unknown image format: %s\n",
239 vo_format_name(ggi_conf
.srcformat
));
243 mp_msg(MSGT_VO
, MSGL_INFO
, "[ggi] input: %dx%dx%d, output: %dx%dx%d\n",
244 ggi_conf
.srcwidth
, ggi_conf
.srcheight
, ggi_conf
.srcdepth
,
245 mode
.virt
.x
, mode
.virt
.y
, vo_dbpp
);
247 ggi_conf
.srcbpp
= (ggi_conf
.srcdepth
+ 7) / 8;
249 ggi_conf
.flushregion
.x1
= vo_dx
;
250 ggi_conf
.flushregion
.y1
= vo_dy
;
251 ggi_conf
.flushregion
.x2
= vo_dwidth
;
252 ggi_conf
.flushregion
.y2
= vo_dheight
;
257 static uint32_t get_image(mp_image_t
*mpi
)
259 /* GGI DirectRendering supports (yet) only BGR/RGB modes */
260 if (!((IMGFMT_IS_BGR(mpi
->imgfmt
)) &&
261 (IMGFMT_BGR_DEPTH(mpi
->imgfmt
) == vo_dbpp
)))
266 if (!((IMGFMT_IS_RGB(mpi
->imgfmt
)) &&
267 (IMGFMT_RGB_DEPTH(mpi
->imgfmt
) == vo_dbpp
)))
272 if (!((mpi
->width
== ggi_conf
.srcwidth
) &&
273 (mpi
->height
== ggi_conf
.srcheight
)))
278 mpi
->planes
[1] = mpi
->planes
[2] = NULL
;
279 mpi
->stride
[1] = mpi
->stride
[2] = 0;
281 mpi
->planes
[0] = NULL
;
282 mpi
->stride
[0] = ggi_conf
.srcwidth
* ggi_conf
.srcbpp
;
283 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
286 if (ggi_conf
.voflags
& VOFLAG_FLIPPING
) {
287 mpi
->stride
[0] = -mpi
->stride
[0];
295 static int draw_frame(uint8_t *src
[])
297 ggiPutBox(ggi_conf
.drawvis
, vo_dx
, vo_dy
,
298 vo_dwidth
, vo_dheight
, src
[0]);
300 ggi_conf
.flushregion
.x1
= vo_dx
;
301 ggi_conf
.flushregion
.y1
= vo_dy
;
302 ggi_conf
.flushregion
.x2
= vo_dwidth
;
303 ggi_conf
.flushregion
.y2
= vo_dheight
;
308 static void draw_osd(void)
313 static void flip_page(void)
315 if (ggi_conf
.drawvis
!= ggi_conf
.vis
) {
317 ggiFlushRegion(ggi_conf
.drawvis
,
318 ggi_conf
.flushregion
.x1
, ggi_conf
.flushregion
.y1
,
319 ggi_conf
.flushregion
.x2
- ggi_conf
.flushregion
.x1
,
320 ggi_conf
.flushregion
.y2
- ggi_conf
.flushregion
.y1
);
322 ggiCrossBlit(ggi_conf
.drawvis
,
323 ggi_conf
.flushregion
.x1
, ggi_conf
.flushregion
.y1
,
324 ggi_conf
.flushregion
.x2
- ggi_conf
.flushregion
.x1
,
325 ggi_conf
.flushregion
.y2
- ggi_conf
.flushregion
.y1
,
327 ggi_conf
.flushregion
.x1
, ggi_conf
.flushregion
.y1
);
330 ggiFlushRegion(ggi_conf
.vis
,
331 ggi_conf
.flushregion
.x1
, ggi_conf
.flushregion
.y1
,
332 ggi_conf
.flushregion
.x2
- ggi_conf
.flushregion
.x1
,
333 ggi_conf
.flushregion
.y2
- ggi_conf
.flushregion
.y1
);
335 ggi_conf
.flushregion
.x1
= ggi_conf
.flushregion
.x2
= -1;
336 ggi_conf
.flushregion
.y1
= ggi_conf
.flushregion
.y2
= -1;
339 static int draw_slice(uint8_t *src
[], int stride
[],
340 int w
, int h
, int x
, int y
)
342 ggiPutBox(ggi_conf
.drawvis
, vo_dx
+ x
, vo_dy
+ y
, w
, h
, src
[0]);
344 if ((ggi_conf
.flushregion
.x1
== -1) ||
345 ((vo_dx
+ x
) < ggi_conf
.flushregion
.x1
))
347 ggi_conf
.flushregion
.x1
= vo_dx
+ x
;
349 if ((ggi_conf
.flushregion
.y1
== -1) ||
350 ((vo_dy
+ y
) < ggi_conf
.flushregion
.y1
))
352 ggi_conf
.flushregion
.y1
= vo_dy
+ y
;
354 if ((ggi_conf
.flushregion
.x2
== -1) ||
355 ((vo_dx
+ x
+ w
) > ggi_conf
.flushregion
.x2
))
357 ggi_conf
.flushregion
.x2
= vo_dx
+ x
+ w
;
359 if ((ggi_conf
.flushregion
.y2
== -1) ||
360 ((vo_dy
+ y
+ h
) > ggi_conf
.flushregion
.y2
))
362 ggi_conf
.flushregion
.y2
= vo_dy
+ y
+ h
;
368 static int query_format(uint32_t format
)
373 vfcap
= VFCAP_CSP_SUPPORTED
374 | VFCAP_CSP_SUPPORTED_BY_HW
375 | VFCAP_ACCEPT_STRIDE
;
377 if ((!vo_depthonscreen
|| !vo_dbpp
) && ggi_conf
.vis
) {
378 if (ggiGetMode(ggi_conf
.vis
, &mode
) == 0) {
379 vo_depthonscreen
= GT_DEPTH(mode
.graphtype
);
380 vo_dbpp
= GT_SIZE(mode
.graphtype
);
382 if (GT_SCHEME(mode
.graphtype
) == GT_AUTO
) {
383 ggiCheckMode(ggi_conf
.vis
, &mode
);
385 if (GT_SCHEME(mode
.graphtype
) != GT_TRUECOLOR
) {
386 mode
.graphtype
= GT_32BIT
;
387 vo_depthonscreen
= GT_DEPTH(mode
.graphtype
);
388 vo_dbpp
= GT_SIZE(mode
.graphtype
);
391 if ((IMGFMT_IS_BGR(format
) && (IMGFMT_BGR_DEPTH(format
) == vo_dbpp
)) ||
392 (IMGFMT_IS_RGB(format
) && (IMGFMT_RGB_DEPTH(format
) == vo_dbpp
)))
396 if (IMGFMT_IS_BGR(format
) || IMGFMT_IS_RGB(format
)) {
397 set_graphtype(format
, &mode
);
399 if (ggiCheckMode(ggi_conf
.drawvis
, &mode
) < 0) {
408 static int preinit(const char *arg
)
410 if (ggiInit() != 0) {
411 mp_msg(MSGT_VO
, MSGL_FATAL
, "[ggi] unable to initialize GGI\n");
415 if (ggiWmhInit() < 0) {
416 mp_msg(MSGT_VO
, MSGL_FATAL
, "[ggi] unable to initialize libggiwmh\n");
423 ggi_conf
.driver
= strdup(arg
);
424 while (ggi_conf
.driver
[i
] != '\0') {
425 if (ggi_conf
.driver
[i
] == '.')
426 ggi_conf
.driver
[i
] = ',';
430 ggi_conf
.driver
= NULL
;
433 ggi_conf
.vis
= ggiOpen(ggi_conf
.driver
);
434 if (ggi_conf
.vis
== NULL
) {
435 mp_msg(MSGT_VO
, MSGL_FATAL
, "[ggi] unable to open '%s' output\n",
436 (ggi_conf
.driver
== NULL
) ? "default" : ggi_conf
.driver
);
440 ggi_conf
.drawvis
= ggi_conf
.vis
;
444 ggiWmhAttach(ggi_conf
.vis
);
448 mp_msg(MSGT_VO
, MSGL_V
, "[ggi] using '%s' output\n",
449 (ggi_conf
.driver
== NULL
) ? "default" : ggi_conf
.driver
);
454 static void uninit(void)
457 free(ggi_conf
.driver
);
460 ggiWmhDetach(ggi_conf
.vis
);
464 if (ggi_conf
.drawvis
!= NULL
&& ggi_conf
.drawvis
!= ggi_conf
.vis
)
465 ggiClose(ggi_conf
.drawvis
);
467 ggiClose(ggi_conf
.vis
);
471 static int control(uint32_t request
, void *data
, ...)
474 case VOCTRL_QUERY_FORMAT
:
475 return query_format(*((uint32_t *) data
));
476 case VOCTRL_GET_IMAGE
:
477 return get_image(data
);
480 vo_ontop
= (!(vo_ontop
));
489 #include "osdep/keycodes.h"
491 static void check_events(void)
493 struct timeval tv
= {0, 0};
497 if ((mask
= ggiEventPoll(ggi_conf
.vis
, emAll
, &tv
))) {
498 if (ggiEventRead(ggi_conf
.vis
, &event
, emAll
) != 0) {
499 mp_dbg(MSGT_VO
, MSGL_DBG3
,
500 "type: %4x, origin: %4x, "
501 "sym: %4x, label: %4x, button=%4x\n",
502 event
.any
.origin
, event
.any
.type
, event
.key
.sym
,
503 event
.key
.label
, event
.key
.button
);
505 switch (event
.any
.type
) {
507 switch (event
.key
.sym
) {
508 case GIIK_PAsterisk
: /* PStar */
510 mplayer_put_key('*');
514 mplayer_put_key('/');
518 mplayer_put_key('+');
522 mplayer_put_key('-');
526 mplayer_put_key('o');
530 mplayer_put_key('g');
534 mplayer_put_key('z');
538 mplayer_put_key('x');
542 mplayer_put_key('m');
546 mplayer_put_key('d');
550 mplayer_put_key('q');
554 mplayer_put_key('h');
558 mplayer_put_key('l');
563 mplayer_put_key('p');
566 mplayer_put_key(KEY_UP
);
569 mplayer_put_key(KEY_DOWN
);
572 mplayer_put_key(KEY_LEFT
);
575 mplayer_put_key(KEY_RIGHT
);
578 mplayer_put_key(KEY_PAGE_UP
);
581 mplayer_put_key(KEY_PAGE_DOWN
);