3 #include "bcresources.h"
6 #include "colormodels.h"
10 #include <X11/extensions/Xvlib.h>
13 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, unsigned char *png_data)
15 // Decompress data into a temporary vframe
18 frame.read_png(png_data);
20 // Initialize the bitmap
21 initialize(parent_window,
24 parent_window->get_color_model(),
27 // Copy the vframe to the bitmap
28 read_frame(&frame, 0, 0, w, h);
31 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window, VFrame *frame)
33 // Initialize the bitmap
34 initialize(parent_window,
37 parent_window->get_color_model(),
40 // Copy the vframe to the bitmap
41 read_frame(frame, 0, 0, w, h);
44 BC_Bitmap::BC_Bitmap(BC_WindowBase *parent_window,
50 initialize(parent_window,
54 use_shm ? parent_window->get_resources()->use_shm : 0);
57 BC_Bitmap::~BC_Bitmap()
62 int BC_Bitmap::initialize(BC_WindowBase *parent_window,
68 this->parent_window = parent_window;
69 this->top_level = parent_window->top_level;
72 this->color_model = color_model;
73 this->use_shm = use_shm ? parent_window->get_resources()->use_shm : 0;
74 this->bg_color = parent_window->bg_color;
80 current_ringbuffer = 0;
81 // Set ring buffers based on total memory used.
82 // The program icon must use multiple buffers but larger bitmaps may not fit
84 int pixelsize = cmodel_calculate_pixelsize(color_model);
85 int buffer_size = w * h * pixelsize;
87 if(buffer_size < 0x40000)
96 int BC_Bitmap::match_params(int w, int h, int color_model, int use_shm)
98 if(this->w /* != */ < w ||
99 this->h /* != */ < h ||
100 this->color_model != color_model ||
101 this->use_shm != use_shm)
104 initialize(parent_window, w, h, color_model, use_shm);
110 int BC_Bitmap::params_match(int w, int h, int color_model, int use_shm)
115 this->color_model == color_model)
117 if(use_shm == this->use_shm || use_shm == BC_INFINITY)
125 int BC_Bitmap::allocate_data()
127 int want_row_pointers = 1;
129 // Shared memory available
134 // Planar YUV. Must use BC_WindowBase::accel_available before calling this.
139 ring_buffers = BITMAP_RING;
140 xv_portid = top_level->xvideo_port_id;
141 // Create the X Image
142 xv_image[0] = XvShmCreateImage(top_level->display,
144 cmodel_bc_to_x(color_model),
149 // Create the shared memory
150 shm_info.shmid = shmget(IPC_PRIVATE,
151 xv_image[0]->data_size * ring_buffers + 4,
153 if(shm_info.shmid < 0) perror("BC_Bitmap::allocate_data shmget");
154 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
155 // setting ximage->data stops BadValue
156 xv_image[0]->data = shm_info.shmaddr = (char*)data[0];
157 shm_info.readOnly = 0;
159 // Get the real parameters
160 w = xv_image[0]->width;
161 h = xv_image[0]->height;
163 // Create remaining X Images
164 for(int i = 1; i < ring_buffers; i++)
166 data[i] = data[0] + xv_image[0]->data_size * i;
167 xv_image[i] = XvShmCreateImage(top_level->display,
169 cmodel_bc_to_x(color_model),
174 xv_image[i]->data = (char*)data[i];
177 if(color_model == BC_YUV422)
179 bytes_per_line = w * 2;
181 want_row_pointers = 1;
187 want_row_pointers = 0;
193 ring_buffers = BITMAP_RING;
194 // Create first X Image
195 ximage[0] = XShmCreateImage(top_level->display,
198 get_default_depth() == 1 ? XYBitmap : ZPixmap,
204 // Create shared memory
205 shm_info.shmid = shmget(IPC_PRIVATE,
206 h * ximage[0]->bytes_per_line * ring_buffers + 4,
208 if(shm_info.shmid < 0)
209 perror("BC_Bitmap::allocate_data shmget");
210 data[0] = (unsigned char *)shmat(shm_info.shmid, NULL, 0);
211 ximage[0]->data = shm_info.shmaddr = (char*)data[0]; // setting ximage->data stops BadValue
212 shm_info.readOnly = 0;
214 // Get the real parameters
215 bits_per_pixel = ximage[0]->bits_per_pixel;
216 bytes_per_line = ximage[0]->bytes_per_line;
218 // Create remaining X Images
219 for(int i = 1; i < ring_buffers; i++)
221 data[i] = data[0] + h * ximage[0]->bytes_per_line * i;
222 ximage[i] = XShmCreateImage(top_level->display,
225 get_default_depth() == 1 ? XYBitmap : ZPixmap,
230 ximage[i]->data = (char*)data[i];
231 //printf("BC_Bitmap::allocate_data %p\n", ximage[i]);
236 if(!XShmAttach(top_level->display, &shm_info))
238 perror("BC_Bitmap::allocate_data XShmAttach");
241 // This causes it to automatically delete when the program exits.
242 shmctl(shm_info.shmid, IPC_RMID, 0);
245 // Use unshared memory.
248 // need to use bytes_per_line for some X servers
252 //printf("BCBitmap::allocate_data 1\n");
253 ximage[0] = XCreateImage(top_level->display,
256 get_default_depth() == 1 ? XYBitmap : ZPixmap,
263 //printf("BCBitmap::allocate_data 1 %d\n", h * ximage[0]->bytes_per_line + 4);
265 data[0] = (unsigned char*)malloc(h * ximage[0]->bytes_per_line + 4);
266 //printf("BCBitmap::allocate_data 2\n");
268 XDestroyImage(ximage[0]);
269 //printf("BCBitmap::allocate_data 1\n");
271 ximage[0] = XCreateImage(top_level->display,
274 get_default_depth() == 1 ? XYBitmap : ZPixmap,
281 //printf("BCBitmap::allocate_data 1\n");
282 // This differs from the depth parameter of the top_level.
283 bits_per_pixel = ximage[0]->bits_per_pixel;
284 bytes_per_line = ximage[0]->bytes_per_line;
285 //printf("BCBitmap::allocate_data 2\n");
288 // Create row pointers
289 if(want_row_pointers)
291 //printf("BC_Bitmap::allocate 1 %d %d %d %d\n", w, h, get_default_depth(), bytes_per_line);
292 for(int j = 0; j < ring_buffers; j++)
294 row_data[j] = new unsigned char*[h];
295 for(int i = 0; i < h; i++)
297 row_data[j][i] = &data[j][i * bytes_per_line];
304 int BC_Bitmap::delete_data()
315 //printf("BC_Bitmap::delete_data 1\n");
316 if(last_pixmap_used) XvStopVideo(top_level->display, xv_portid, last_pixmap);
317 for(int i = 0; i < ring_buffers; i++)
321 XShmDetach(top_level->display, &shm_info);
322 XvUngrabPort(top_level->display, xv_portid, CurrentTime);
324 shmdt(shm_info.shmaddr);
325 shmctl(shm_info.shmid, IPC_RMID, 0);
329 for(int i = 0; i < ring_buffers; i++)
331 XDestroyImage(ximage[i]);
332 delete [] row_data[i];
334 XShmDetach(top_level->display, &shm_info);
336 shmdt(shm_info.shmaddr);
337 shmctl(shm_info.shmid, IPC_RMID, 0);
343 XDestroyImage(ximage[0]);
344 delete [] row_data[0];
347 // data is automatically freed by XDestroyImage
349 last_pixmap_used = 0;
354 int BC_Bitmap::get_default_depth()
356 if(color_model == BC_TRANSPARENCY)
359 return top_level->default_depth;
363 int BC_Bitmap::set_bg_color(int color)
365 this->bg_color = color;
369 int BC_Bitmap::invert()
371 for(int j = 0; j < ring_buffers; j++)
372 for(int k = 0; k < h; k++)
373 for(int i = 0; i < bytes_per_line; i++)
375 row_data[j][k][i] ^= 0xff;
380 int BC_Bitmap::write_drawable(Drawable &pixmap,
390 return write_drawable(pixmap,
403 void BC_Bitmap::rewind_ring()
405 current_ringbuffer--;
406 if(current_ringbuffer < 0) current_ringbuffer = ring_buffers - 1;
409 int BC_Bitmap::write_drawable(Drawable &pixmap,
421 //printf("BC_Bitmap::write_drawable 1 %p %d\n", this, current_ringbuffer);fflush(stdout);
424 if(dont_wait) XSync(top_level->display, False);
426 if(hardware_scaling())
428 // printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x,
436 //for(int i = 0; i < 1000; i++) xv_image[current_ringbuffer]->data[i] = 255;
437 //printf("BC_Bitmap::write_drawable 2 %d %d %p %p\n", xv_portid,
440 // xv_image[current_ringbuffer]);
441 XvShmPutImage(top_level->display,
445 xv_image[current_ringbuffer],
455 // Need to pass these to the XvStopVideo
456 last_pixmap = pixmap;
457 last_pixmap_used = 1;
461 // printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x,
469 XShmPutImage(top_level->display,
472 ximage[current_ringbuffer],
482 // Force the X server into processing all requests.
483 // This allows the shared memory to be written to again.
484 if(!dont_wait) XSync(top_level->display, False);
485 //TRACE("BC_Bitmap::write_drawable 5");
489 XPutImage(top_level->display,
492 ximage[current_ringbuffer],
501 //printf("BC_Bitmap %d\n", current_ringbuffer);
502 current_ringbuffer++;
503 if(current_ringbuffer >= ring_buffers) current_ringbuffer = 0;
504 //printf("BC_Bitmap::write_drawable 2\n");fflush(stdout);
511 // the bitmap must be wholly contained in the source during a GetImage
512 int BC_Bitmap::read_drawable(Drawable &pixmap, int source_x, int source_y)
515 XShmGetImage(top_level->display, pixmap, ximage[current_ringbuffer], source_x, source_y, 0xffffffff);
517 XGetSubImage(top_level->display, pixmap, source_x, source_y, w, h, 0xffffffff, ZPixmap, ximage[current_ringbuffer], 0, 0);
521 // ============================ Decoding VFrames
523 int BC_Bitmap::read_frame(VFrame *frame,
529 return read_frame(frame,
530 0, 0, frame->get_w(), frame->get_h(),
531 x1, y1, x2 - x1, y2 - y1);
535 int BC_Bitmap::read_frame(VFrame *frame,
547 // Hardware accelerated bitmap
549 if(frame->get_color_model() == color_model)
551 memcpy(get_y_plane(), frame->get_y(), w * h);
552 memcpy(get_u_plane(), frame->get_u(), w * h / 4);
553 memcpy(get_v_plane(), frame->get_v(), w * h / 4);
558 if(frame->get_color_model() == color_model)
560 memcpy(get_y_plane(), frame->get_y(), w * h);
561 memcpy(get_u_plane(), frame->get_u(), w * h / 2);
562 memcpy(get_v_plane(), frame->get_v(), w * h / 2);
567 if(frame->get_color_model() == color_model)
569 memcpy(get_data(), frame->get_data(), w * h + w * h);
575 // printf("BC_Bitmap::read_frame %d -> %d %d %d %d %d -> %d %d %d %d\n",
576 // frame->get_color_model(),
586 // printf("BC_Bitmap::read_frame 1 %d %p\n", bits_per_pixel, frame->get_rows());
587 cmodel_transfer(row_data[current_ringbuffer],
603 frame->get_color_model(),
608 // color model transfer_*_to_TRANSPARENCY don't care about endianness
609 // so buffer bitswaped here if needed.
610 if ((color_model == BC_TRANSPARENCY) && (!top_level->server_byte_order))
611 transparency_bitswap();
614 // printf("BC_Bitmap::read_frame 2\n");
622 long BC_Bitmap::get_shm_id()
624 return shm_info.shmid;
627 long BC_Bitmap::get_shm_size()
630 return xv_image[0]->data_size * ring_buffers;
632 return h * ximage[0]->bytes_per_line;
635 long BC_Bitmap::get_shm_offset()
638 return xv_image[0]->data_size * current_ringbuffer;
641 return h * ximage[0]->bytes_per_line * current_ringbuffer;
646 long BC_Bitmap::get_y_shm_offset()
649 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[0];
654 long BC_Bitmap::get_u_shm_offset()
657 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[2];
662 long BC_Bitmap::get_v_shm_offset()
665 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[1];
670 long BC_Bitmap::get_y_offset()
673 return xv_image[current_ringbuffer]->offsets[0];
678 long BC_Bitmap::get_u_offset()
681 return xv_image[current_ringbuffer]->offsets[2];
686 long BC_Bitmap::get_v_offset()
689 return xv_image[current_ringbuffer]->offsets[1];
695 unsigned char** BC_Bitmap::get_row_pointers()
697 return row_data[current_ringbuffer];
700 int BC_Bitmap::get_bytes_per_line()
702 return bytes_per_line;
704 unsigned char* BC_Bitmap::get_data()
706 //printf("BC_Bitmap::get_data %d %p\n",current_ringbuffer , data[current_ringbuffer]);
707 return data[current_ringbuffer];
710 unsigned char* BC_Bitmap::get_y_plane()
712 if(color_model == BC_YUV420P ||
713 color_model == BC_YUV422P)
714 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[0];
719 unsigned char* BC_Bitmap::get_v_plane()
721 if(color_model == BC_YUV420P ||
722 color_model == BC_YUV422P)
723 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[1];
728 unsigned char* BC_Bitmap::get_u_plane()
730 if(color_model == BC_YUV420P ||
731 color_model == BC_YUV422P)
732 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[2];
737 void BC_Bitmap::rewind_ringbuffer()
739 current_ringbuffer--;
740 if(current_ringbuffer < 0) current_ringbuffer = ring_buffers - 1;
743 int BC_Bitmap::hardware_scaling()
745 return (get_color_model() == BC_YUV420P ||
746 get_color_model() == BC_YUV422P ||
747 get_color_model() == BC_YUV422);
750 int BC_Bitmap::get_w() { return w; }
752 int BC_Bitmap::get_h() { return h; }
754 char BC_Bitmap::byte_bitswap(char src) {
759 if (src & 1) dst |= ((unsigned char)1 << 7);
761 if (src & 1) dst |= ((unsigned char)1 << 6);
763 if (src & 1) dst |= ((unsigned char)1 << 5);
765 if (src & 1) dst |= ((unsigned char)1 << 4);
767 if (src & 1) dst |= ((unsigned char)1 << 3);
769 if (src & 1) dst |= ((unsigned char)1 << 2);
771 if (src & 1) dst |= ((unsigned char)1 << 1);
773 if (src & 1) dst |= ((unsigned char)1 << 0);
778 void BC_Bitmap::transparency_bitswap() {
780 int i, width, height;
783 buf = *row_data[current_ringbuffer];
788 width = width + 8 - (width % 8);
789 len = width * height / 8;
791 for(i=0 ; i+8<=len ; i+=8){
792 buf[i+0] = byte_bitswap(buf[i+0]);
793 buf[i+1] = byte_bitswap(buf[i+1]);
794 buf[i+2] = byte_bitswap(buf[i+2]);
795 buf[i+3] = byte_bitswap(buf[i+3]);
796 buf[i+4] = byte_bitswap(buf[i+4]);
797 buf[i+5] = byte_bitswap(buf[i+5]);
798 buf[i+6] = byte_bitswap(buf[i+6]);
799 buf[i+7] = byte_bitswap(buf[i+7]);
802 buf[i+0] = byte_bitswap(buf[i+0]);
806 int BC_Bitmap::get_color_model() { return color_model; }