additional Andrew provided Termux mods +
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bcpixmap.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcbitmap.h"
23 #include "bcpixmap.h"
24 #include "bcresources.h"
25 #include "bcsignals.h"
26 #include "bcsynchronous.h"
27 #include "bcwindowbase.h"
28 #include "vframe.h"
29 #include "workarounds.h"
30
31 #include <unistd.h>
32
33 BC_Pixmap::BC_Pixmap(BC_WindowBase *parent_window,
34         VFrame *frame,
35         int mode,
36         int icon_offset)
37 {
38         reset();
39
40         BC_Bitmap *opaque_bitmap = 0, *alpha_bitmap = 0;
41         if(frame->get_color_model() != BC_RGBA8888 && mode == PIXMAP_ALPHA)
42                 mode = PIXMAP_OPAQUE;
43         this->mode = mode;
44
45 // Temporary bitmaps
46         if(use_opaque())
47         {
48                 opaque_bitmap = new BC_Bitmap(parent_window,
49                         frame->get_w(), frame->get_h(),
50                         parent_window->get_color_model(), 0);
51                 opaque_bitmap->read_frame(frame,
52                         0, 0, frame->get_w(), frame->get_h());
53
54         }
55
56         if(use_alpha())
57         {
58                 alpha_bitmap = new BC_Bitmap(parent_window,
59                                 frame->get_w(),
60                                 frame->get_h(),
61                                 BC_TRANSPARENCY,
62                                 0);
63
64                 if(frame->get_color_model() != BC_RGBA8888)
65                         printf("BC_Pixmap::BC_Pixmap: PIXMAP_ALPHA but frame doesn't have alpha.\n");
66                 alpha_bitmap->read_frame(frame,
67                         0,
68                         0,
69                         frame->get_w(),
70                         frame->get_h());
71         }
72
73         initialize(parent_window,
74                 frame->get_w(),
75                 frame->get_h(),
76                 mode);
77
78         if(use_opaque())
79         {
80                 opaque_bitmap->write_drawable(opaque_pixmap,
81                         top_level->gc, 0, 0, 0, 0, w, h, 1);
82                 delete opaque_bitmap;
83         }
84
85         if(use_alpha())
86         {
87                 alpha_bitmap->write_drawable(alpha_pixmap,
88                         copy_gc, 0, 0, icon_offset ? 2 : 0, icon_offset ? 2 : 0, w, h, 1);
89                 delete alpha_bitmap;
90                 XFreeGC(top_level->display, copy_gc);
91
92                 XSetClipMask(top_level->display, alpha_gc, alpha_pixmap);
93         }
94 }
95
96 BC_Pixmap::BC_Pixmap(BC_WindowBase *parent_window, int w, int h)
97 {
98         reset();
99         initialize(parent_window, w, h, PIXMAP_OPAQUE);
100 }
101
102
103 BC_Pixmap::~BC_Pixmap()
104 {
105         if(use_opaque())
106         {
107 #ifdef HAVE_XFT
108                 if(opaque_xft_draw)
109                         xftDrawDestroy((XftDraw*)opaque_xft_draw);
110 #endif
111                 XFreePixmap(top_level->display, opaque_pixmap);
112         }
113
114         if(use_alpha())
115         {
116                 XFreeGC(top_level->display, alpha_gc);
117 #ifdef HAVE_XFT
118                 if(alpha_xft_draw)
119                         xftDrawDestroy((XftDraw*)alpha_xft_draw);
120 #endif
121                 XFreePixmap(top_level->display, alpha_pixmap);
122         }
123
124
125 // Have to delete GL objects because pixmaps are deleted during resizes.
126 #ifdef HAVE_GL
127         if(BC_WindowBase::get_synchronous() && glx_pixmap)
128         {
129                 BC_WindowBase::get_synchronous()->delete_pixmap(parent_window,
130                         glx_pixmap, glx_pixmap_context);
131         }
132 #endif
133 }
134
135
136 void BC_Pixmap::reset()
137 {
138         parent_window = 0;
139         top_level = 0;
140         opaque_pixmap = 0;
141         alpha_pixmap = 0;
142         opaque_xft_draw = 0;
143         alpha_xft_draw = 0;
144 #ifdef HAVE_GL
145         glx_pixmap_context = 0;
146         glx_pixmap = 0;
147 #endif
148 }
149
150 int BC_Pixmap::initialize(BC_WindowBase *parent_window, int w, int h, int mode)
151 {
152         if( w < 1 ) w = 1;
153         if( h < 1 ) h = 1;
154         this->w = w;
155         this->h = h;
156         this->parent_window = parent_window;
157         this->mode = mode;
158         top_level = parent_window->top_level;
159
160         if(use_opaque())
161         {
162                 opaque_pixmap = XCreatePixmap(top_level->display,
163                         top_level->win,
164                         w,
165                         h,
166                         top_level->default_depth);
167 #ifdef HAVE_XFT
168                 if(BC_WindowBase::get_resources()->use_xft)
169                 {
170                         opaque_xft_draw = xftDrawCreate(top_level->display,
171                            opaque_pixmap,
172                            top_level->vis,
173                            top_level->cmap);
174                 }
175 #endif
176         }
177
178         if(use_alpha())
179         {
180                 unsigned long gcmask = GCGraphicsExposures |
181                         GCForeground |
182                         GCBackground |
183                         GCFunction;
184                 XGCValues gcvalues;
185                 gcvalues.graphics_exposures = 0;        // prevent expose events for every redraw
186                 gcvalues.foreground = 0;
187                 gcvalues.background = 1;
188                 gcvalues.function = GXcopy;
189
190                 alpha_pixmap = XCreatePixmap(top_level->display,
191                         top_level->win, w, h, 1);
192                 alpha_gc = XCreateGC(top_level->display,
193                         top_level->win, gcmask, &gcvalues);
194                 copy_gc = XCreateGC(top_level->display,
195                         alpha_pixmap, gcmask, &gcvalues);
196
197 #ifdef HAVE_XFT
198                 if(BC_WindowBase::get_resources()->use_xft)
199                 {
200                         alpha_xft_draw = xftDrawCreateBitmap(top_level->display,
201                                 alpha_pixmap);
202                 }
203 #endif
204         }
205
206
207
208 // // For some reason, this is required in 32 bit.
209 // #ifdef HAVE_XFT
210 //      if(BC_WindowBase::get_resources()->use_xft)
211 //              XSync(top_level->display, False);
212 // #endif
213
214         return 0;
215 }
216
217 void BC_Pixmap::resize(int w, int h)
218 {
219         Pixmap new_pixmap = XCreatePixmap(top_level->display,
220                         top_level->win,
221                         w,
222                         h,
223                         top_level->default_depth);
224 #ifdef HAVE_XFT
225         XftDraw *new_xft_draw = 0;
226         if(BC_WindowBase::get_resources()->use_xft) {
227                 new_xft_draw = xftDrawCreate(top_level->display,
228                        new_pixmap,
229                        top_level->vis,
230                        top_level->cmap);
231         }
232 #endif
233
234
235
236
237         XCopyArea(top_level->display,
238                 opaque_pixmap,
239                 new_pixmap,
240                 top_level->gc,
241                 0,
242                 0,
243                 get_w(),
244                 get_h(),
245                 0,
246                 0);
247         this->w = w;
248         this->h = h;
249 #ifdef HAVE_XFT
250         if(BC_WindowBase::get_resources()->use_xft)
251                 xftDrawDestroy((XftDraw*)opaque_xft_draw);
252 #endif
253         XFreePixmap(top_level->display, opaque_pixmap);
254
255         opaque_pixmap = new_pixmap;
256 #ifdef HAVE_XFT
257         if(BC_WindowBase::get_resources()->use_xft)
258                 opaque_xft_draw = new_xft_draw;
259 #endif
260 }
261
262
263 void BC_Pixmap::copy_area(int x, int y, int w, int h, int x2, int y2)
264 {
265         XCopyArea(top_level->display,
266                 opaque_pixmap, opaque_pixmap, top_level->gc,
267                 x, y, w, h, x2, y2);
268 }
269
270 int BC_Pixmap::write_drawable(Drawable &pixmap,
271         int dest_x, int dest_y, int dest_w, int dest_h,
272         int src_x, int src_y)
273 {
274 //printf("BC_Pixmap::write_drawable 1\n");
275         if(dest_w < 0)
276         {
277                 dest_w = w;
278                 src_x = 0;
279         }
280
281         if(dest_h < 0)
282         {
283                 dest_h = h;
284                 src_y = 0;
285         }
286
287         if(use_alpha())
288         {
289                 XSetClipOrigin(top_level->display, alpha_gc, dest_x - src_x, dest_y - src_y);
290                 XCopyArea(top_level->display,
291                         this->opaque_pixmap, pixmap, alpha_gc,
292                         src_x, src_y, dest_w, dest_h, dest_x, dest_y);
293         }
294         else
295         if(use_opaque())
296         {
297                 XCopyArea(top_level->display,
298                         this->opaque_pixmap, pixmap, top_level->gc,
299                         src_x, src_y, dest_w, dest_h, dest_x, dest_y);
300         }
301 //printf("BC_Pixmap::write_drawable 2\n");
302
303         return 0;
304 }
305
306 void BC_Pixmap::draw_vframe(VFrame *frame,
307         int dest_x, int dest_y, int dest_w, int dest_h,
308         int src_x, int src_y)
309 {
310         parent_window->draw_vframe(frame,
311                 dest_x, dest_y, dest_w, dest_h, src_x,
312                 src_y, 0, 0, this);
313 }
314
315 void BC_Pixmap::draw_pixmap(BC_Pixmap *pixmap,
316         int dest_x, int dest_y, int dest_w, int dest_h,
317         int src_x, int src_y)
318 {
319         pixmap->write_drawable(this->opaque_pixmap,
320                 dest_x, dest_y, dest_w, dest_h,
321                 src_x, src_y);
322 }
323
324
325 int BC_Pixmap::get_w() { return w; }
326 int BC_Pixmap::get_h() { return h; }
327 int BC_Pixmap::get_w_fixed() { return w - 1; }
328 int BC_Pixmap::get_h_fixed() { return h - 1; }
329 Pixmap BC_Pixmap::get_pixmap() { return opaque_pixmap; }
330 Pixmap BC_Pixmap::get_alpha() { return alpha_pixmap; }
331 int BC_Pixmap::use_opaque() { return 1; }
332 int BC_Pixmap::use_alpha() { return mode == PIXMAP_ALPHA; }
333
334
335 void BC_Pixmap::enable_opengl()
336 {
337 //printf("BC_Pixmap::enable_opengl called but it doesn't work.\n");
338 #ifdef HAVE_GL
339         BC_WindowBase *current_window = BC_WindowBase::get_synchronous()->current_window;
340         if(!glx_pixmap_context) {
341                 GLXFBConfig *glx_fb_configs = current_window->glx_pixmap_fb_configs();
342                 if( glx_fb_configs ) {
343                         Display *dpy = current_window->get_display();
344                         glx_pixmap =
345                                 glXCreatePixmap(dpy, *glx_fb_configs, opaque_pixmap, 0);
346                         glx_pixmap_context =
347                                 glXCreateNewContext(dpy, *glx_fb_configs, GLX_RGBA_TYPE, 0, True);
348                 }
349         }
350         if( !glx_pixmap )
351                 printf("BC_Pixmap::enable_opengl(): no glx_pixmap\n");
352         else if( !glx_pixmap_context )
353                 printf("BC_Pixmap::enable_opengl(): no glx_pixmap_context\n");
354         else
355                 current_window->glx_make_current(glx_pixmap, glx_pixmap_context);
356 #endif
357 }
358