initial commit
[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(),
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         if( w < 1 ) w = 1;
173         if( h < 1 ) h = 1;
174         this->w = w;
175         this->h = h;
176         this->parent_window = parent_window;
177         this->mode = mode;
178         top_level = parent_window->top_level;
179
180         if(use_opaque())
181         {
182                 opaque_pixmap = XCreatePixmap(top_level->display,
183                         top_level->win,
184                         w,
185                         h,
186                         top_level->default_depth);
187 #ifdef HAVE_XFT
188                 if(BC_WindowBase::get_resources()->use_xft)
189                 {
190                         opaque_xft_draw = xftDrawCreate(top_level->display,
191                            opaque_pixmap,
192                            top_level->vis,
193                            top_level->cmap);
194                 }
195 #endif
196         }
197
198         if(use_alpha())
199         {
200                 unsigned long gcmask = GCGraphicsExposures |
201                         GCForeground |
202                         GCBackground |
203                         GCFunction;
204                 XGCValues gcvalues;
205                 gcvalues.graphics_exposures = 0;        // prevent expose events for every redraw
206                 gcvalues.foreground = 0;
207                 gcvalues.background = 1;
208                 gcvalues.function = GXcopy;
209
210                 alpha_pixmap = XCreatePixmap(top_level->display,
211                         top_level->win,
212                         w,
213                         h,
214                         1);
215
216                 alpha_gc = XCreateGC(top_level->display,
217                         top_level->win,
218                         gcmask,
219                         &gcvalues);
220
221                 copy_gc = XCreateGC(top_level->display,
222                         alpha_pixmap,
223                         gcmask,
224                         &gcvalues);
225
226 #ifdef HAVE_XFT
227                 if(BC_WindowBase::get_resources()->use_xft)
228                 {
229                         alpha_xft_draw = xftDrawCreateBitmap(top_level->display,
230                                 alpha_pixmap);
231                 }
232 #endif
233         }
234
235
236
237 // // For some reason, this is required in 32 bit.
238 // #ifdef HAVE_XFT
239 //      if(BC_WindowBase::get_resources()->use_xft)
240 //              XSync(top_level->display, False);
241 // #endif
242
243         return 0;
244 }
245
246 void BC_Pixmap::resize(int w, int h)
247 {
248         Pixmap new_pixmap = XCreatePixmap(top_level->display,
249                         top_level->win,
250                         w,
251                         h,
252                         top_level->default_depth);
253 #ifdef HAVE_XFT
254         XftDraw *new_xft_draw = 0;
255         if(BC_WindowBase::get_resources()->use_xft) {
256                 new_xft_draw = xftDrawCreate(top_level->display,
257                        new_pixmap,
258                        top_level->vis,
259                        top_level->cmap);
260         }
261 #endif
262
263
264
265
266         XCopyArea(top_level->display,
267                 opaque_pixmap,
268                 new_pixmap,
269                 top_level->gc,
270                 0,
271                 0,
272                 get_w(),
273                 get_h(),
274                 0,
275                 0);
276         this->w = w;
277         this->h = h;
278 #ifdef HAVE_XFT
279         if(BC_WindowBase::get_resources()->use_xft)
280                 xftDrawDestroy((XftDraw*)opaque_xft_draw);
281 #endif
282         XFreePixmap(top_level->display, opaque_pixmap);
283
284         opaque_pixmap = new_pixmap;
285 #ifdef HAVE_XFT
286         if(BC_WindowBase::get_resources()->use_xft)
287                 opaque_xft_draw = new_xft_draw;
288 #endif
289 }
290
291
292 void BC_Pixmap::copy_area(int x, int y, int w, int h, int x2, int y2)
293 {
294         XCopyArea(top_level->display,
295                 opaque_pixmap,
296                 opaque_pixmap,
297                 top_level->gc,
298                 x,
299                 y,
300                 w,
301                 h,
302                 x2,
303                 y2);
304 }
305
306 int BC_Pixmap::write_drawable(Drawable &pixmap,
307                         int dest_x,
308                         int dest_y,
309                         int dest_w,
310                         int dest_h,
311                         int src_x,
312                         int src_y)
313 {
314 //printf("BC_Pixmap::write_drawable 1\n");
315         if(dest_w < 0)
316         {
317                 dest_w = w;
318                 src_x = 0;
319         }
320
321         if(dest_h < 0)
322         {
323                 dest_h = h;
324                 src_y = 0;
325         }
326
327         if(use_alpha())
328         {
329                 XSetClipOrigin(top_level->display, alpha_gc, dest_x - src_x, dest_y - src_y);
330                 XCopyArea(top_level->display,
331                         this->opaque_pixmap,
332                         pixmap,
333                         alpha_gc,
334                         src_x,
335                         src_y,
336                         dest_w,
337                         dest_h,
338                         dest_x,
339                         dest_y);
340         }
341         else
342         if(use_opaque())
343         {
344                 XCopyArea(top_level->display,
345                         this->opaque_pixmap,
346                         pixmap,
347                         top_level->gc,
348                         src_x,
349                         src_y,
350                         dest_w,
351                         dest_h,
352                         dest_x,
353                         dest_y);
354         }
355 //printf("BC_Pixmap::write_drawable 2\n");
356
357         return 0;
358 }
359
360 void BC_Pixmap::draw_vframe(VFrame *frame,
361                 int dest_x,
362                 int dest_y,
363                 int dest_w,
364                 int dest_h,
365                 int src_x,
366                 int src_y)
367 {
368         parent_window->draw_vframe(frame,
369                 dest_x,
370                 dest_y,
371                 dest_w,
372                 dest_h,
373                 src_x,
374                 src_y,
375                 0,
376                 0,
377                 this);
378 }
379
380 void BC_Pixmap::draw_pixmap(BC_Pixmap *pixmap,
381         int dest_x,
382         int dest_y,
383         int dest_w,
384         int dest_h,
385         int src_x,
386         int src_y)
387 {
388         pixmap->write_drawable(this->opaque_pixmap,
389                         dest_x,
390                         dest_y,
391                         dest_w,
392                         dest_h,
393                         src_x,
394                         src_y);
395 }
396
397
398
399
400
401
402
403
404
405
406
407 int BC_Pixmap::get_w()
408 {
409         return w;
410 }
411
412 int BC_Pixmap::get_h()
413 {
414         return h;
415 }
416
417 int BC_Pixmap::get_w_fixed()
418 {
419         return w - 1;
420 }
421
422 int BC_Pixmap::get_h_fixed()
423 {
424         return h - 1;
425 }
426
427 Pixmap BC_Pixmap::get_pixmap()
428 {
429         return opaque_pixmap;
430 }
431
432 Pixmap BC_Pixmap::get_alpha()
433 {
434         return alpha_pixmap;
435 }
436
437 int BC_Pixmap::use_opaque()
438 {
439         return 1;
440 }
441
442 int BC_Pixmap::use_alpha()
443 {
444         return mode == PIXMAP_ALPHA;
445 }
446
447
448 void BC_Pixmap::enable_opengl()
449 {
450 //printf("BC_Pixmap::enable_opengl called but it doesn't work.\n");
451 #ifdef HAVE_GL
452         BC_WindowBase *current_window = BC_WindowBase::get_synchronous()->current_window;
453         if(!glx_pixmap_context) {
454                 GLXFBConfig *glx_fb_configs = current_window->glx_pixmap_fb_configs();
455                 if( glx_fb_configs ) {
456                         Display *dpy = current_window->get_display();
457                         glx_pixmap =
458                                 glXCreatePixmap(dpy, *glx_fb_configs, opaque_pixmap, 0);
459                         glx_pixmap_context =
460                                 glXCreateNewContext(dpy, *glx_fb_configs, GLX_RGBA_TYPE, 0, True);
461                 }
462         }
463         if( !glx_pixmap )
464                 printf("BC_Pixmap::enable_opengl(): no glx_pixmap\n");
465         else if( !glx_pixmap_context )
466                 printf("BC_Pixmap::enable_opengl(): no glx_pixmap_context\n");
467         else
468                 current_window->glx_make_current(glx_pixmap, glx_pixmap_context);
469 #endif
470 }
471