Panda3D
|
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 if (!get_unexposed_draw() && !_got_expose_event) { 00076 if (tinydisplay_cat.is_spam()) { 00077 tinydisplay_cat.spam() 00078 << "Not drawing " << this << ": unexposed.\n"; 00079 } 00080 return false; 00081 } 00082 00083 TinyGraphicsStateGuardian *tinygsg; 00084 DCAST_INTO_R(tinygsg, _gsg, false); 00085 00086 tinygsg->_current_frame_buffer = _frame_buffer; 00087 tinygsg->reset_if_new(); 00088 00089 _gsg->set_current_properties(&get_fb_properties()); 00090 return _gsg->begin_frame(current_thread); 00091 } 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: TinyWinGraphicsWindow::end_frame 00095 // Access: Public, Virtual 00096 // Description: This function will be called within the draw thread 00097 // after rendering is completed for a given frame. It 00098 // should do whatever finalization is required. 00099 //////////////////////////////////////////////////////////////////// 00100 void TinyWinGraphicsWindow:: 00101 end_frame(FrameMode mode, Thread *current_thread) { 00102 end_frame_spam(mode); 00103 nassertv(_gsg != (GraphicsStateGuardian *)NULL); 00104 00105 if (mode == FM_render) { 00106 // end_render_texture(); 00107 copy_to_textures(); 00108 } 00109 00110 _gsg->end_frame(current_thread); 00111 00112 if (mode == FM_render) { 00113 trigger_flip(); 00114 clear_cube_map_selection(); 00115 } 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: TinyWinGraphicsWindow::end_flip 00120 // Access: Public, Virtual 00121 // Description: This function will be called within the draw thread 00122 // after begin_flip() has been called on all windows, to 00123 // finish the exchange of the front and back buffers. 00124 // 00125 // This should cause the window to wait for the flip, if 00126 // necessary. 00127 //////////////////////////////////////////////////////////////////// 00128 void TinyWinGraphicsWindow:: 00129 end_flip() { 00130 if (!_flip_ready) { 00131 GraphicsWindow::end_flip(); 00132 return; 00133 } 00134 00135 HBITMAP bm = CreateCompatibleBitmap(_hdc, _frame_buffer->xsize, _frame_buffer->ysize); 00136 HDC bmdc = CreateCompatibleDC(_hdc); 00137 SelectObject(bmdc, bm); 00138 00139 int fb_xsize = get_fb_x_size(); 00140 int fb_ysize = get_fb_y_size(); 00141 int fb_ytop = _frame_buffer->ysize - fb_ysize; 00142 00143 SetDIBits(_hdc, bm, fb_ytop, fb_ysize, _frame_buffer->pbuf, 00144 &_bitmap_info, DIB_RGB_COLORS); 00145 00146 if (fb_xsize == _frame_buffer->xsize) { 00147 BitBlt(_hdc, 0, 0, fb_xsize, fb_ysize, 00148 bmdc, 0, 0, SRCCOPY); 00149 } else { 00150 // SetStretchBltMode(_hdc, HALFTONE); 00151 StretchBlt(_hdc, 0, 0, _frame_buffer->xsize, _frame_buffer->ysize, 00152 bmdc, 0, 0,fb_xsize, fb_ysize, 00153 SRCCOPY); 00154 } 00155 00156 DeleteDC(bmdc); 00157 DeleteObject(bm); 00158 GdiFlush(); 00159 GraphicsWindow::end_flip(); 00160 } 00161 00162 //////////////////////////////////////////////////////////////////// 00163 // Function: TinyWinGraphicsWindow::supports_pixel_zoom 00164 // Access: Published, Virtual 00165 // Description: Returns true if a call to set_pixel_zoom() will be 00166 // respected, false if it will be ignored. If this 00167 // returns false, then get_pixel_factor() will always 00168 // return 1.0, regardless of what value you specify for 00169 // set_pixel_zoom(). 00170 // 00171 // This may return false if the underlying renderer 00172 // doesn't support pixel zooming, or if you have called 00173 // this on a DisplayRegion that doesn't have both 00174 // set_clear_color() and set_clear_depth() enabled. 00175 //////////////////////////////////////////////////////////////////// 00176 bool TinyWinGraphicsWindow:: 00177 supports_pixel_zoom() const { 00178 return true; 00179 } 00180 00181 //////////////////////////////////////////////////////////////////// 00182 // Function: TinyWinGraphicsWindow::close_window 00183 // Access: Protected, Virtual 00184 // Description: Closes the window right now. Called from the window 00185 // thread. 00186 //////////////////////////////////////////////////////////////////// 00187 void TinyWinGraphicsWindow:: 00188 close_window() { 00189 if (_gsg != (GraphicsStateGuardian *)NULL) { 00190 TinyGraphicsStateGuardian *tinygsg; 00191 DCAST_INTO_V(tinygsg, _gsg); 00192 tinygsg->_current_frame_buffer = NULL; 00193 _gsg.clear(); 00194 } 00195 00196 ReleaseDC(_hWnd, _hdc); 00197 _hdc = (HDC)0; 00198 WinGraphicsWindow::close_window(); 00199 } 00200 00201 //////////////////////////////////////////////////////////////////// 00202 // Function: TinyWinGraphicsWindow::open_window 00203 // Access: Protected, Virtual 00204 // Description: Opens the window right now. Called from the window 00205 // thread. Returns true if the window is successfully 00206 // opened, or false if there was a problem. 00207 //////////////////////////////////////////////////////////////////// 00208 bool TinyWinGraphicsWindow:: 00209 open_window() { 00210 if (!WinGraphicsWindow::open_window()) { 00211 return false; 00212 } 00213 00214 // GSG Creation/Initialization 00215 TinyGraphicsStateGuardian *tinygsg; 00216 if (_gsg == 0) { 00217 // There is no old gsg. Create a new one. 00218 tinygsg = new TinyGraphicsStateGuardian(_engine, _pipe, NULL); 00219 _gsg = tinygsg; 00220 } else { 00221 DCAST_INTO_R(tinygsg, _gsg, false); 00222 } 00223 00224 _hdc = GetDC(_hWnd); 00225 00226 create_frame_buffer(); 00227 if (_frame_buffer == NULL) { 00228 tinydisplay_cat.error() 00229 << "Could not create frame buffer.\n"; 00230 return false; 00231 } 00232 00233 tinygsg->_current_frame_buffer = _frame_buffer; 00234 00235 tinygsg->reset_if_new(); 00236 if (!tinygsg->is_valid()) { 00237 close_window(); 00238 return false; 00239 } 00240 00241 return true; 00242 } 00243 00244 //////////////////////////////////////////////////////////////////// 00245 // Function: WinGraphicsWindow::handle_reshape 00246 // Access: Protected, Virtual 00247 // Description: Called in the window thread when the window size or 00248 // location is changed, this updates the properties 00249 // structure accordingly. 00250 //////////////////////////////////////////////////////////////////// 00251 void TinyWinGraphicsWindow:: 00252 handle_reshape() { 00253 WinGraphicsWindow::handle_reshape(); 00254 ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size()); 00255 setup_bitmap_info(); 00256 } 00257 00258 //////////////////////////////////////////////////////////////////// 00259 // Function: WinGraphicsWindow::do_fullscreen_resize 00260 // Access: Protected, Virtual 00261 // Description: Called in the window thread when the window size or 00262 // location is changed, this updates the properties 00263 // structure accordingly. 00264 //////////////////////////////////////////////////////////////////// 00265 bool TinyWinGraphicsWindow:: 00266 do_fullscreen_resize(int x_size, int y_size) { 00267 bool result = WinGraphicsWindow::do_fullscreen_resize(x_size, y_size); 00268 ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size()); 00269 setup_bitmap_info(); 00270 return result; 00271 } 00272 00273 //////////////////////////////////////////////////////////////////// 00274 // Function: TinyWinGraphicsWindow::create_frame_buffer 00275 // Access: Private 00276 // Description: Creates a suitable frame buffer for the current 00277 // window size. 00278 //////////////////////////////////////////////////////////////////// 00279 void TinyWinGraphicsWindow:: 00280 create_frame_buffer() { 00281 if (_frame_buffer != NULL) { 00282 ZB_close(_frame_buffer); 00283 _frame_buffer = NULL; 00284 } 00285 00286 _frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), ZB_MODE_RGBA, 0, 0, 0, 0); 00287 setup_bitmap_info(); 00288 } 00289 00290 //////////////////////////////////////////////////////////////////// 00291 // Function: TinyWinGraphicsWindow::setup_bitmap_info 00292 // Access: Private 00293 // Description: Determines the BITMAPINFO stuff for blitting the 00294 // frame buffer to the window. 00295 //////////////////////////////////////////////////////////////////// 00296 void TinyWinGraphicsWindow:: 00297 setup_bitmap_info() { 00298 _bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 00299 _bitmap_info.bmiHeader.biWidth = _frame_buffer->xsize; 00300 _bitmap_info.bmiHeader.biHeight = -_frame_buffer->ysize; 00301 _bitmap_info.bmiHeader.biPlanes = 1; 00302 _bitmap_info.bmiHeader.biBitCount = 32; 00303 _bitmap_info.bmiHeader.biCompression = BI_RGB; 00304 _bitmap_info.bmiHeader.biSizeImage = _frame_buffer->linesize * _frame_buffer->ysize; 00305 _bitmap_info.bmiHeader.biXPelsPerMeter = 0; 00306 _bitmap_info.bmiHeader.biYPelsPerMeter = 0; 00307 _bitmap_info.bmiHeader.biClrUsed = 0; 00308 _bitmap_info.bmiHeader.biClrImportant = 0; 00309 } 00310 00311 #endif // WIN32