3 #include "bcresources.h"
6 #include "colormodels.h"
11 #include <X11/extensions/Xvlib.h>
14 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, unsigned char *png_data)
16 // Decompress data into a temporary vframe
19 frame.read_png(png_data);
21 // Initialize the bitmap
22 initialize(parent_window,
25 parent_window->get_color_model(),
28 // Copy the vframe to the bitmap
29 read_frame(&frame, 0, 0, w, h);
32 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, VFrame *frame)
34 // Initialize the bitmap
35 initialize(parent_window,
38 parent_window->get_color_model(),
41 // Copy the vframe to the bitmap
42 read_frame(frame, 0, 0, w, h);
45 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window,
51 initialize(parent_window,
55 use_shm ? parent_window->get_resources()->use_shm : 0);
58 BC_Bitmap::~BC_Bitmap()
63 int BC_Bitmap::initialize(BC_WindowBase *parent_window,
69 this->parent_window = parent_window;
70 this->top_level = parent_window->top_level;
73 this->color_model = color_model;
74 this->use_shm = use_shm ? parent_window->get_resources()->use_shm : 0;
75 this->bg_color = parent_window->bg_color;
81 current_ringbuffer = 0;
82 // Set ring buffers based on total memory used.
83 // The program icon must use multiple buffers but larger bitmaps may not fit
85 int pixelsize = cmodel_calculate_pixelsize(color_model);
86 int buffer_size = w * h * pixelsize;
88 if(buffer_size < 0x40000)
97 int BC_Bitmap::match_params(int w, int h, int color_model, int use_shm)
99 if(this->w /* != */ < w ||
100 this->h /* != */ < h ||
101 this->color_model != color_model ||
102 this->use_shm != use_shm)
105 initialize(parent_window, w, h, color_model, use_shm);
111 int BC_Bitmap::params_match(int w, int h, int color_model, int use_shm)
116 this->color_model == color_model)
118 if(use_shm == this->use_shm || use_shm == BC_INFINITY)
126 int BC_Bitmap::allocate_data()
128 int want_row_pointers = 1;
130 // Shared memory available
135 // Planar YUV. Must use BC_WindowBase::accel_available before calling this.
140 ring_buffers = BITMAP_RING;
141 xv_portid = top_level->xvideo_port_id;
142 // Create the X Image
143 xv_image[0] = XvShmCreateImage(top_level->display,
145 cmodel_bc_to_x(color_model),
150 // Create the shared memory
151 shm_info.shmid = shmget(IPC_PRIVATE,
152 xv_image[0]->data_size * ring_buffers + 4,
154 if(shm_info.shmid < 0) perror("BC_Bitmap::allocate_data shmget");
155 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
156 // setting ximage->data stops BadValue
157 xv_image[0]->data = shm_info.shmaddr = (char*)data[0];
158 shm_info.readOnly = 0;
160 // Get the real parameters
161 w = xv_image[0]->width;
162 h = xv_image[0]->height;
164 // Create remaining X Images
165 for(int i = 1; i < ring_buffers; i++)
167 data[i] = data[0] + xv_image[0]->data_size * i;
168 xv_image[i] = XvShmCreateImage(top_level->display,
170 cmodel_bc_to_x(color_model),
175 xv_image[i]->data = (char*)data[i];
178 if(color_model == BC_YUV422)
180 bytes_per_line = w * 2;
182 want_row_pointers = 1;
188 want_row_pointers = 0;
194 ring_buffers = BITMAP_RING;
195 // Create first X Image
196 ximage[0] = XShmCreateImage(top_level->display,
199 get_default_depth() == 1 ? XYBitmap : ZPixmap,
205 // Create shared memory
206 shm_info.shmid = shmget(IPC_PRIVATE,
207 h * ximage[0]->bytes_per_line * ring_buffers + 4,
209 if(shm_info.shmid < 0)
210 perror("BC_Bitmap::allocate_data shmget");
211 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
212 ximage[0]->data = shm_info.shmaddr = (char*)data[0]; // setting ximage->data stops BadValue
213 shm_info.readOnly = 0;
215 // Get the real parameters
216 bits_per_pixel = ximage[0]->bits_per_pixel;
217 bytes_per_line = ximage[0]->bytes_per_line;
219 // Create remaining X Images
220 for(int i = 1; i < ring_buffers; i++)
222 data[i] = data[0] + h * ximage[0]->bytes_per_line * i;
223 ximage[i] = XShmCreateImage(top_level->display,
226 get_default_depth() == 1 ? XYBitmap : ZPixmap,
231 ximage[i]->data = (char*)data[i];
232 //printf("BC_Bitmap::allocate_data %p\n", ximage[i]);
237 if(!XShmAttach(top_level->display, &shm_info))
239 perror("BC_Bitmap::allocate_data XShmAttach");
242 // This causes it to automatically delete when the program exits.
243 shmctl(shm_info.shmid, IPC_RMID, 0);
246 // Use unshared memory.
249 // need to use bytes_per_line for some X servers
253 //printf("BCBitmap::allocate_data 1\n");
254 ximage[0] = XCreateImage(top_level->display,
257 get_default_depth() == 1 ? XYBitmap : ZPixmap,
264 //printf("BCBitmap::allocate_data 1 %d\n", h * ximage[0]->bytes_per_line + 4);
266 data[0] = (unsigned char*)malloc(h * ximage[0]->bytes_per_line + 4);
267 //printf("BCBitmap::allocate_data 2\n");
269 XDestroyImage(ximage[0]);
270 //printf("BCBitmap::allocate_data 1\n");
272 ximage[0] = XCreateImage(top_level->display,
275 get_default_depth() == 1 ? XYBitmap : ZPixmap,
282 //printf("BCBitmap::allocate_data 1\n");
283 // This differs from the depth parameter of the top_level.
284 bits_per_pixel = ximage[0]->bits_per_pixel;
285 bytes_per_line = ximage[0]->bytes_per_line;
286 //printf("BCBitmap::allocate_data 2\n");
289 // Create row pointers
290 if(want_row_pointers)
292 //printf("BC_Bitmap::allocate 1 %d %d %d %d\n", w, h, get_default_depth(), bytes_per_line);
293 for(int j = 0; j < ring_buffers; j++)
295 row_data[j] = new unsigned char*[h];
296 for(int i = 0; i < h; i++)
298 row_data[j][i] = &data[j][i * bytes_per_line];
305 int BC_Bitmap::delete_data()
316 //printf("BC_Bitmap::delete_data 1\n");
317 if(last_pixmap_used) XvStopVideo(top_level->display, xv_portid, last_pixmap);
318 for(int i = 0; i < ring_buffers; i++)
322 XShmDetach(top_level->display, &shm_info);
323 XvUngrabPort(top_level->display, xv_portid, CurrentTime);
325 shmdt(shm_info.shmaddr);
326 shmctl(shm_info.shmid, IPC_RMID, 0);
330 for(int i = 0; i < ring_buffers; i++)
332 XDestroyImage(ximage[i]);
333 delete [] row_data[i];
335 XShmDetach(top_level->display, &shm_info);
337 shmdt(shm_info.shmaddr);
338 shmctl(shm_info.shmid, IPC_RMID, 0);
344 XDestroyImage(ximage[0]);
345 delete [] row_data[0];
348 // data is automatically freed by XDestroyImage
350 last_pixmap_used = 0;
355 int BC_Bitmap::get_default_depth()
357 if(color_model == BC_TRANSPARENCY)
360 return top_level->default_depth;
364 int BC_Bitmap::set_bg_color(int color)
366 this->bg_color = color;
370 int BC_Bitmap::invert()
372 for(int j = 0; j < ring_buffers; j++)
373 for(int k = 0; k < h; k++)
374 for(int i = 0; i < bytes_per_line; i++)
376 row_data[j][k][i] ^= 0xff;
381 int BC_Bitmap::write_drawable(Drawable &pixmap,
391 return write_drawable(pixmap,
404 void BC_Bitmap::rewind_ring()
406 current_ringbuffer--;
407 if(current_ringbuffer < 0) current_ringbuffer = ring_buffers - 1;
410 int BC_Bitmap::write_drawable(Drawable &pixmap,
422 //printf("BC_Bitmap::write_drawable 1 %p %d\n", this, current_ringbuffer);fflush(stdout);
425 if(dont_wait) XSync(top_level->display, False);
427 if(hardware_scaling())
429 // printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x,
437 //for(int i = 0; i < 1000; i++) xv_image[current_ringbuffer]->data[i] = 255;
438 //printf("BC_Bitmap::write_drawable 2 %d %d %p %p\n", xv_portid,
441 // xv_image[current_ringbuffer]);
442 XvShmPutImage(top_level->display,
446 xv_image[current_ringbuffer],
456 // Need to pass these to the XvStopVideo
457 last_pixmap = pixmap;
458 last_pixmap_used = 1;
462 // printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x,
470 XShmPutImage(top_level->display,
473 ximage[current_ringbuffer],
483 // Force the X server into processing all requests.
484 // This allows the shared memory to be written to again.
485 if(!dont_wait) XSync(top_level->display, False);
486 //TRACE("BC_Bitmap::write_drawable 5");
490 XPutImage(top_level->display,
493 ximage[current_ringbuffer],
502 //printf("BC_Bitmap %d\n", current_ringbuffer);
503 current_ringbuffer++;
504 if(current_ringbuffer >= ring_buffers) current_ringbuffer = 0;
505 //printf("BC_Bitmap::write_drawable 2\n");fflush(stdout);
512 // the bitmap must be wholly contained in the source during a GetImage
513 int BC_Bitmap::read_drawable(Drawable &pixmap, int source_x, int source_y)
516 XShmGetImage(top_level->display, pixmap, ximage[current_ringbuffer], source_x, source_y, 0xffffffff);
518 XGetSubImage(top_level->display, pixmap, source_x, source_y, w, h, 0xffffffff, ZPixmap, ximage[current_ringbuffer], 0, 0);
522 // ============================ Decoding VFrames
524 int BC_Bitmap::read_frame(VFrame *frame,
530 return read_frame(frame,
531 0, 0, frame->get_w(), frame->get_h(),
532 x1, y1, x2 - x1, y2 - y1);
536 int BC_Bitmap::read_frame(VFrame *frame,
548 // Hardware accelerated bitmap
550 if(frame->get_color_model() == color_model)
552 memcpy(get_y_plane(), frame->get_y(), w * h);
553 memcpy(get_u_plane(), frame->get_u(), w * h / 4);
554 memcpy(get_v_plane(), frame->get_v(), w * h / 4);
559 if(frame->get_color_model() == color_model)
561 memcpy(get_y_plane(), frame->get_y(), w * h);
562 memcpy(get_u_plane(), frame->get_u(), w * h / 2);
563 memcpy(get_v_plane(), frame->get_v(), w * h / 2);
568 if(frame->get_color_model() == color_model)
570 memcpy(get_data(), frame->get_data(), w * h + w * h);
576 // printf("BC_Bitmap::read_frame %d -> %d %d %d %d %d -> %d %d %d %d\n",
577 // frame->get_color_model(),
587 //if(color_model == 6 && frame->get_color_model() == 19)
588 //printf("BC_Bitmap::read_frame 1 %d %d %d %d\n", frame->get_w(), frame->get_h(), get_w(), get_h());
589 cmodel_transfer(row_data[current_ringbuffer],
605 frame->get_color_model(),
610 // color model transfer_*_to_TRANSPARENCY don't care about endianness
611 // so buffer bitswaped here if needed.
612 if ((color_model == BC_TRANSPARENCY) && (!top_level->server_byte_order))
613 transparency_bitswap();
616 //if(color_model == 6 && frame->get_color_model() == 19)
617 //printf("BC_Bitmap::read_frame 2\n");
625 long BC_Bitmap::get_shm_id()
627 return shm_info.shmid;
630 long BC_Bitmap::get_shm_size()
633 return xv_image[0]->data_size * ring_buffers;
635 return h * ximage[0]->bytes_per_line;
638 long BC_Bitmap::get_shm_offset()
641 return xv_image[0]->data_size * current_ringbuffer;
644 return h * ximage[0]->bytes_per_line * current_ringbuffer;
649 long BC_Bitmap::get_y_shm_offset()
652 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[0];
657 long BC_Bitmap::get_u_shm_offset()
660 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[2];
665 long BC_Bitmap::get_v_shm_offset()
668 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[1];
673 long BC_Bitmap::get_y_offset()
676 return xv_image[current_ringbuffer]->offsets[0];
681 long BC_Bitmap::get_u_offset()
683 if(xv_image[0] && xv_image[current_ringbuffer]->num_planes > 1)
684 return xv_image[current_ringbuffer]->offsets[2];
689 long BC_Bitmap::get_v_offset()
691 if(xv_image[0] && xv_image[current_ringbuffer]->num_planes > 1)
692 return xv_image[current_ringbuffer]->offsets[1];
698 unsigned char** BC_Bitmap::get_row_pointers()
700 return row_data[current_ringbuffer];
703 int BC_Bitmap::get_bytes_per_line()
705 return bytes_per_line;
707 unsigned char* BC_Bitmap::get_data()
709 //printf("BC_Bitmap::get_data %d %p\n",current_ringbuffer , data[current_ringbuffer]);
710 return data[current_ringbuffer];
713 unsigned char* BC_Bitmap::get_y_plane()
715 if(color_model == BC_YUV420P ||
716 color_model == BC_YUV422P)
717 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[0];
722 unsigned char* BC_Bitmap::get_v_plane()
724 if(color_model == BC_YUV420P ||
725 color_model == BC_YUV422P)
726 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[1];
731 unsigned char* BC_Bitmap::get_u_plane()
733 if(color_model == BC_YUV420P ||
734 color_model == BC_YUV422P)
735 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[2];
740 void BC_Bitmap::rewind_ringbuffer()
742 current_ringbuffer--;
743 if(current_ringbuffer < 0) current_ringbuffer = ring_buffers - 1;
746 int BC_Bitmap::hardware_scaling()
748 return (get_color_model() == BC_YUV420P ||
749 get_color_model() == BC_YUV422P ||
750 get_color_model() == BC_YUV422);
753 int BC_Bitmap::get_w() { return w; }
755 int BC_Bitmap::get_h() { return h; }
757 char BC_Bitmap::byte_bitswap(char src) {
762 if (src & 1) dst |= ((unsigned char)1 << 7);
764 if (src & 1) dst |= ((unsigned char)1 << 6);
766 if (src & 1) dst |= ((unsigned char)1 << 5);
768 if (src & 1) dst |= ((unsigned char)1 << 4);
770 if (src & 1) dst |= ((unsigned char)1 << 3);
772 if (src & 1) dst |= ((unsigned char)1 << 2);
774 if (src & 1) dst |= ((unsigned char)1 << 1);
776 if (src & 1) dst |= ((unsigned char)1 << 0);
781 void BC_Bitmap::transparency_bitswap() {
783 int i, width, height;
786 buf = *row_data[current_ringbuffer];
791 width = width + 8 - (width % 8);
792 len = width * height / 8;
794 for(i=0 ; i+8<=len ; i+=8){
795 buf[i+0] = byte_bitswap(buf[i+0]);
796 buf[i+1] = byte_bitswap(buf[i+1]);
797 buf[i+2] = byte_bitswap(buf[i+2]);
798 buf[i+3] = byte_bitswap(buf[i+3]);
799 buf[i+4] = byte_bitswap(buf[i+4]);
800 buf[i+5] = byte_bitswap(buf[i+5]);
801 buf[i+6] = byte_bitswap(buf[i+6]);
802 buf[i+7] = byte_bitswap(buf[i+7]);
805 buf[i+0] = byte_bitswap(buf[i+0]);
809 int BC_Bitmap::get_color_model() { return color_model; }