瀏覽代碼

X zoom window

David Rose 17 年之前
父節點
當前提交
0f634524be

+ 2 - 21
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -446,27 +446,8 @@ end_scene() {
     int fb_xsize = int(xsize * pixel_factor);
     int fb_xsize = int(xsize * pixel_factor);
     int fb_ysize = int(ysize * 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;
     _c->zb = _current_frame_buffer;
   }
   }
 
 

+ 72 - 20
panda/src/tinydisplay/tinyXGraphicsWindow.cxx

@@ -78,7 +78,8 @@ TinyXGraphicsWindow(GraphicsPipe *pipe,
   _net_wm_state_add = tinyx_pipe->_net_wm_state_add;
   _net_wm_state_add = tinyx_pipe->_net_wm_state_add;
   _net_wm_state_remove = tinyx_pipe->_net_wm_state_remove;
   _net_wm_state_remove = tinyx_pipe->_net_wm_state_remove;
 
 
-  _frame_buffer = NULL;
+  _reduced_frame_buffer = NULL;
+  _full_frame_buffer = NULL;
   _ximage = NULL;
   _ximage = NULL;
   update_pixel_factor();
   update_pixel_factor();
 
 
@@ -159,7 +160,11 @@ begin_frame(FrameMode mode, Thread *current_thread) {
   TinyGraphicsStateGuardian *tinygsg;
   TinyGraphicsStateGuardian *tinygsg;
   DCAST_INTO_R(tinygsg, _gsg, false);
   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();
   tinygsg->reset_if_new();
   
   
   _gsg->set_current_properties(&get_fb_properties());
   _gsg->set_current_properties(&get_fb_properties());
@@ -210,17 +215,25 @@ end_frame(FrameMode mode, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TinyXGraphicsWindow::
 void TinyXGraphicsWindow::
 begin_flip() {
 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
     // If we match the expected bpp, we don't need an intervening copy
     // operation.  Just point the XImage directly at the framebuffer
     // operation.  Just point the XImage directly at the framebuffer
     // data.
     // data.
-    _ximage->data = (char *)_frame_buffer->pbuf;
+    _ximage->data = (char *)_full_frame_buffer->pbuf;
   } else {
   } 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,
   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);
   XFlush(_display);
 }
 }
 
 
@@ -331,8 +344,9 @@ process_events() {
         // A normal window may be resized by the user at will.
         // A normal window may be resized by the user at will.
         properties.set_size(event.xconfigure.width, event.xconfigure.height);
         properties.set_size(event.xconfigure.width, event.xconfigure.height);
         system_changed_properties(properties);
         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();
         create_ximage();
       }
       }
       break;
       break;
@@ -774,16 +788,17 @@ open_window() {
 
 
   _gc = XCreateGC(_display, _xwindow, 0, NULL);
   _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()
     tinydisplay_cat.error()
       << "Could not create frame buffer.\n";
       << "Could not create frame buffer.\n";
     return false;
     return false;
   }
   }
+  create_reduced_frame_buffer();
   create_ximage();
   create_ximage();
   nassertr(_ximage != NULL, false);
   nassertr(_ximage != NULL, false);
 
 
-  tinygsg->_current_frame_buffer = _frame_buffer;
+  tinygsg->_current_frame_buffer = _full_frame_buffer;
   
   
   tinygsg->reset_if_new();
   tinygsg->reset_if_new();
   if (!tinygsg->is_valid()) {
   if (!tinygsg->is_valid()) {
@@ -805,6 +820,17 @@ open_window() {
   return true;
   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
 //     Function: TinyXGraphicsWindow::set_wm_properties
 //       Access: Private
 //       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
 //       Access: Private
 //  Description: Creates a suitable frame buffer for the current
 //  Description: Creates a suitable frame buffer for the current
 //               window size.
 //               window size.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TinyXGraphicsWindow::
 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;
   int mode;
@@ -1610,8 +1636,34 @@ create_frame_buffer() {
     return;
     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;
     _ximage = NULL;
   }
   }
 
 
-  int image_size = _frame_buffer->ysize * _pitch;
+  int image_size = _full_frame_buffer->ysize * _pitch;
   char *data = NULL;
   char *data = NULL;
   if (_bytes_per_pixel != 4) {
   if (_bytes_per_pixel != 4) {
     data = (char *)PANDA_MALLOC_ARRAY(image_size);
     data = (char *)PANDA_MALLOC_ARRAY(image_size);
   }
   }
 
 
   _ximage = XCreateImage(_display, _visual, _depth, ZPixmap, 0, data,
   _ximage = XCreateImage(_display, _visual, _depth, ZPixmap, 0, data,
-                         _frame_buffer->xsize, _frame_buffer->ysize,
+                         _full_frame_buffer->xsize, _full_frame_buffer->ysize,
                          32, 0);
                          32, 0);
 }
 }
 
 

