osdep: Remove cruft
[mplayer.git] / libvo / vo_ggi.c
bloba4ded390a6ca57d824bdce181f1a23c4cffe6edf
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 * 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.
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
22 #include "mp_msg.h"
24 #include "config.h"
25 #include "video_out.h"
26 #include "video_out_internal.h"
28 #include "mp_fifo.h"
30 #include <ggi/ggi.h>
32 #ifdef HAVE_GGIWMH
33 #include <ggi/wmh.h>
34 #endif
36 /* maximum buffers */
37 #undef GGI_FLIP
39 static const vo_info_t info =
41 "General Graphics Interface (GGI) output",
42 "ggi",
43 "Alex Beregszaszi",
44 "major"
47 const LIBVO_EXTERN(ggi)
50 static struct ggi_conf_s {
51 char *driver;
53 ggi_visual_t vis;
54 ggi_visual_t drawvis;
56 /* source image format */
57 int srcwidth;
58 int srcheight;
59 int srcformat;
60 int srcdepth;
61 int srcbpp;
63 /* dirty region */
64 struct {
65 int x1, y1;
66 int x2, y2;
67 } flushregion;
69 int voflags;
71 int depthonscreen;
72 } ggi_conf;
75 #ifdef HAVE_GGIWMH
76 static void window_ontop(void)
78 mp_msg(MSGT_VO, MSGL_V, "[ggi] debug: window_ontop() called\n");
79 ggiWmhZOrder(ggi_conf.vis, ZO_TOP);
80 return;
82 #endif
85 static void set_graphtype(uint32_t format, ggi_mode *mode)
87 switch (format) {
88 case IMGFMT_RGB4:
89 mode->graphtype = GT_4BIT;
90 break;
91 case IMGFMT_BGR4:
92 mode->graphtype = GT_4BIT;
93 GT_SETSUBSCHEME(mode->graphtype, GT_SUB_HIGHBIT_RIGHT);
94 break;
95 case IMGFMT_RGB8:
96 case IMGFMT_BGR8:
97 mode->graphtype = GT_8BIT;
98 break;
99 case IMGFMT_RGB15:
100 case IMGFMT_BGR15:
101 mode->graphtype = GT_15BIT;
102 break;
103 case IMGFMT_RGB16:
104 case IMGFMT_BGR16:
105 mode->graphtype = GT_16BIT;
106 break;
107 case IMGFMT_RGB24:
108 case IMGFMT_BGR24:
109 mode->graphtype = GT_24BIT;
110 break;
111 case IMGFMT_RGB32:
112 case IMGFMT_BGR32:
113 mode->graphtype = GT_32BIT;
114 break;
117 return;
120 static int config(uint32_t width, uint32_t height, uint32_t d_width,
121 uint32_t d_height, uint32_t flags, char *title,
122 uint32_t format)
124 ggi_mode mode = {
125 1, /* frames */
126 {width, height}, /* visible */
127 {GGI_AUTO, GGI_AUTO}, /* virt */
128 {GGI_AUTO, GGI_AUTO}, /* size */
129 GT_AUTO, /* graphtype */
130 {GGI_AUTO, GGI_AUTO} /* dots per pixel */
134 set_graphtype(format, &mode);
136 #if 0
137 printf("[ggi] mode: ");
138 ggiPrintMode(&mode);
139 printf("\n");
140 #endif
142 ggiCheckMode(ggi_conf.vis, &mode);
144 if (ggiSetMode(ggi_conf.vis, &mode) < 0) {
145 mp_msg(MSGT_VO, MSGL_ERR, "[ggi] unable to set display mode\n");
146 return (-1);
148 if (ggiGetMode(ggi_conf.vis, &mode) < 0) {
149 mp_msg(MSGT_VO, MSGL_ERR, "[ggi] unable to get display mode\n");
150 return (-1);
152 if ((mode.graphtype == GT_INVALID)
153 || (mode.graphtype == GT_AUTO))
155 mp_msg(MSGT_VO, MSGL_ERR, "[ggi] not supported depth/bpp\n");
156 return (-1);
159 #if 0
160 printf("[ggi] mode: ");
161 ggiPrintMode(&mode);
162 printf("\n");
163 #endif
166 #ifdef HAVE_GGIWMH
167 ggiWmhSetTitle(ggi_conf.vis, title);
168 if (vo_ontop) window_ontop();
169 #endif
171 ggiSetFlags(ggi_conf.vis, GGIFLAG_ASYNC);
173 if (GT_SCHEME(mode.graphtype) == GT_PALETTE)
174 ggiSetColorfulPalette(ggi_conf.vis);
176 if (GT_SCHEME(mode.graphtype) != GT_TRUECOLOR) {
177 ggi_mode drawmode;
179 ggi_conf.drawvis = ggiOpen("display-memory", NULL);
180 if (ggi_conf.drawvis == NULL) {
181 mp_msg(MSGT_VO, MSGL_ERR,
182 "[ggi] unable to get backbuffer for conversion\n");
183 return -1;
185 memcpy(&drawmode, &mode, sizeof(ggi_mode));
186 drawmode.graphtype = GT_32BIT;
187 drawmode.size.x = GGI_AUTO;
188 drawmode.size.y = GGI_AUTO;
189 ggiCheckMode(ggi_conf.drawvis, &drawmode);
190 if (ggiSetMode(ggi_conf.drawvis, &drawmode) < 0) {
191 mp_msg(MSGT_VO, MSGL_ERR,
192 "[ggi] unable to set backbuffer mode\n");
193 return -1;
195 mode.graphtype = drawmode.graphtype;
197 ggiSetFlags(ggi_conf.drawvis, GGIFLAG_ASYNC);
199 ggi_conf.depthonscreen = GT_DEPTH(mode.graphtype);
200 vo_screenwidth = mode.virt.x;
201 vo_screenheight = mode.virt.y;
203 vo_dwidth = width;
204 vo_dheight = height;
205 vo_dbpp = GT_SIZE(mode.graphtype);
208 /* calculate top, left corner */
209 vo_dx = (vo_screenwidth - vo_dwidth) / 2;
210 vo_dy = (vo_screenheight - vo_dheight) / 2;
213 ggi_conf.srcwidth = width;
214 ggi_conf.srcheight = height;
215 ggi_conf.srcformat = format;
217 ggi_conf.voflags = flags;
219 if (IMGFMT_IS_RGB(ggi_conf.srcformat)) {
220 ggi_conf.srcdepth = IMGFMT_RGB_DEPTH(ggi_conf.srcformat);
221 } else if (IMGFMT_IS_BGR(ggi_conf.srcformat)) {
222 ggi_conf.srcdepth = IMGFMT_BGR_DEPTH(ggi_conf.srcformat);
223 } else {
224 mp_msg(MSGT_VO, MSGL_FATAL, "[ggi] Unknown image format: %s\n",
225 vo_format_name(ggi_conf.srcformat));
226 return (-1);
229 mp_msg(MSGT_VO, MSGL_INFO, "[ggi] input: %dx%dx%d, output: %dx%dx%d\n",
230 ggi_conf.srcwidth, ggi_conf.srcheight, ggi_conf.srcdepth,
231 mode.virt.x, mode.virt.y, vo_dbpp);
233 ggi_conf.srcbpp = (ggi_conf.srcdepth + 7) / 8;
235 ggi_conf.flushregion.x1 = vo_dx;
236 ggi_conf.flushregion.y1 = vo_dy;
237 ggi_conf.flushregion.x2 = vo_dwidth;
238 ggi_conf.flushregion.y2 = vo_dheight;
240 return (0);
243 static uint32_t get_image(mp_image_t *mpi)
245 /* GGI DirectRendering supports (yet) only BGR/RGB modes */
246 if (!((IMGFMT_IS_BGR(mpi->imgfmt)) &&
247 (IMGFMT_BGR_DEPTH(mpi->imgfmt) == vo_dbpp)))
249 return (VO_FALSE);
252 if (!((IMGFMT_IS_RGB(mpi->imgfmt)) &&
253 (IMGFMT_RGB_DEPTH(mpi->imgfmt) == vo_dbpp)))
255 return (VO_FALSE);
258 if (!((mpi->width == ggi_conf.srcwidth) &&
259 (mpi->height == ggi_conf.srcheight)))
261 return (VO_FALSE);
264 mpi->planes[1] = mpi->planes[2] = NULL;
265 mpi->stride[1] = mpi->stride[2] = 0;
267 mpi->planes[0] = NULL;
268 mpi->stride[0] = ggi_conf.srcwidth * ggi_conf.srcbpp;
269 mpi->flags |= MP_IMGFLAG_DIRECT;
271 #ifdef GGI_FLIP
272 if (ggi_conf.voflags & VOFLAG_FLIPPING) {
273 mpi->stride[0] = -mpi->stride[0];
275 #endif
277 return (VO_TRUE);
281 static int draw_frame(uint8_t *src[])
283 ggiPutBox(ggi_conf.drawvis, vo_dx, vo_dy,
284 vo_dwidth, vo_dheight, src[0]);
286 ggi_conf.flushregion.x1 = vo_dx;
287 ggi_conf.flushregion.y1 = vo_dy;
288 ggi_conf.flushregion.x2 = vo_dwidth;
289 ggi_conf.flushregion.y2 = vo_dheight;
291 return (0);
294 static void draw_osd(void)
296 return;
299 static void flip_page(void)
301 if (ggi_conf.drawvis != ggi_conf.vis) {
302 #if 0
303 ggiFlushRegion(ggi_conf.drawvis,
304 ggi_conf.flushregion.x1, ggi_conf.flushregion.y1,
305 ggi_conf.flushregion.x2 - ggi_conf.flushregion.x1,
306 ggi_conf.flushregion.y2 - ggi_conf.flushregion.y1);
307 #endif
308 ggiCrossBlit(ggi_conf.drawvis,
309 ggi_conf.flushregion.x1, ggi_conf.flushregion.y1,
310 ggi_conf.flushregion.x2 - ggi_conf.flushregion.x1,
311 ggi_conf.flushregion.y2 - ggi_conf.flushregion.y1,
312 ggi_conf.vis,
313 ggi_conf.flushregion.x1, ggi_conf.flushregion.y1);
316 ggiFlushRegion(ggi_conf.vis,
317 ggi_conf.flushregion.x1, ggi_conf.flushregion.y1,
318 ggi_conf.flushregion.x2 - ggi_conf.flushregion.x1,
319 ggi_conf.flushregion.y2 - ggi_conf.flushregion.y1);
321 ggi_conf.flushregion.x1 = ggi_conf.flushregion.x2 = -1;
322 ggi_conf.flushregion.y1 = ggi_conf.flushregion.y2 = -1;
325 static int draw_slice(uint8_t *src[], int stride[],
326 int w, int h, int x, int y)
328 ggiPutBox(ggi_conf.drawvis, vo_dx + x, vo_dy + y, w, h, src[0]);
330 if ((ggi_conf.flushregion.x1 == -1) ||
331 ((vo_dx + x) < ggi_conf.flushregion.x1))
333 ggi_conf.flushregion.x1 = vo_dx + x;
335 if ((ggi_conf.flushregion.y1 == -1) ||
336 ((vo_dy + y) < ggi_conf.flushregion.y1))
338 ggi_conf.flushregion.y1 = vo_dy + y;
340 if ((ggi_conf.flushregion.x2 == -1) ||
341 ((vo_dx + x + w) > ggi_conf.flushregion.x2))
343 ggi_conf.flushregion.x2 = vo_dx + x + w;
345 if ((ggi_conf.flushregion.y2 == -1) ||
346 ((vo_dy + y + h) > ggi_conf.flushregion.y2))
348 ggi_conf.flushregion.y2 = vo_dy + y + h;
351 return (1);
354 static int query_format(uint32_t format)
356 ggi_mode mode;
357 uint32_t vfcap;
359 vfcap = VFCAP_CSP_SUPPORTED
360 | VFCAP_CSP_SUPPORTED_BY_HW
361 | VFCAP_ACCEPT_STRIDE;
363 if ((!ggi_conf.depthonscreen || !vo_dbpp) && ggi_conf.vis) {
364 if (ggiGetMode(ggi_conf.vis, &mode) == 0) {
365 ggi_conf.depthonscreen = GT_DEPTH(mode.graphtype);
366 vo_dbpp = GT_SIZE(mode.graphtype);
368 if (GT_SCHEME(mode.graphtype) == GT_AUTO) {
369 ggiCheckMode(ggi_conf.vis, &mode);
371 if (GT_SCHEME(mode.graphtype) != GT_TRUECOLOR) {
372 mode.graphtype = GT_32BIT;
373 ggi_conf.depthonscreen = GT_DEPTH(mode.graphtype);
374 vo_dbpp = GT_SIZE(mode.graphtype);
377 if ((IMGFMT_IS_BGR(format) && (IMGFMT_BGR_DEPTH(format) == vo_dbpp)) ||
378 (IMGFMT_IS_RGB(format) && (IMGFMT_RGB_DEPTH(format) == vo_dbpp)))
380 return vfcap;
382 if (IMGFMT_IS_BGR(format) || IMGFMT_IS_RGB(format)) {
383 set_graphtype(format, &mode);
385 if (ggiCheckMode(ggi_conf.drawvis, &mode) < 0) {
386 return 0;
387 } else {
388 return vfcap;
391 return (0);
394 static int preinit(const char *arg)
396 if (ggiInit() != 0) {
397 mp_msg(MSGT_VO, MSGL_FATAL, "[ggi] unable to initialize GGI\n");
398 return (-1);
400 #ifdef HAVE_GGIWMH
401 if (ggiWmhInit() < 0) {
402 mp_msg(MSGT_VO, MSGL_FATAL, "[ggi] unable to initialize libggiwmh\n");
403 return (-1);
405 #endif
407 if (arg) {
408 int i = 0;
409 ggi_conf.driver = strdup(arg);
410 while (ggi_conf.driver[i] != '\0') {
411 if (ggi_conf.driver[i] == '.')
412 ggi_conf.driver[i] = ',';
413 i++;
415 } else {
416 ggi_conf.driver = NULL;
419 ggi_conf.vis = ggiOpen(ggi_conf.driver);
420 if (ggi_conf.vis == NULL) {
421 mp_msg(MSGT_VO, MSGL_FATAL, "[ggi] unable to open '%s' output\n",
422 (ggi_conf.driver == NULL) ? "default" : ggi_conf.driver);
423 ggiExit();
424 return (-1);
426 ggi_conf.drawvis = ggi_conf.vis;
429 #ifdef HAVE_GGIWMH
430 ggiWmhAttach(ggi_conf.vis);
431 #endif
434 mp_msg(MSGT_VO, MSGL_V, "[ggi] using '%s' output\n",
435 (ggi_conf.driver == NULL) ? "default" : ggi_conf.driver);
437 return 0;
440 static void uninit(void)
442 if (ggi_conf.driver)
443 free(ggi_conf.driver);
445 #ifdef HAVE_GGIWMH
446 ggiWmhDetach(ggi_conf.vis);
447 ggiWmhExit();
448 #endif
450 if (ggi_conf.drawvis != NULL && ggi_conf.drawvis != ggi_conf.vis)
451 ggiClose(ggi_conf.drawvis);
453 ggiClose(ggi_conf.vis);
454 ggiExit();
457 static int control(uint32_t request, void *data)
459 switch (request) {
460 case VOCTRL_QUERY_FORMAT:
461 return query_format(*((uint32_t *) data));
462 case VOCTRL_GET_IMAGE:
463 return get_image(data);
464 #ifdef HAVE_GGIWMH
465 case VOCTRL_ONTOP:
466 vo_ontop = (!(vo_ontop));
467 window_ontop();
468 return VO_TRUE;
469 #endif
471 return VO_NOTIMPL;
474 /* EVENT handling */
475 #include "osdep/keycodes.h"
477 static void check_events(void)
479 struct timeval tv = {0, 0};
480 ggi_event event;
481 ggi_event_mask mask;
483 if ((mask = ggiEventPoll(ggi_conf.vis, emAll, &tv))) {
484 if (ggiEventRead(ggi_conf.vis, &event, emAll) != 0) {
485 mp_dbg(MSGT_VO, MSGL_DBG3,
486 "type: %4x, origin: %4x, "
487 "sym: %4x, label: %4x, button=%4x\n",
488 event.any.origin, event.any.type, event.key.sym,
489 event.key.label, event.key.button);
491 switch (event.any.type) {
492 case evKeyPress:
493 switch (event.key.sym) {
494 case GIIK_PAsterisk: /* PStar */
495 case GIIUC_Asterisk:
496 mplayer_put_key('*');
497 break;
498 case GIIK_PSlash:
499 case GIIUC_Slash:
500 mplayer_put_key('/');
501 break;
502 case GIIK_PPlus:
503 case GIIUC_Plus:
504 mplayer_put_key('+');
505 break;
506 case GIIK_PMinus:
507 case GIIUC_Minus:
508 mplayer_put_key('-');
509 break;
510 case GIIUC_o:
511 case GIIUC_O:
512 mplayer_put_key('o');
513 break;
514 case GIIUC_g:
515 case GIIUC_G:
516 mplayer_put_key('g');
517 break;
518 case GIIUC_z:
519 case GIIUC_Z:
520 mplayer_put_key('z');
521 break;
522 case GIIUC_x:
523 case GIIUC_X:
524 mplayer_put_key('x');
525 break;
526 case GIIUC_m:
527 case GIIUC_M:
528 mplayer_put_key('m');
529 break;
530 case GIIUC_d:
531 case GIIUC_D:
532 mplayer_put_key('d');
533 break;
534 case GIIUC_q:
535 case GIIUC_Q:
536 mplayer_put_key('q');
537 break;
538 case GIIUC_h:
539 case GIIUC_H:
540 mplayer_put_key('h');
541 break;
542 case GIIUC_l:
543 case GIIUC_L:
544 mplayer_put_key('l');
545 break;
546 case GIIUC_Space:
547 case GIIUC_p:
548 case GIIUC_P:
549 mplayer_put_key('p');
550 break;
551 case GIIK_Up:
552 mplayer_put_key(KEY_UP);
553 break;
554 case GIIK_Down:
555 mplayer_put_key(KEY_DOWN);
556 break;
557 case GIIK_Left:
558 mplayer_put_key(KEY_LEFT);
559 break;
560 case GIIK_Right:
561 mplayer_put_key(KEY_RIGHT);
562 break;
563 case GIIK_PageUp:
564 mplayer_put_key(KEY_PAGE_UP);
565 break;
566 case GIIK_PageDown:
567 mplayer_put_key(KEY_PAGE_DOWN);
568 break;
569 default:
570 break;
571 } /* switch */
573 break;
574 } /* switch */
575 } /* if */
576 } /* if */
577 return;