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