+ 11 - 8
panda/src/tinydisplay/tinyXGraphicsWindow.h

@@ -31,12 +31,12 @@
 class EXPCL_TINYDISPLAY TinyXGraphicsWindow : public GraphicsWindow {
 class EXPCL_TINYDISPLAY TinyXGraphicsWindow : public GraphicsWindow {
 public:
 public:
   TinyXGraphicsWindow(GraphicsPipe *pipe, 
   TinyXGraphicsWindow(GraphicsPipe *pipe, 
-                    const string &name,
-                    const FrameBufferProperties &fb_prop,
-                    const WindowProperties &win_prop,
-                    int flags,
-                    GraphicsStateGuardian *gsg,
-                    GraphicsOutput *host);
+                      const string &name,
+                      const FrameBufferProperties &fb_prop,
+                      const WindowProperties &win_prop,
+                      int flags,
+                      GraphicsStateGuardian *gsg,
+                      GraphicsOutput *host);
   virtual ~TinyXGraphicsWindow();
   virtual ~TinyXGraphicsWindow();
 
 
   virtual bool move_pointer(int device, int x, int y);
   virtual bool move_pointer(int device, int x, int y);
@@ -51,6 +51,7 @@ public:
 protected:
 protected:
   virtual void close_window();
   virtual void close_window();
   virtual bool open_window();
   virtual bool open_window();
+  virtual void pixel_factor_changed();
 
 
 private:
 private:
   void set_wm_properties(const WindowProperties &properties,
   void set_wm_properties(const WindowProperties &properties,
@@ -69,11 +70,13 @@ private:
   void open_raw_mice();
   void open_raw_mice();
   void poll_raw_mice();
   void poll_raw_mice();
 
 
-  void create_frame_buffer();
+  void create_full_frame_buffer();
+  void create_reduced_frame_buffer();
   void create_ximage();
   void create_ximage();
   
   
 private:
 private:
-  ZBuffer *_frame_buffer;
+  ZBuffer *_reduced_frame_buffer;
+  ZBuffer *_full_frame_buffer;
   int _pitch;
   int _pitch;
   XImage *_ximage;
   XImage *_ximage;
 
 

+ 31 - 4
panda/src/tinydisplay/zbuffer.cxx

@@ -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,
                           void *buf,
                           int linesize)
                           int linesize)
 {
 {
@@ -152,7 +152,7 @@ static void ZB_copyBuffer(ZBuffer * zb,
   (((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v) & 0xff) >> 3))
   (((v >> 8) & 0xf800) | (((v) >> 5) & 0x07e0) | (((v) & 0xff) >> 3))
 
 
 /* XXX: not optimized */
 /* XXX: not optimized */
-static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb, 
+static void ZB_copyFrameBuffer5R6G5B(const ZBuffer * zb, 
                                      void *buf, int linesize) 
                                      void *buf, int linesize) 
 {
 {
     PIXEL *q;
     PIXEL *q;
@@ -178,7 +178,7 @@ static void ZB_copyFrameBuffer5R6G5B(ZBuffer * zb,
 }
 }
 
 
 /* XXX: not optimized */
 /* XXX: not optimized */
-static void ZB_copyFrameBufferRGB24(ZBuffer * zb, 
+static void ZB_copyFrameBufferRGB24(const ZBuffer * zb, 
                                     void *buf, int linesize) 
                                     void *buf, int linesize) 
 {
 {
     PIXEL *q;
     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)
 			int linesize)
 {
 {
     switch (zb->mode) {
     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'
  * adr must be aligned on an 'int'

+ 5 - 1
panda/src/tinydisplay/zbuffer.h

@@ -229,7 +229,11 @@ int texcoord_mirror(int coord, int max_coord);
 int texcoord_mirror_once(int coord, int max_coord);
 int texcoord_mirror_once(int coord, int max_coord);
 
 
 /* linesize is in BYTES */
 /* 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 */
 /* zdither.c */