Panda3D

tinyWinGraphicsWindow.cxx

00001 // Filename: tinyWinGraphicsWindow.cxx
00002 // Created by:  drose (06May08)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pandabase.h"
00016 
00017 #ifdef WIN32
00018 
00019 #include "tinyWinGraphicsWindow.h"
00020 #include "config_tinydisplay.h"
00021 #include "config_windisplay.h"
00022 #include "tinyWinGraphicsPipe.h"
00023 #include "tinyGraphicsStateGuardian.h"
00024 #include "pStatTimer.h"
00025 
00026 #include <wingdi.h>
00027 
00028 TypeHandle TinyWinGraphicsWindow::_type_handle;
00029 
00030 ////////////////////////////////////////////////////////////////////
00031 //     Function: TinyWinGraphicsWindow::Constructor
00032 //       Access: Public
00033 //  Description:
00034 ////////////////////////////////////////////////////////////////////
00035 TinyWinGraphicsWindow::
00036 TinyWinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe, 
00037                       const string &name,
00038                       const FrameBufferProperties &fb_prop,
00039                       const WindowProperties &win_prop,
00040                       int flags,
00041                       GraphicsStateGuardian *gsg,
00042                       GraphicsOutput *host) :
00043   WinGraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
00044 {
00045   _frame_buffer = NULL;
00046   _hdc = (HDC)0;
00047   update_pixel_factor();
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: TinyWinGraphicsWindow::Destructor
00052 //       Access: Public, Virtual
00053 //  Description:
00054 ////////////////////////////////////////////////////////////////////
00055 TinyWinGraphicsWindow::
00056 ~TinyWinGraphicsWindow() {
00057 }
00058 
00059 ////////////////////////////////////////////////////////////////////
00060 //     Function: TinyWinGraphicsWindow::begin_frame
00061 //       Access: Public, Virtual
00062 //  Description: This function will be called within the draw thread
00063 //               before beginning rendering for a given frame.  It
00064 //               should do whatever setup is required, and return true
00065 //               if the frame should be rendered, or false if it
00066 //               should be skipped.
00067 ////////////////////////////////////////////////////////////////////
00068 bool TinyWinGraphicsWindow::
00069 begin_frame(FrameMode mode, Thread *current_thread) {
00070   begin_frame_spam(mode);
00071   if (_gsg == (GraphicsStateGuardian *)NULL) {
00072     return false;
00073   }
00074 
00075   TinyGraphicsStateGuardian *tinygsg;
00076   DCAST_INTO_R(tinygsg, _gsg, false);
00077 
00078   tinygsg->_current_frame_buffer = _frame_buffer;
00079   tinygsg->reset_if_new();
00080   
00081   _gsg->set_current_properties(&get_fb_properties());
00082   return _gsg->begin_frame(current_thread);
00083 }
00084 
00085 ////////////////////////////////////////////////////////////////////
00086 //     Function: TinyWinGraphicsWindow::end_frame
00087 //       Access: Public, Virtual
00088 //  Description: This function will be called within the draw thread
00089 //               after rendering is completed for a given frame.  It
00090 //               should do whatever finalization is required.
00091 ////////////////////////////////////////////////////////////////////
00092 void TinyWinGraphicsWindow::
00093 end_frame(FrameMode mode, Thread *current_thread) {
00094   end_frame_spam(mode);
00095   nassertv(_gsg != (GraphicsStateGuardian *)NULL);
00096 
00097   if (mode == FM_render) {
00098     // end_render_texture();
00099     copy_to_textures();
00100   }
00101 
00102   _gsg->end_frame(current_thread);
00103 
00104   if (mode == FM_render) {
00105     trigger_flip();
00106     if (_one_shot) {
00107       prepare_for_deletion();
00108     }
00109     clear_cube_map_selection();
00110   }
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: TinyWinGraphicsWindow::begin_flip
00115 //       Access: Public, Virtual
00116 //  Description: This function will be called within the draw thread
00117 //               after end_frame() has been called on all windows, to
00118 //               initiate the exchange of the front and back buffers.
00119 //
00120 //               This should instruct the window to prepare for the
00121 //               flip at the next video sync, but it should not wait.
00122 //
00123 //               We have the two separate functions, begin_flip() and
00124 //               end_flip(), to make it easier to flip all of the
00125 //               windows at the same time.
00126 ////////////////////////////////////////////////////////////////////
00127 void TinyWinGraphicsWindow::
00128 begin_flip() {
00129   HBITMAP bm = CreateCompatibleBitmap(_hdc, _frame_buffer->xsize, _frame_buffer->ysize);
00130   HDC bmdc = CreateCompatibleDC(_hdc);
00131   SelectObject(bmdc, bm);
00132 
00133   int fb_xsize = get_fb_x_size();
00134   int fb_ysize = get_fb_y_size();
00135   int fb_ytop = _frame_buffer->ysize - fb_ysize;
00136 
00137   SetDIBits(_hdc, bm, fb_ytop, fb_ysize, _frame_buffer->pbuf,
00138             &_bitmap_info, DIB_RGB_COLORS);
00139 
00140   if (fb_xsize == _frame_buffer->xsize) {
00141     BitBlt(_hdc, 0, 0, fb_xsize, fb_ysize,
00142            bmdc, 0, 0, SRCCOPY);
00143   } else {
00144     //    SetStretchBltMode(_hdc, HALFTONE);
00145     StretchBlt(_hdc, 0, 0, _frame_buffer->xsize, _frame_buffer->ysize,
00146                bmdc, 0, 0,fb_xsize, fb_ysize,
00147                SRCCOPY);
00148   }
00149     
00150   DeleteDC(bmdc);
00151   DeleteObject(bm);
00152   GdiFlush();
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: TinyWinGraphicsWindow::supports_pixel_zoom
00157 //       Access: Published, Virtual
00158 //  Description: Returns true if a call to set_pixel_zoom() will be
00159 //               respected, false if it will be ignored.  If this
00160 //               returns false, then get_pixel_factor() will always
00161 //               return 1.0, regardless of what value you specify for
00162 //               set_pixel_zoom().
00163 //
00164 //               This may return false if the underlying renderer
00165 //               doesn't support pixel zooming, or if you have called
00166 //               this on a DisplayRegion that doesn't have both
00167 //               set_clear_color() and set_clear_depth() enabled.
00168 ////////////////////////////////////////////////////////////////////
00169 bool TinyWinGraphicsWindow::
00170 supports_pixel_zoom() const {
00171   return true;
00172 }
00173 
00174 ////////////////////////////////////////////////////////////////////
00175 //     Function: TinyWinGraphicsWindow::close_window
00176 //       Access: Protected, Virtual
00177 //  Description: Closes the window right now.  Called from the window
00178 //               thread.
00179 ////////////////////////////////////////////////////////////////////
00180 void TinyWinGraphicsWindow::
00181 close_window() {
00182   if (_gsg != (GraphicsStateGuardian *)NULL) {
00183     TinyGraphicsStateGuardian *tinygsg;
00184     DCAST_INTO_V(tinygsg, _gsg);
00185     tinygsg->_current_frame_buffer = NULL;
00186     _gsg.clear();
00187     _active = false;
00188   }
00189 
00190   ReleaseDC(_hWnd, _hdc);
00191   _hdc = (HDC)0;
00192   WinGraphicsWindow::close_window();
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: TinyWinGraphicsWindow::open_window
00197 //       Access: Protected, Virtual
00198 //  Description: Opens the window right now.  Called from the window
00199 //               thread.  Returns true if the window is successfully
00200 //               opened, or false if there was a problem.
00201 ////////////////////////////////////////////////////////////////////
00202 bool TinyWinGraphicsWindow::
00203 open_window() {
00204   if (!WinGraphicsWindow::open_window()) {
00205     return false;
00206   }
00207 
00208   // GSG Creation/Initialization
00209   TinyGraphicsStateGuardian *tinygsg;
00210   if (_gsg == 0) {
00211     // There is no old gsg.  Create a new one.
00212     tinygsg = new TinyGraphicsStateGuardian(_engine, _pipe, NULL);
00213     _gsg = tinygsg;
00214   } else {
00215     DCAST_INTO_R(tinygsg, _gsg, false);
00216   }
00217   
00218   _hdc = GetDC(_hWnd);
00219 
00220   create_frame_buffer();
00221   if (_frame_buffer == NULL) {
00222     tinydisplay_cat.error()
00223       << "Could not create frame buffer.\n";
00224     return false;
00225   }
00226 
00227   tinygsg->_current_frame_buffer = _frame_buffer;
00228   
00229   tinygsg->reset_if_new();
00230   if (!tinygsg->is_valid()) {
00231     close_window();
00232     return false;
00233   }
00234 
00235   return true;
00236 }
00237 
00238 ////////////////////////////////////////////////////////////////////
00239 //     Function: WinGraphicsWindow::handle_reshape
00240 //       Access: Protected, Virtual
00241 //  Description: Called in the window thread when the window size or
00242 //               location is changed, this updates the properties
00243 //               structure accordingly.
00244 ////////////////////////////////////////////////////////////////////
00245 void TinyWinGraphicsWindow::
00246 handle_reshape() {
00247   WinGraphicsWindow::handle_reshape();
00248   ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
00249   setup_bitmap_info();
00250 }
00251 
00252 ////////////////////////////////////////////////////////////////////
00253 //     Function: WinGraphicsWindow::do_fullscreen_resize
00254 //       Access: Protected, Virtual
00255 //  Description: Called in the window thread when the window size or
00256 //               location is changed, this updates the properties
00257 //               structure accordingly.
00258 ////////////////////////////////////////////////////////////////////
00259 bool TinyWinGraphicsWindow::
00260 do_fullscreen_resize(int x_size, int y_size) {
00261   bool result = WinGraphicsWindow::do_fullscreen_resize(x_size, y_size);
00262   ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
00263   setup_bitmap_info();
00264   return result;
00265 }
00266 
00267 ////////////////////////////////////////////////////////////////////
00268 //     Function: TinyWinGraphicsWindow::create_frame_buffer
00269 //       Access: Private
00270 //  Description: Creates a suitable frame buffer for the current
00271 //               window size.
00272 ////////////////////////////////////////////////////////////////////
00273 void TinyWinGraphicsWindow::
00274 create_frame_buffer() {
00275   if (_frame_buffer != NULL) {
00276     ZB_close(_frame_buffer);
00277     _frame_buffer = NULL;
00278   }
00279 
00280   _frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), ZB_MODE_RGBA, 0, 0, 0, 0);
00281   setup_bitmap_info();
00282 }
00283 
00284 ////////////////////////////////////////////////////////////////////
00285 //     Function: TinyWinGraphicsWindow::setup_bitmap_info
00286 //       Access: Private
00287 //  Description: Determines the BITMAPINFO stuff for blitting the
00288 //               frame buffer to the window.
00289 ////////////////////////////////////////////////////////////////////
00290 void TinyWinGraphicsWindow::
00291 setup_bitmap_info() {
00292   _bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00293   _bitmap_info.bmiHeader.biWidth = _frame_buffer->xsize;
00294   _bitmap_info.bmiHeader.biHeight = -_frame_buffer->ysize;
00295   _bitmap_info.bmiHeader.biPlanes = 1;
00296   _bitmap_info.bmiHeader.biBitCount = 32;
00297   _bitmap_info.bmiHeader.biCompression = BI_RGB;
00298   _bitmap_info.bmiHeader.biSizeImage = _frame_buffer->linesize * _frame_buffer->ysize;
00299   _bitmap_info.bmiHeader.biXPelsPerMeter = 0;
00300   _bitmap_info.bmiHeader.biYPelsPerMeter = 0;
00301   _bitmap_info.bmiHeader.biClrUsed = 0;
00302   _bitmap_info.bmiHeader.biClrImportant = 0;
00303 }
00304 
00305 #endif  // WIN32
 All Classes Functions Variables Enumerations