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 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