initial commit
[goodguy/history.git] / cinelerra-5.0 / guicast / bcbitmap.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2009 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 "bcipc.h"
24 #include "bcresources.h"
25 #include "bcsignals.h"
26 #include "bcwindow.h"
27 #include "bccmodels.h"
28 #include "vframe.h"
29
30 #include <string.h>
31 #include <unistd.h>
32 #include <X11/extensions/Xvlib.h>
33
34 int BC_Bitmap::max_active_buffers = 0;
35 int BC_Bitmap::zombies = 0;
36
37
38 BC_BitmapImage::BC_BitmapImage(BC_Bitmap *bitmap, int index)
39 {
40         this->index = index;
41         this->bitmap = bitmap;
42         this->top_level = bitmap->top_level;
43         this->drawable = 0;
44         this->data = 0;
45         this->row_data = 0;
46         this->dataSize = 0;
47         this->bytesPerLine = 0;
48         this->bitsPerPixel = 0;
49 }
50
51 BC_BitmapImage::~BC_BitmapImage()
52 {
53         delete [] data;
54         delete [] row_data;
55 }
56
57 bool BC_BitmapImage::is_avail()
58 {
59         return owner == &bitmap->avail;
60 }
61
62 BC_BitmapImage *BC_Bitmap::cur_bfr()
63 {
64         if( !active_bfr ) {
65                 avail_lock->lock("BC_Bitmap::cur_bfr 1");
66                 if( (!use_shm || top_level->is_running()) &&
67                      (active_bfr=avail.first) != 0 )
68                         avail.remove_pointer(active_bfr);
69                 else {
70                         update_buffers(buffer_count+1, 0);
71                         if( (active_bfr=avail.first) != 0 )
72                                 avail.remove_pointer(active_bfr);
73                         else
74                                 active_bfr = new_buffer(type, -1);
75                 }
76                 avail_lock->unlock();
77         }
78         return active_bfr;
79 }
80
81 int BC_BitmapImage::
82 read_frame_rgb(VFrame *frame)
83 {
84         int w = bitmap->w, h = bitmap->h;
85         if( frame->get_w() != w || frame->get_h() != h ||
86             frame->get_color_model() != BC_RGB888 )
87                 frame->reallocate(0, 0, 0, 0, 0, w, h, BC_RGB888, -1);
88         uint8_t *dp = frame->get_data();
89         int rmask = ximage->red_mask;
90         int gmask = ximage->green_mask;
91         int bmask = ximage->blue_mask;
92 //due to a bug in the xserver, the mask is being cleared by XShm.C:402
93 //  when a faulty data in a XShmGetImage reply returns a zero visual
94 //workaround, use the original visual for the mask data
95         if ( !rmask ) rmask = bitmap->top_level->vis->red_mask;
96         if ( !gmask ) gmask = bitmap->top_level->vis->green_mask;
97         if ( !bmask ) bmask = bitmap->top_level->vis->blue_mask;
98         double fr = 255.0 / rmask;
99         double fg = 255.0 / gmask;
100         double fb = 255.0 / bmask;
101         int nbyte = (ximage->bits_per_pixel+7)/8;
102         int b0 = ximage->byte_order == MSBFirst ? 0 : nbyte-1;
103         int bi = ximage->byte_order == MSBFirst ? 1 : -1;
104         uint8_t *data = (uint8_t *)ximage->data;
105
106         for( int y=0;  y<h; ++y ) {
107                 uint8_t *cp = data + y*ximage->bytes_per_line + b0;
108                 for( int x=0; x<w; ++x, cp+=nbyte ) {
109                         uint8_t *bp = cp;  uint32_t n = *bp;
110                         for( int i=nbyte; --i>0; n=(n<<8)|*bp ) bp += bi;
111                         *dp++ = (int)((n&rmask)*fr + 0.5);
112                         *dp++ = (int)((n&gmask)*fg + 0.5);
113                         *dp++ = (int)((n&bmask)*fb + 0.5);
114                 }
115         }
116         return 0;
117 }
118
119 void BC_Bitmap::reque(BC_BitmapImage *bfr)
120 {
121         avail_lock->lock("BC_Bitmap::reque");
122         --active_buffers;
123         avail.append(bfr);
124         avail_lock->unlock();
125 }
126
127 BC_XvShmImage::BC_XvShmImage(BC_Bitmap *bitmap, int index,
128         int w, int h, int color_model)
129  : BC_BitmapImage(bitmap, index)
130 {
131         Display *display = top_level->get_display();
132         int id = BC_CModels::bc_to_x(color_model);
133 // Create the XvImage
134         xv_image = XvShmCreateImage(display, bitmap->xv_portid, id,
135                         0, w, h, &shm_info);
136         dataSize = xv_image->data_size;
137 // Create the shared memory
138         shm_info.shmid = shmget(IPC_PRIVATE, 
139                 dataSize + 8, IPC_CREAT | 0777);
140         if(shm_info.shmid < 0)
141                 perror("BC_XvShmImage::BC_XvShmImage shmget");
142         data = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
143 // This causes it to automatically delete when the program exits.
144         shmctl(shm_info.shmid, IPC_RMID, 0);
145 // setting ximage->data stops BadValue
146         xv_image->data = shm_info.shmaddr = (char*)data;
147         shm_info.readOnly = 0;
148 // Get the real parameters
149         w = xv_image->width;
150         h = xv_image->height;
151         if(!XShmAttach(top_level->display, &shm_info))
152                 perror("BC_XvShmImage::BC_XvShmImage XShmAttach");
153         if( color_model == BC_YUV422 ) {
154                 bytesPerLine = w*2;
155                 bitsPerPixel = 12;
156                 row_data = new unsigned char*[h];
157                 for( int i=0; i<h; ++i )
158                         row_data[i] = &data[i*bytesPerLine];
159         }
160 }
161
162 BC_XvShmImage::~BC_XvShmImage()
163 {
164         data = 0;
165         XFree(xv_image);
166         XShmDetach(top_level->display, &shm_info);
167         shmdt(shm_info.shmaddr);
168 }
169
170
171 BC_XShmImage::BC_XShmImage(BC_Bitmap *bitmap, int index,
172         int w, int h, int color_model)
173  : BC_BitmapImage(bitmap, index)
174 {
175         Display *display = top_level->display;
176         Visual *visual = top_level->vis;
177         int default_depth = bitmap->get_default_depth();
178         ximage = XShmCreateImage(display, visual, 
179                 default_depth, default_depth == 1 ? XYBitmap : ZPixmap, 
180                 (char*)NULL, &shm_info, w, h);
181 // Create shared memory
182         bytesPerLine = ximage->bytes_per_line;
183         bitsPerPixel = ximage->bits_per_pixel;
184         dataSize = h * bytesPerLine;
185         shm_info.shmid = shmget(IPC_PRIVATE, 
186                 dataSize + 8, IPC_CREAT | 0777);
187         if(shm_info.shmid < 0) 
188                 perror("BC_XShmImage::BC_XShmImage shmget");
189         data = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
190 // This causes it to automatically delete when the program exits.
191         shmctl(shm_info.shmid, IPC_RMID, 0);
192         ximage->data = shm_info.shmaddr = (char*)data;
193         shm_info.readOnly = 0;
194 // Get the real parameters
195         if(!XShmAttach(top_level->display, &shm_info))
196                 perror("BC_XShmImage::BC_XShmImage XShmAttach");
197         row_data = new unsigned char*[h];
198         for( int i=0; i<h; ++i )
199                 row_data[i] = &data[i*bytesPerLine];
200 }
201
202 BC_XShmImage::~BC_XShmImage()
203 {
204         data = 0;
205         ximage->data = 0;
206         XDestroyImage(ximage);
207         XShmDetach(top_level->display, &shm_info);
208         XFlush(top_level->display);
209         shmdt(shm_info.shmaddr);
210 }
211
212
213
214 BC_XvImage::BC_XvImage(BC_Bitmap *bitmap, int index,
215         int w, int h, int color_model)
216  : BC_BitmapImage(bitmap, index)
217 {
218         Display *display = top_level->display;
219         int id = BC_CModels::bc_to_x(color_model);
220         xv_image = XvCreateImage(display, bitmap->xv_portid, id, 0, w, h);
221         dataSize = xv_image->data_size;
222         data = new unsigned char[dataSize + 8];
223         xv_image->data = (char *) data;
224         w = xv_image->width;
225         h = xv_image->height;
226         if( color_model == BC_YUV422 ) {
227                 int bytesPerLine = w*2;
228                 row_data = new unsigned char*[h];
229                 for( int i=0; i<h; ++i )
230                         row_data[i] = &data[i*bytesPerLine];
231         }
232 }
233
234 BC_XvImage::~BC_XvImage()
235 {
236         XFree(xv_image);
237 }
238
239
240 BC_XImage::BC_XImage(BC_Bitmap *bitmap, int index,
241         int w, int h, int color_model)
242  : BC_BitmapImage(bitmap, index)
243 {
244         Display *display = top_level->display;
245         Visual *visual = top_level->vis;
246         int default_depth = bitmap->get_default_depth();
247         ximage = XCreateImage(display, visual, default_depth, 
248                 default_depth == 1 ? XYBitmap : ZPixmap, 
249                 0, (char*)data, w, h, 8, 0);
250         bytesPerLine = ximage->bytes_per_line;
251         bitsPerPixel = ximage->bits_per_pixel;
252         dataSize = h * bytesPerLine;
253         data = new unsigned char[dataSize + 8];
254         ximage->data = (char*) data;
255         row_data = new unsigned char*[h];
256         for( int i=0; i<h; ++i )
257                 row_data[i] = &data[i*bytesPerLine];
258 }
259
260 BC_XImage::~BC_XImage()
261 {
262         delete [] data;
263         data = 0;
264         ximage->data = 0;
265         XDestroyImage(ximage);
266 }
267
268
269 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, unsigned char *png_data)
270 {
271 // Decompress data into a temporary vframe
272         VFrame frame;
273
274         frame.read_png(png_data);
275
276         avail_lock = 0;
277 // Initialize the bitmap
278         initialize(parent_window, 
279                 frame.get_w(), 
280                 frame.get_h(), 
281                 parent_window->get_color_model(), 
282                 0);
283
284 // Copy the vframe to the bitmap
285         read_frame(&frame, 0, 0, w, h);
286 }
287
288 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, VFrame *frame)
289 {
290         avail_lock = 0;
291 // Initialize the bitmap
292         initialize(parent_window, 
293                 frame->get_w(), 
294                 frame->get_h(), 
295                 parent_window->get_color_model(), 
296                 0);
297
298 // Copy the vframe to the bitmap
299         read_frame(frame, 0, 0, w, h);
300 }
301
302 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, 
303         int w, int h, int color_model, int use_shm)
304 {
305         avail_lock = 0;
306         initialize(parent_window, w, h, color_model, use_shm);
307 }
308
309 BC_Bitmap::~BC_Bitmap()
310 {
311         delete_data();
312         delete avail_lock;
313 }
314
315 int BC_Bitmap::initialize(BC_WindowBase *parent_window, 
316         int w, int h, int color_model, int use_shm)
317 {
318         BC_Resources *resources = parent_window->get_resources();
319         this->parent_window = parent_window;
320         this->top_level = parent_window->top_level;
321         this->xv_portid = resources->use_xvideo ? top_level->xvideo_port_id : -1;
322         this->w = w;
323         this->h = h;
324         this->color_model = color_model;
325         this->use_shm = !use_shm ? 0 : need_shm();
326         this->shm_reply = this->use_shm && resources->shm_reply ? 1 : 0;
327         // dont use shm for less than one page
328         this->bg_color = parent_window->bg_color;
329         if( !this->avail_lock )
330                 this->avail_lock = new Mutex("BC_Bitmap::avail_lock");
331         else
332                 this->avail_lock->reset();
333         this->buffers = 0;
334         this->last_pixmap_used = 0;
335         this->last_pixmap = 0;
336
337         this->active_bfr = 0;
338         this->buffer_count = 0;
339         this->max_buffer_count = 0;
340         this->active_buffers = 0;
341         allocate_data();
342         return 0;
343 }
344
345 int BC_Bitmap::match_params(int w, int h, int color_model, int use_shm)
346 {
347         if( use_shm ) use_shm = need_shm();
348         if(this->w /* != */ < w || this->h /* != */ < h ||
349            this->color_model != color_model || this->use_shm != use_shm) {
350                 delete_data();
351                 initialize(parent_window, w, h, color_model, use_shm);
352         }
353
354         return 0;
355 }
356
357 int BC_Bitmap::params_match(int w, int h, int color_model, int use_shm)
358 {
359         int result = 0;
360         if( use_shm ) use_shm = need_shm();
361         if(this->w == w && this->h == h && this->color_model == color_model) {
362                 if(use_shm == this->use_shm || use_shm == BC_INFINITY)
363                         result = 1;
364         }
365         return result;
366 }
367
368 BC_BitmapImage *BC_Bitmap::new_buffer(int type, int idx)
369 {
370         BC_BitmapImage *buffer = 0;
371         if( idx < 0 ) {
372                 if( type == bmXShmImage ) type = bmXImage;
373                 else if( type ==  bmXvShmImage ) type = bmXvImage;
374         }
375         switch( type ) {
376         default:
377         case bmXImage:
378                 buffer = new BC_XImage(this, idx, w, h, color_model);
379                 break;
380         case bmXvImage:
381                 buffer = new BC_XvImage(this, idx, w, h, color_model);
382                 break;
383         case bmXShmImage:
384                 buffer = new BC_XShmImage(this, idx, w, h, color_model);
385                 break;
386         case bmXvShmImage:
387                 buffer = new BC_XvShmImage(this, idx, w, h, color_model);
388                 break;
389         }
390         if( buffer->is_zombie() ) ++zombies;
391         return buffer;
392 }
393
394 void BC_Bitmap::
395 update_buffers(int count, int lock_avail)
396 {
397         int i;
398         // can deadlock in XReply (libxcb bug) without this lock
399         //top_level->lock_window("BC_Bitmap::update_buffers");
400         if( lock_avail ) avail_lock->lock("BC_Bitmap::update_buffers");
401         if( count > max_buffer_count ) count = max_buffer_count;
402         BC_BitmapImage **new_buffers = !count ? 0 : new BC_BitmapImage *[count];
403         if( buffer_count < count ) {
404                 for( i=0; i<buffer_count; ++i )
405                         new_buffers[i] = buffers[i];
406                 while( i < count ) {
407                         BC_BitmapImage *buffer = new_buffer(type, i);
408                         new_buffers[i] = buffer;
409                         avail.append(buffer);
410                         ++i;
411                 }
412         }
413         else {
414                 for( i=0; i<count; ++i )
415                         new_buffers[i] = buffers[i];
416                 while( i < buffer_count ) {
417                         BC_BitmapImage *buffer = buffers[i];
418                         if( buffer == active_bfr ) active_bfr = 0;
419                         if( buffer->is_avail() ) {
420                                 avail.remove_pointer(buffer);
421                                 delete buffer;
422                         }
423                         else {
424                                 ++zombies;
425                                 buffer->index = -1;
426                         }
427                         ++i;
428                 }
429         }
430         if( lock_avail ) avail_lock->unlock();
431         delete [] buffers;
432         buffers = new_buffers;
433         buffer_count = count;
434         //top_level->unlock_window();
435 }
436
437 int BC_Bitmap::allocate_data()
438 {
439         int count = 1;
440         max_buffer_count = MAX_BITMAP_BUFFERS;
441         if(use_shm) { // Use shared memory.
442                 int bsz = best_buffer_size();
443                 if( bsz >= 0x800000 ) max_buffer_count = 2;
444                 else if( bsz >= 0x400000 ) max_buffer_count /= 8;
445                 else if( bsz >= 0x100000 ) max_buffer_count /= 4;
446                 else if( bsz >= 0x10000 ) max_buffer_count /= 2;
447                 type = hardware_scaling() ? bmXvShmImage : bmXShmImage;
448                 count = MIN_BITMAP_BUFFERS;
449         }
450         else // use unshared memory.
451                 type = hardware_scaling() ? bmXvImage : bmXImage;
452         update_buffers(count);
453         return 0;
454 }
455
456 int BC_Bitmap::delete_data()
457 {
458 //printf("BC_Bitmap::delete_data 1\n");
459         if( last_pixmap_used && xv_portid >= 0 )
460                 XvStopVideo(top_level->display, xv_portid, last_pixmap);
461         update_buffers(0);
462         if( xv_portid >= 0 )
463                 XvUngrabPort(top_level->display, xv_portid, CurrentTime);
464         last_pixmap_used = 0;
465         active_bfr = 0;
466         buffer_count = 0;
467         max_buffer_count = 0;
468         return 0;
469 }
470
471 int BC_Bitmap::get_default_depth()
472 {
473         return color_model == BC_TRANSPARENCY ? 1 : top_level->default_depth;
474 }
475
476 long BC_Bitmap::best_buffer_size()
477 {
478         long pixelsize = BC_CModels::calculate_pixelsize(get_color_model());
479         return pixelsize * w * h;
480 }
481
482 int BC_Bitmap::need_shm()
483 {
484 // dont use shm for less than one page
485         return best_buffer_size() < 0x1000 ? 0 :
486                 parent_window->get_resources()->use_shm > 0 ? 1 : 0;
487 }
488
489 int BC_Bitmap::set_bg_color(int color)
490 {
491         this->bg_color = color;
492         return 0;
493 }
494
495 int BC_Bitmap::invert()
496 {
497         for( int j=0; j<buffer_count; ++j ) {
498                 unsigned char **rows = buffers[j]->get_row_data();
499                 if( !rows ) continue;
500                 long bytesPerLine = buffers[j]->bytes_per_line();
501                 for( int k=0; k<h; ++k ) {
502                         unsigned char *bp = rows[k];
503                         for( int i=0; i<bytesPerLine; ++i )
504                                 *bp++ ^= 0xff;
505                 }
506         }
507         return 0;
508 }
509
510 int BC_XShmImage::get_shm_size()
511 {
512         return bytesPerLine * bitmap->h;
513 }
514
515 int BC_Bitmap::write_drawable(Drawable &pixmap, GC &gc,
516         int dest_x, int dest_y, int source_x, int source_y, 
517         int dest_w, int dest_h, int dont_wait)
518 {
519         return write_drawable(pixmap, gc,
520                 source_x, source_y, get_w() - source_x, get_h() - source_y,
521                 dest_x, dest_y, dest_w, dest_h, dont_wait);
522 }
523
524 int BC_XImage::write_drawable(Drawable &pixmap, GC &gc,
525         int source_x, int source_y, int source_w, int source_h,
526         int dest_x, int dest_y, int dest_w, int dest_h)
527 {
528         XPutImage(top_level->display, pixmap, gc,
529                 ximage, source_x, source_y,
530                 dest_x, dest_y, dest_w, dest_h);
531         return 0;
532 }
533
534 int BC_XShmImage::write_drawable(Drawable &pixmap, GC &gc,
535         int source_x, int source_y, int source_w, int source_h,
536         int dest_x, int dest_y, int dest_w, int dest_h)
537 {
538         XShmPutImage(top_level->display, pixmap, gc,
539                 ximage, source_x, source_y,
540                 dest_x, dest_y, dest_w, dest_h, bitmap->shm_reply);
541         return 0;
542 }
543
544 int BC_XvImage::write_drawable(Drawable &pixmap, GC &gc,
545         int source_x, int source_y, int source_w, int source_h,
546         int dest_x, int dest_y, int dest_w, int dest_h)
547 {
548         XvPutImage(top_level->display,
549                 bitmap->xv_portid, pixmap, gc, xv_image,
550                 source_x, source_y, source_w, source_h,
551                 dest_x, dest_y, dest_w, dest_h);
552         return 0;
553 }
554
555 int BC_XvShmImage::write_drawable(Drawable &pixmap, GC &gc,
556         int source_x, int source_y, int source_w, int source_h,
557         int dest_x, int dest_y, int dest_w, int dest_h)
558 {
559         XvShmPutImage(top_level->display,
560                 bitmap->xv_portid, pixmap, gc, xv_image,
561                 source_x, source_y, source_w, source_h,
562                 dest_x, dest_y, dest_w, dest_h, bitmap->shm_reply);
563         return 0;
564 }
565
566 int BC_Bitmap::write_drawable(Drawable &pixmap, GC &gc,
567                 int source_x, int source_y, int source_w, int source_h,
568                 int dest_x, int dest_y, int dest_w, int dest_h, 
569                 int dont_wait)
570 {
571 //printf("BC_Bitmap::write_drawable 1 %p %d\n", this, current_ringbuffer); fflush(stdout);
572         //if( dont_wait ) XSync(top_level->display, False);
573         BC_BitmapImage *bfr = cur_bfr();
574         if( !bfr->is_zombie() && is_shared() && shm_reply ) {
575 //printf("activate %p %08lx\n",bfr,bfr->get_shmseg());
576                 top_level->active_bitmaps.insert(bfr, pixmap);
577                 if( ++active_buffers > max_active_buffers )
578                         max_active_buffers = active_buffers;
579         }
580         bfr->write_drawable(pixmap, gc,
581                 source_x, source_y, source_w, source_h,
582                 dest_x, dest_y, dest_w, dest_h);
583         XFlush(top_level->display);
584         avail_lock->lock(" BC_Bitmap::write_drawable");
585         if( bfr->is_zombie() ) {
586                 delete bfr;
587                 --zombies;
588         }
589         else if( is_unshared() || !shm_reply )
590                 avail.append(bfr);
591         active_bfr = 0;
592         avail_lock->unlock();
593         last_pixmap = pixmap;
594         last_pixmap_used = 1;
595         if( !dont_wait && !shm_reply )
596                 XSync(top_level->display, False);
597         return 0;
598 }
599
600
601 int BC_XImage::read_drawable(Drawable &pixmap, int source_x, int source_y)
602 {
603         XGetSubImage(top_level->display, pixmap,
604                 source_x, source_y, bitmap->w, bitmap->h,
605                 0xffffffff, ZPixmap, ximage, 0, 0);
606         return 0;
607 }
608
609 int BC_XShmImage::read_drawable(Drawable &pixmap, int source_x, int source_y)
610 {
611         XShmGetImage(top_level->display, pixmap,
612                 ximage, source_x, source_y, 0xffffffff);
613         return 0;
614 }
615
616 int BC_Bitmap::read_drawable(Drawable &pixmap, int source_x, int source_y, VFrame *frame)
617 {
618         BC_BitmapImage *bfr = cur_bfr();
619         int result = bfr->read_drawable(pixmap, source_x, source_y);
620         if( !result && frame ) result = bfr->read_frame_rgb(frame);
621         return result;
622 }
623
624
625 // ============================ Decoding VFrames
626
627 int BC_Bitmap::read_frame(VFrame *frame, int x1, int y1, int x2, int y2)
628 {
629         return read_frame(frame, 
630                 0, 0, frame->get_w(), frame->get_h(),
631                 x1, y1, x2 - x1, y2 - y1);
632 }
633
634
635 int BC_Bitmap::read_frame(VFrame *frame, 
636         int in_x, int in_y, int in_w, int in_h,
637         int out_x, int out_y, int out_w, int out_h)
638 {
639         BC_BitmapImage *bfr = cur_bfr();
640         if( hardware_scaling() && frame->get_color_model() == color_model ) {
641 // Hardware accelerated bitmap
642                 switch(color_model) {
643                 case BC_YUV420P:
644                         memcpy(bfr->get_y_data(), frame->get_y(), w * h);
645                         memcpy(bfr->get_u_data(), frame->get_u(), w * h / 4);
646                         memcpy(bfr->get_v_data(), frame->get_v(), w * h / 4);
647                         break;
648                 case BC_YUV422P:
649                         memcpy(bfr->get_y_data(), frame->get_y(), w * h);
650                         memcpy(bfr->get_u_data(), frame->get_u(), w * h / 2);
651                         memcpy(bfr->get_v_data(), frame->get_v(), w * h / 2);
652                         break;
653                 default:
654                 case BC_YUV422:
655                         memcpy(get_data(), frame->get_data(), w * h + w * h);
656                         break;
657                 }
658         }
659         else {
660 // Software only
661
662 //printf("BC_Bitmap::read_frame %d -> %d %d %d %d %d -> %d %d %d %d\n",
663 //  frame->get_color_model(), color_model,
664 //  in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h);
665 //if(color_model == 6 && frame->get_color_model() == 19)
666 //printf("BC_Bitmap::read_frame 1 %d %d %d %d\n", frame->get_w(), frame->get_h(), get_w(), get_h());
667                 BC_CModels::transfer(
668                         bfr->get_row_data(), frame->get_rows(),
669                         bfr->get_y_data(), bfr->get_u_data(), bfr->get_v_data(),
670                         frame->get_y(), frame->get_u(), frame->get_v(),
671                         in_x, in_y, in_w, in_h,
672                         out_x, out_y, out_w, out_h,
673                         frame->get_color_model(), color_model,
674                         bg_color, frame->get_w(), w);
675
676                 if( color_model == BC_TRANSPARENCY && !top_level->server_byte_order )
677                         transparency_bitswap(frame->get_data(), w, h);
678 //if(color_model == 6 && frame->get_color_model() == 19)
679 //printf("BC_Bitmap::read_frame 2\n");
680         }
681
682         return 0;
683 }
684
685 uint8_t BC_Bitmap::bitswap[256]={
686   0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0,
687   0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8,
688   0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4,
689   0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc,
690   0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2,
691   0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa,
692   0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6,
693   0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe,
694   0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1,
695   0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9,
696   0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5,
697   0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd,
698   0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3,
699   0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb,
700   0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7,
701   0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff,
702 };
703
704 void BC_Bitmap::transparency_bitswap(uint8_t *buf, int w, int h)
705 {
706         w = ((w-1) | 7) + 1;
707         int len = w * h / 8;
708         int i;
709         for(i=0 ; i+8<=len ; i+=8){
710                 buf[i+0] = bitswap[buf[i+0]];
711                 buf[i+1] = bitswap[buf[i+1]];
712                 buf[i+2] = bitswap[buf[i+2]];
713                 buf[i+3] = bitswap[buf[i+3]];
714                 buf[i+4] = bitswap[buf[i+4]];
715                 buf[i+5] = bitswap[buf[i+5]];
716                 buf[i+6] = bitswap[buf[i+6]];
717                 buf[i+7] = bitswap[buf[i+7]];
718         }
719         for( ; i<len ; i++)
720                 buf[i+0] = bitswap[buf[i+0]];
721 }
722