shuttlerc, boobytraps, vwindow hang, lock cleanup
[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,
82                                                                 0,
83                                                                 0,
84                                                                 0,
85                                                                 0,
86                                                                 w,
87                                                                 h,
88                                                                 1);
89                 delete opaque_bitmap;
90         }
91
92         if(use_alpha())
93         {
94                 alpha_bitmap->write_drawable(alpha_pixmap,
95                         copy_gc,
96                         0,
97                         0,
98                         icon_offset ? 2 : 0,
99                         icon_offset ? 2 : 0,
100                         w,
101                         h,
102                         1);
103                 delete alpha_bitmap;
104                 XFreeGC(top_level->display, copy_gc);
105
106                 XSetClipMask(top_level->display, alpha_gc, alpha_pixmap);
107         }
108 }
109
110 BC_Pixmap::BC_Pixmap(BC_WindowBase *parent_window, int w, int h)
111 {
112         reset();
113         initialize(parent_window, w, h, PIXMAP_OPAQUE);
114 }
115
116
117 BC_Pixmap::~BC_Pixmap()
118 {
119         if(use_opaque())
120         {
121 #ifdef HAVE_XFT
122                 if(opaque_xft_draw)
123                         xftDrawDestroy((XftDraw*)opaque_xft_draw);
124 #endif
125                 XFreePixmap(top_level->display, opaque_pixmap);
126         }
127
128         if(use_alpha())
129         {
130                 XFreeGC(top_level->display, alpha_gc);
131 #ifdef HAVE_XFT
132                 if(alpha_xft_draw)
133                         xftDrawDestroy((XftDraw*)alpha_xft_draw);
134 #endif
135                 XFreePixmap(top_level->display, alpha_pixmap);
136         }
137
138
139 // Have to delete GL objects because pixmaps are deleted during resizes.
140 #ifdef HAVE_GL
141         if(BC_WindowBase::get_synchronous() && glx_pixmap)
142         {
143                 BC_WindowBase::get_synchronous()->delete_pixmap(parent_window,
144                         glx_pixmap, glx_pixmap_context);
145         }
146 #endif
147 }
148
149
150 void BC_Pixmap::reset()
151 {
152         parent_window = 0;
153         top_level = 0;
154         opaque_pixmap = 0;
155         alpha_pixmap = 0;
156         opaque_xft_draw = 0;
157         alpha_xft_draw = 0;
158 #ifdef HAVE_GL
159         glx_pixmap_context = 0;
160         glx_pixmap = 0;
161 #endif
162 }
163
164 int BC_Pixmap::initialize(BC_WindowBase *parent_window, int w, int h, int mode)
165 {
166         if( w < 1 ) w = 1;
167         if( h < 1 ) h = 1;
168         this->w = w;
169         this->h = h;
170         this->parent_window = parent_window;
171         this->mode = mode;
172         top_level = parent_window->top_level;
173
174         if(use_opaque())
175         {
176                 opaque_pixmap = XCreatePixmap(top_level->display,
177                         top_level->win,
178                         w,
179                         h,
180                         top_level->default_depth);
181 #ifdef HAVE_XFT
182                 if(BC_WindowBase::get_resources()->use_xft)
183                 {
184                         opaque_xft_draw = xftDrawCreate(top_level->display,
185                            opaque_pixmap,
186                            top_level->vis,
187                            top_level->cmap);
188                 }
189 #endif
190         }
191
192         if(use_alpha())
193         {
194                 unsigned long gcmask = GCGraphicsExposures |
195                         GCForeground |
196                         GCBackground |
197                         GCFunction;
198                 XGCValues gcvalues;
199                 gcvalues.graphics_exposures = 0;        // prevent expose events for every redraw
200                 gcvalues.foreground = 0;
201                 gcvalues.background = 1;
202                 gcvalues.function = GXcopy;
203
204                 alpha_pixmap = XCreatePixmap(top_level->display,
205                         top_level->win,
206                         w,
207                         h,
208                         1);
209
210                 alpha_gc = XCreateGC(top_level->display,
211                         top_level->win,
212                         gcmask,
213                         &gcvalues);
214
215                 copy_gc = XCreateGC(top_level->display,
216                         alpha_pixmap,
217                         gcmask,
218                         &gcvalues);
219
220 #ifdef HAVE_XFT
221                 if(BC_WindowBase::get_resources()->use_xft)
222                 {
223                         alpha_xft_draw = xftDrawCreateBitmap(top_level->display,
224                                 alpha_pixmap);
225                 }
226 #endif
227         }
228
229
230
231 // // For some reason, this is required in 32 bit.
232 // #ifdef HAVE_XFT
233 //      if(BC_WindowBase::get_resources()->use_xft)
234 //              XSync(top_level->display, False);
235 // #endif
236
237         return 0;
238 }
239
240 void BC_Pixmap::resize(int w, int h)
241 {
242         Pixmap new_pixmap = XCreatePixmap(top_level->display,
243                         top_level->win,
244                         w,
245                         h,
246                         top_level->default_depth);
247 #ifdef HAVE_XFT
248         XftDraw *new_xft_draw = 0;
249         if(BC_WindowBase::get_resources()->use_xft) {
250                 new_xft_draw = xftDrawCreate(top_level->display,
251                        new_pixmap,
252                        top_level->vis,
253                        top_level->cmap);
254         }
255 #endif
256
257
258
259
260         XCopyArea(top_level->display,
261                 opaque_pixmap,
262                 new_pixmap,
263                 top_level->gc,
264                 0,
265                 0,
266                 get_w(),
267                 get_h(),
268                 0,
269                 0);
270         this->w = w;
271         this->h = h;
272 #ifdef HAVE_XFT
273         if(BC_WindowBase::get_resources()->use_xft)
274                 xftDrawDestroy((XftDraw*)opaque_xft_draw);
275 #endif
276         XFreePixmap(top_level->display, opaque_pixmap);
277
278         opaque_pixmap = new_pixmap;
279 #ifdef HAVE_XFT
280         if(BC_WindowBase::get_resources()->use_xft)
281                 opaque_xft_draw = new_xft_draw;
282 #endif
283 }
284
285
286 void BC_Pixmap::copy_area(int x, int y, int w, int h, int x2, int y2)
287 {
288         XCopyArea(top_level->display,
289                 opaque_pixmap,
290                 opaque_pixmap,
291                 top_level->gc,
292                 x,
293                 y,
294                 w,
295                 h,
296                 x2,
297                 y2);
298 }
299
300 int BC_Pixmap::write_drawable(Drawable &pixmap,
301                         int dest_x,
302                         int dest_y,
303                         int dest_w,
304                         int dest_h,
305                         int src_x,
306                         int src_y)
307 {
308 //printf("BC_Pixmap::write_drawable 1\n");
309         if(dest_w < 0)
310         {
311                 dest_w = w;
312                 src_x = 0;
313         }
314
315         if(dest_h < 0)
316         {
317                 dest_h = h;
318                 src_y = 0;
319         }
320
321         if(use_alpha())
322         {
323                 XSetClipOrigin(top_level->display, alpha_gc, dest_x - src_x, dest_y - src_y);
324                 XCopyArea(top_level->display,
325                         this->opaque_pixmap,
326                         pixmap,
327                         alpha_gc,
328                         src_x,
329                         src_y,
330                         dest_w,
331                         dest_h,
332                         dest_x,
333                         dest_y);
334         }
335         else
336         if(use_opaque())
337         {
338                 XCopyArea(top_level->display,
339                         this->opaque_pixmap,
340                         pixmap,
341                         top_level->gc,
342                         src_x,
343                         src_y,
344                         dest_w,
345                         dest_h,
346                         dest_x,
347                         dest_y);
348         }
349 //printf("BC_Pixmap::write_drawable 2\n");
350
351         return 0;
352 }
353
354 void BC_Pixmap::draw_vframe(VFrame *frame,
355                 int dest_x,
356                 int dest_y,
357                 int dest_w,
358                 int dest_h,
359                 int src_x,
360                 int src_y)
361 {
362         parent_window->draw_vframe(frame,
363                 dest_x,
364                 dest_y,
365                 dest_w,
366                 dest_h,
367                 src_x,
368                 src_y,
369                 0,
370                 0,
371                 this);
372 }
373
374 void BC_Pixmap::draw_pixmap(BC_Pixmap *pixmap,
375         int dest_x,
376         int dest_y,
377         int dest_w,
378         int dest_h,
379         int src_x,
380         int src_y)
381 {
382         pixmap->write_drawable(this->opaque_pixmap,
383                         dest_x,
384                         dest_y,
385                         dest_w,
386                         dest_h,
387                         src_x,
388                         src_y);
389 }
390
391
392
393
394
395
396
397
398
399
400
401 int BC_Pixmap::get_w()
402 {
403         return w;
404 }
405
406 int BC_Pixmap::get_h()
407 {
408         return h;
409 }
410
411 int BC_Pixmap::get_w_fixed()
412 {
413         return w - 1;
414 }
415
416 int BC_Pixmap::get_h_fixed()
417 {
418         return h - 1;
419 }
420
421 Pixmap BC_Pixmap::get_pixmap()
422 {
423         return opaque_pixmap;
424 }
425
426 Pixmap BC_Pixmap::get_alpha()
427 {
428         return alpha_pixmap;
429 }
430
431 int BC_Pixmap::use_opaque()
432 {
433         return 1;
434 }
435
436 int BC_Pixmap::use_alpha()
437 {
438         return mode == PIXMAP_ALPHA;
439 }
440
441
442 void BC_Pixmap::enable_opengl()
443 {
444 //printf("BC_Pixmap::enable_opengl called but it doesn't work.\n");
445 #ifdef HAVE_GL
446         BC_WindowBase *current_window = BC_WindowBase::get_synchronous()->current_window;
447         if(!glx_pixmap_context) {
448                 GLXFBConfig *glx_fb_configs = current_window->glx_pixmap_fb_configs();
449                 if( glx_fb_configs ) {
450                         Display *dpy = current_window->get_display();
451                         glx_pixmap =
452                                 glXCreatePixmap(dpy, *glx_fb_configs, opaque_pixmap, 0);
453                         glx_pixmap_context =
454                                 glXCreateNewContext(dpy, *glx_fb_configs, GLX_RGBA_TYPE, 0, True);
455                 }
456         }
457         if( !glx_pixmap )
458                 printf("BC_Pixmap::enable_opengl(): no glx_pixmap\n");
459         else if( !glx_pixmap_context )
460                 printf("BC_Pixmap::enable_opengl(): no glx_pixmap_context\n");
461         else
462                 current_window->glx_make_current(glx_pixmap, glx_pixmap_context);
463 #endif
464 }
465