1 /*****************************************************************
2 * gmerlin - a general purpose multimedia framework and applications
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22 #include <x11/x11.h>
23 #include <x11/x11_window_private.h>
24
25 /* XImage video driver */
26
init_ximage(driver_data_t * d)27 static int init_ximage(driver_data_t * d)
28 {
29 d->pixelformats = malloc(2*sizeof(*d->pixelformats));
30 d->pixelformats[0] = bg_x11_window_get_pixelformat(d->win->dpy, d->win->visual, d->win->depth);
31 d->pixelformats[1] = GAVL_PIXELFORMAT_NONE;
32 return 1;
33 }
34
35 typedef struct
36 {
37 XImage * x11_image;
38 XShmSegmentInfo shminfo;
39 } ximage_frame_t;
40
create_frame_ximage(driver_data_t * d)41 static gavl_video_frame_t * create_frame_ximage(driver_data_t * d)
42 {
43 ximage_frame_t * frame;
44 gavl_video_frame_t * ret;
45 bg_x11_window_t * w = d->win;
46
47 frame = calloc(1, sizeof(*frame));
48
49 if(w->have_shm)
50 {
51 /* Create Shm Image */
52 frame->x11_image = XShmCreateImage(w->dpy, w->visual,
53 w->depth, ZPixmap,
54 NULL, &frame->shminfo,
55 w->window_format.frame_width,
56 w->window_format.frame_height);
57 if(!frame->x11_image)
58 w->have_shm = 0;
59 else
60 {
61 if(!bg_x11_window_create_shm(w, &frame->shminfo,
62 frame->x11_image->height *
63 frame->x11_image->bytes_per_line))
64 {
65 XDestroyImage(frame->x11_image);
66
67 w->have_shm = 0;
68 }
69 frame->x11_image->data = frame->shminfo.shmaddr;
70
71 ret = calloc(1, sizeof(*ret));
72
73 ret->planes[0] = (uint8_t*)(frame->x11_image->data);
74 ret->strides[0] = frame->x11_image->bytes_per_line;
75 }
76 }
77 if(!w->have_shm)
78 {
79 /* Use gavl to allocate memory aligned scanlines */
80 ret = gavl_video_frame_create(&w->window_format);
81 frame->x11_image = XCreateImage(w->dpy, w->visual, w->depth,
82 ZPixmap,
83 0, (char*)(ret->planes[0]),
84 w->window_format.frame_width,
85 w->window_format.frame_height,
86 32,
87 ret->strides[0]);
88 }
89 ret->user_data = frame;
90 return ret;
91 }
92
put_frame_ximage(driver_data_t * d,gavl_video_frame_t * f)93 static void put_frame_ximage(driver_data_t * d, gavl_video_frame_t * f)
94 {
95 ximage_frame_t * frame = (ximage_frame_t*)f->user_data;
96 bg_x11_window_t * w = d->win;
97
98 if(w->have_shm)
99 {
100 XShmPutImage(w->dpy, /* dpy */
101 w->current->win, /* d */
102 w->gc, /* gc */
103 frame->x11_image, /* image */
104 w->dst_rect.x, /* src_x */
105 w->dst_rect.y, /* src_y */
106 w->dst_rect.x, /* dst_x */
107 w->dst_rect.y, /* dst_y */
108 w->dst_rect.w, /* src_width */
109 w->dst_rect.h, /* src_height */
110 True /* send_event */);
111 w->wait_for_completion = 1;
112 }
113 else
114 {
115 XPutImage(w->dpy, /* dpy */
116 w->current->win, /* d */
117 w->gc, /* gc */
118 frame->x11_image, /* image */
119 w->dst_rect.x, /* src_x */
120 w->dst_rect.y, /* src_y */
121 w->dst_rect.x, /* dst_x */
122 w->dst_rect.y, /* dst_y */
123 w->dst_rect.w, /* src_width */
124 w->dst_rect.h); /* src_height */
125 }
126 }
127
destroy_frame_ximage(driver_data_t * d,gavl_video_frame_t * f)128 static void destroy_frame_ximage(driver_data_t * d, gavl_video_frame_t * f)
129 {
130 ximage_frame_t * frame = (ximage_frame_t*)f->user_data;
131 bg_x11_window_t * w = d->win;
132 if(frame->x11_image)
133 XFree(frame->x11_image);
134 if(w->have_shm)
135 {
136 bg_x11_window_destroy_shm(w, &frame->shminfo);
137 gavl_video_frame_null(f);
138 gavl_video_frame_destroy(f);
139 }
140 else
141 {
142 gavl_video_frame_destroy(f);
143 }
144 free(frame);
145 }
146
147 const video_driver_t ximage_driver =
148 {
149 .name = "XImage",
150 .init = init_ximage,
151 .create_frame = create_frame_ximage,
152 .put_frame = put_frame_ximage,
153 .destroy_frame = destroy_frame_ximage
154 };
155