X zoom window

This commit is contained in:
David Rose 2009-02-24 00:49:22 +00:00
parent 5bde231490
commit 0f634524be
5 changed files with 121 additions and 54 deletions

View File

@ -446,27 +446,8 @@ end_scene() {
int fb_xsize = int(xsize * pixel_factor);
int fb_ysize = int(ysize * pixel_factor);
int tyinc = _current_frame_buffer->linesize / PSZB;
int fyinc = _aux_frame_buffer->linesize / PSZB;
int fyt = 0;
for (int ty = 0; ty < ysize; ++ty) {
int fy = fyt / ysize;
fyt += fb_ysize;
PIXEL *tp = _current_frame_buffer->pbuf + xmin + (ymin + ty) * tyinc;
PIXEL *fp = _aux_frame_buffer->pbuf + fy * fyinc;
ZPOINT *tz = _current_frame_buffer->zbuf + xmin + (ymin + ty) * _current_frame_buffer->xsize;
ZPOINT *fz = _aux_frame_buffer->zbuf + fy * _aux_frame_buffer->xsize;
int fxt = 0;
for (int tx = 0; tx < xsize; ++tx) {
int fx = fxt / xsize;
fxt += fb_xsize;
tp[tx] = fp[fx];
tz[tx] = fz[fx];
}
}
ZB_zoomFrameBuffer(_current_frame_buffer, xmin, ymin, xsize, ysize,
_aux_frame_buffer, 0, 0, fb_xsize, fb_ysize);
_c->zb = _current_frame_buffer;
}

View File

