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