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 //TRACE("BC_Bitmap::write_drawable 1");
425 if(dont_wait) XSync(top_level->display, False);
426 //TRACE("BC_Bitmap::write_drawable 2");
428 if(hardware_scaling())
430 // printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x,
438 //for(int i = 0; i < 1000; i++) xv_image[current_ringbuffer]->data[i] = 255;
439 //printf("BC_Bitmap::write_drawable 2 %d %d %p %p\n", xv_portid,
442 // xv_image[current_ringbuffer]);
443 //TRACE("BC_Bitmap::write_drawable 3");
444 XvShmPutImage(top_level->display,
448 xv_image[current_ringbuffer],
458 //TRACE("BC_Bitmap::write_drawable 4");
459 // Need to pass these to the XvStopVideo
460 last_pixmap = pixmap;
461 last_pixmap_used = 1;
465 // printf("BC_Bitmap::write_drawable %d %d %d %d -> %d %d %d %d\n", source_x,
473 XShmPutImage(top_level->display,
476 ximage[current_ringbuffer],
486 // Force the X server into processing all requests.
487 // This allows the shared memory to be written to again.
488 if(!dont_wait) XSync(top_level->display, False);
489 //TRACE("BC_Bitmap::write_drawable 5");
493 XPutImage(top_level->display,
496 ximage[current_ringbuffer],
505 //printf("BC_Bitmap %d\n", current_ringbuffer);
506 current_ringbuffer++;
507 if(current_ringbuffer >= ring_buffers) current_ringbuffer = 0;
508 //printf("BC_Bitmap::write_drawable 2\n");fflush(stdout);
515 // the bitmap must be wholly contained in the source during a GetImage
516 int BC_Bitmap::read_drawable(Drawable &pixmap, int source_x, int source_y)
519 XShmGetImage(top_level->display, pixmap, ximage[current_ringbuffer], source_x, source_y, 0xffffffff);
521 XGetSubImage(top_level->display, pixmap, source_x, source_y, w, h, 0xffffffff, ZPixmap, ximage[current_ringbuffer], 0, 0);
525 // ============================ Decoding VFrames
527 int BC_Bitmap::read_frame(VFrame *frame,
533 return read_frame(frame,
534 0, 0, frame->get_w(), frame->get_h(),
535 x1, y1, x2 - x1, y2 - y1);
539 int BC_Bitmap::read_frame(VFrame *frame,
551 // Hardware accelerated bitmap
553 if(frame->get_color_model() == color_model)
555 memcpy(get_y_plane(), frame->get_y(), w * h);
556 memcpy(get_u_plane(), frame->get_u(), w * h / 4);
557 memcpy(get_v_plane(), frame->get_v(), w * h / 4);
562 if(frame->get_color_model() == color_model)
564 memcpy(get_y_plane(), frame->get_y(), w * h);
565 memcpy(get_u_plane(), frame->get_u(), w * h / 2);
566 memcpy(get_v_plane(), frame->get_v(), w * h / 2);
571 if(frame->get_color_model() == color_model)
573 memcpy(get_data(), frame->get_data(), w * h + w * h);
579 // printf("BC_Bitmap::read_frame %d -> %d %d %d %d %d -> %d %d %d %d\n",
580 // frame->get_color_model(),
590 // printf("BC_Bitmap::read_frame 1 %d %p\n", bits_per_pixel, frame->get_rows());
591 cmodel_transfer(row_data[current_ringbuffer],
607 frame->get_color_model(),
612 // printf("BC_Bitmap::read_frame 2\n");
620 long BC_Bitmap::get_shm_id()
622 return shm_info.shmid;
625 long BC_Bitmap::get_shm_size()
628 return xv_image[0]->data_size * ring_buffers;
630 return h * ximage[0]->bytes_per_line;
633 long BC_Bitmap::get_shm_offset()
636 return xv_image[0]->data_size * current_ringbuffer;
639 return h * ximage[0]->bytes_per_line * current_ringbuffer;
644 long BC_Bitmap::get_y_shm_offset()
647 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[0];
652 long BC_Bitmap::get_u_shm_offset()
655 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[2];
660 long BC_Bitmap::get_v_shm_offset()
663 return get_shm_offset() + xv_image[current_ringbuffer]->offsets[1];
668 long BC_Bitmap::get_y_offset()
671 return xv_image[current_ringbuffer]->offsets[0];
676 long BC_Bitmap::get_u_offset()
679 return xv_image[current_ringbuffer]->offsets[2];
684 long BC_Bitmap::get_v_offset()
687 return xv_image[current_ringbuffer]->offsets[1];
693 unsigned char** BC_Bitmap::get_row_pointers()
695 return row_data[current_ringbuffer];
698 int BC_Bitmap::get_bytes_per_line()
700 return bytes_per_line;
702 unsigned char* BC_Bitmap::get_data()
704 //printf("BC_Bitmap::get_data %d %p\n",current_ringbuffer , data[current_ringbuffer]);
705 return data[current_ringbuffer];
708 unsigned char* BC_Bitmap::get_y_plane()
710 if(color_model == BC_YUV420P ||
711 color_model == BC_YUV422P)
712 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[0];
717 unsigned char* BC_Bitmap::get_v_plane()
719 if(color_model == BC_YUV420P ||
720 color_model == BC_YUV422P)
721 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[1];
726 unsigned char* BC_Bitmap::get_u_plane()
728 if(color_model == BC_YUV420P ||
729 color_model == BC_YUV422P)
730 return data[current_ringbuffer] + xv_image[current_ringbuffer]->offsets[2];
735 void BC_Bitmap::rewind_ringbuffer()
737 current_ringbuffer--;
738 if(current_ringbuffer < 0) current_ringbuffer = ring_buffers - 1;
741 int BC_Bitmap::hardware_scaling()
743 return (get_color_model() == BC_YUV420P ||
744 get_color_model() == BC_YUV422P ||
745 get_color_model() == BC_YUV422);
748 int BC_Bitmap::get_w() { return w; }
750 int BC_Bitmap::get_h() { return h; }
752 int BC_Bitmap::get_color_model() { return color_model; }