@ -78,7 +78,8 @@ TinyXGraphicsWindow(GraphicsPipe *pipe,
_net_wm_state_add = tinyx_pipe->_net_wm_state_add;
_net_wm_state_remove = tinyx_pipe->_net_wm_state_remove;
_frame_buffer = NULL;
_reduced_frame_buffer = NULL;
_full_frame_buffer = NULL;
_ximage = NULL;
update_pixel_factor();
@ -159,7 +160,11 @@ begin_frame(FrameMode mode, Thread *current_thread) {
TinyGraphicsStateGuardian *tinygsg;
DCAST_INTO_R(tinygsg, _gsg, false);
tinygsg->_current_frame_buffer = _frame_buffer;
if (_reduced_frame_buffer != (ZBuffer *)NULL) {
tinygsg->_current_frame_buffer = _reduced_frame_buffer;
} else {
tinygsg->_current_frame_buffer = _full_frame_buffer;
}
tinygsg->reset_if_new();
_gsg->set_current_properties(&get_fb_properties());
@ -210,17 +215,25 @@ end_frame(FrameMode mode, Thread *current_thread) {
////////////////////////////////////////////////////////////////////
void TinyXGraphicsWindow::
begin_flip() {
if (_bytes_per_pixel == 4 && _pitch == _frame_buffer->linesize) {
if (_reduced_frame_buffer != (ZBuffer *)NULL) {
// Zoom the reduced buffer onto the full buffer.
ZB_zoomFrameBuffer(_full_frame_buffer, 0, 0,
_full_frame_buffer->xsize, _full_frame_buffer->ysize,
_reduced_frame_buffer, 0, 0,
_reduced_frame_buffer->xsize, _reduced_frame_buffer->ysize);
}
if (_bytes_per_pixel == 4 && _pitch == _full_frame_buffer->linesize) {
// If we match the expected bpp, we don't need an intervening copy
// operation. Just point the XImage directly at the framebuffer
// data.
_ximage->data = (char *)_frame_buffer->pbuf;
_ximage->data = (char *)_full_frame_buffer->pbuf;
} else {
ZB_copyFrameBuffer(_frame_buffer, _ximage->data, _pitch);
ZB_copyFrameBuffer(_full_frame_buffer, _ximage->data, _pitch);
}
XPutImage(_display, _xwindow, _gc, _ximage, 0, 0, 0, 0,
_frame_buffer->xsize, _frame_buffer->ysize);
_full_frame_buffer->xsize, _full_frame_buffer->ysize);
XFlush(_display);
}
@ -331,8 +344,9 @@ process_events() {
// A normal window may be resized by the user at will.
properties.set_size(event.xconfigure.width, event.xconfigure.height);
system_changed_properties(properties);
ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
_pitch = (_frame_buffer->xsize * _bytes_per_pixel + 3) & ~3;
ZB_resize(_full_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
_pitch = (_full_frame_buffer->xsize * _bytes_per_pixel + 3) & ~3;
create_reduced_frame_buffer();
create_ximage();
}
break;
@ -774,16 +788,17 @@ open_window() {
_gc = XCreateGC(_display, _xwindow, 0, NULL);
create_frame_buffer();
if (_frame_buffer == NULL) {
create_full_frame_buffer();
if (_full_frame_buffer == NULL) {
tinydisplay_cat.error()
<< "Could not create frame buffer.\n";
return false;
}
create_reduced_frame_buffer();
create_ximage();
nassertr(_ximage != NULL, false);
tinygsg->_current_frame_buffer = _frame_buffer;
tinygsg->_current_frame_buffer = _full_frame_buffer;
tinygsg->reset_if_new();
if (!tinygsg->is_valid()) {
@ -805,6 +820,17 @@ open_window() {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: TinyXGraphicsWindow::pixel_factor_changed
// Access: Protected, Virtual
// Description: Called internally when the pixel factor changes.
////////////////////////////////////////////////////////////////////
void TinyXGraphicsWindow::
pixel_factor_changed() {
GraphicsWindow::pixel_factor_changed();
create_reduced_frame_buffer();
}
////////////////////////////////////////////////////////////////////
// Function: TinyXGraphicsWindow::set_wm_properties
// Access: Private
@ -1580,16 +1606,16 @@ check_event(Display *display, XEvent *event, char *arg) {
}
////////////////////////////////////////////////////////////////////
// Function: TinyXGraphicsWindow::create_frame_buffer
// Function: TinyXGraphicsWindow::create_full_frame_buffer
// Access: Private
// Description: Creates a suitable frame buffer for the current
// window size.
////////////////////////////////////////////////////////////////////
void TinyXGraphicsWindow::
create_frame_buffer() {
if (_frame_buffer != NULL) {
ZB_close(_frame_buffer);
_frame_buffer = NULL;
create_full_frame_buffer() {
if (_full_frame_buffer != NULL) {
ZB_close(_full_frame_buffer);
_full_frame_buffer = NULL;
}
int mode;
@ -1610,8 +1636,34 @@ create_frame_buffer() {
return;
}
_frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), mode, 0, 0, 0, 0);
_pitch = (_frame_buffer->xsize * _bytes_per_pixel + 3) & ~3;
_full_frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), mode, 0, 0, 0, 0);
_pitch = (_full_frame_buffer->xsize * _bytes_per_pixel + 3) & ~3;
}
////////////////////////////////////////////////////////////////////
// Function: TinyXGraphicsWindow::create_reduced_frame_buffer
// Access: Private
// Description: Creates a suitable frame buffer for the current
// window size and pixel zoom.
////////////////////////////////////////////////////////////////////
void TinyXGraphicsWindow::
create_reduced_frame_buffer() {
if (_reduced_frame_buffer != NULL) {
ZB_close(_reduced_frame_buffer);
_reduced_frame_buffer = NULL;
}
int x_size = get_fb_x_size();
int y_size = get_fb_y_size();
if (x_size == _full_frame_buffer->xsize) {
// No zooming is necessary.
} else {
// The reduced size is different, so we need a separate buffer to
// render into.
_reduced_frame_buffer = ZB_open(x_size, y_size, _full_frame_buffer->mode, 0, 0, 0, 0);
}
}
@ -1632,14 +1684,14 @@ create_ximage() {
_ximage = NULL;
}
int image_size = _frame_buffer->ysize * _pitch;
int image_size = _full_frame_buffer->ysize * _pitch;
char *data = NULL;
if (_bytes_per_pixel != 4) {
data = (char *)PANDA_MALLOC_ARRAY(image_size);
}
_ximage = XCreateImage(_display, _visual, _depth, ZPixmap, 0, data,
_frame_buffer->xsize, _frame_buffer->ysize,
_full_frame_buffer->xsize, _full_frame_buffer->ysize,
32, 0);
}

View File

@ -51,6 +51,7 @@ public:
protected:
virtual void close_window();
virtual bool open_window();
virtual void pixel_factor_changed();
private:
void set_wm_properties(const WindowProperties &properties,
@ -69,11 +70,13 @@ private:
void open_raw_mice();
void poll_raw_mice();
void create_frame_buffer();
void create_full_frame_buffer();
void create_reduced_frame_buffer();
void create_ximage();
private:
ZBuffer *_frame_buffer;
ZBuffer *_reduced_frame_buffer;
ZBuffer *_full_frame_buffer;
int _pitch;
XImage *_ximage;

View File

@ -130,7 +130,7 @@ void ZB_resize(ZBuffer * zb, void *frame_buffer, int xsize, int ysize)
}
}
static void ZB_copyBuffer(ZBuffer * zb,
static void ZB_copyBuffer(const ZBuffer * zb,
void *buf,
int linesize)
{
@ -152,7 +152,7 @@ static void ZB_copyBuffer(ZBuffer * zb,
(((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v) & 0xff) >> 3))
/* XXX: not optimized */
static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb,
static void ZB_copyFrameBuffer5R6G5B(const ZBuffer * zb,
void *buf, int linesize)
{
PIXEL *q;
@ -178,7 +178,7 @@ static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb,
}
/* XXX: not optimized */
static void ZB_copyFrameBufferRGB24(ZBuffer * zb,
static void ZB_copyFrameBufferRGB24(const ZBuffer * zb,
void *buf, int linesize)
{
PIXEL *q;
@ -204,7 +204,7 @@ static void ZB_copyFrameBufferRGB24(ZBuffer * zb,
}
}
void ZB_copyFrameBuffer(ZBuffer * zb, void *buf,
void ZB_copyFrameBuffer(const ZBuffer * zb, void *buf,
int linesize)
{
switch (zb->mode) {
@ -228,6 +228,33 @@ void ZB_copyFrameBuffer(ZBuffer * zb, void *buf,
}
}
// Copy from (source_xmin,source_ymin)+(source_xsize,source_ysize) to
// (dest_xmin,dest_ymin)+(dest_xsize,dest_ysize).
void ZB_zoomFrameBuffer(ZBuffer *dest, int dest_xmin, int dest_ymin, int dest_xsize, int dest_ysize,
const ZBuffer *source, int source_xmin, int source_ymin, int source_xsize, int source_ysize) {
int tyinc = dest->linesize / PSZB;
int fyinc = source->linesize / PSZB;
int fyt = 0;
for (int ty = 0; ty < dest_ysize; ++ty) {
int fy = fyt / dest_ysize;
fyt += source_ysize;
PIXEL *tp = dest->pbuf + dest_xmin + (dest_ymin + ty) * tyinc;
PIXEL *fp = source->pbuf + source_xmin + (source_ymin + fy) * fyinc;
ZPOINT *tz = dest->zbuf + dest_xmin + (dest_ymin + ty) * dest->xsize;
ZPOINT *fz = source->zbuf + source_xmin + (source_ymin + fy) * source->xsize;
int fxt = 0;
for (int tx = 0; tx < dest_xsize; ++tx) {
int fx = fxt / dest_xsize;
fxt += source_xsize;
tp[tx] = fp[fx];
tz[tx] = fz[fx];
}
}
}
/*
* adr must be aligned on an 'int'

View File

@ -229,7 +229,11 @@ int texcoord_mirror(int coord, int max_coord);
int texcoord_mirror_once(int coord, int max_coord);
/* linesize is in BYTES */
void ZB_copyFrameBuffer(ZBuffer *zb,void *buf,int linesize);
void ZB_copyFrameBuffer(const ZBuffer *zb,void *buf,int linesize);
void ZB_zoomFrameBuffer(ZBuffer *dest, int dest_xmin, int dest_ymin,
int dest_xsize, int dest_ysize,
const ZBuffer *source, int source_xmin, int source_ymin,
int source_xsize, int source_ysize);
/* zdither.c */