Panda3D
tinyWinGraphicsWindow.cxx
1 // Filename: tinyWinGraphicsWindow.cxx
2 // Created by: drose (06May08)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "pandabase.h"
16 
17 #ifdef WIN32
18 
19 #include "tinyWinGraphicsWindow.h"
20 #include "config_tinydisplay.h"
21 #include "config_windisplay.h"
22 #include "tinyWinGraphicsPipe.h"
23 #include "tinyGraphicsStateGuardian.h"
24 #include "pStatTimer.h"
25 
26 #include <wingdi.h>
27 
28 TypeHandle TinyWinGraphicsWindow::_type_handle;
29 
30 ////////////////////////////////////////////////////////////////////
31 // Function: TinyWinGraphicsWindow::Constructor
32 // Access: Public
33 // Description:
34 ////////////////////////////////////////////////////////////////////
35 TinyWinGraphicsWindow::
36 TinyWinGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
37  const string &name,
38  const FrameBufferProperties &fb_prop,
39  const WindowProperties &win_prop,
40  int flags,
42  GraphicsOutput *host) :
43  WinGraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
44 {
45  _frame_buffer = NULL;
46  _hdc = (HDC)0;
47  update_pixel_factor();
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: TinyWinGraphicsWindow::Destructor
52 // Access: Public, Virtual
53 // Description:
54 ////////////////////////////////////////////////////////////////////
55 TinyWinGraphicsWindow::
56 ~TinyWinGraphicsWindow() {
57 }
58 
59 ////////////////////////////////////////////////////////////////////
60 // Function: TinyWinGraphicsWindow::begin_frame
61 // Access: Public, Virtual
62 // Description: This function will be called within the draw thread
63 // before beginning rendering for a given frame. It
64 // should do whatever setup is required, and return true
65 // if the frame should be rendered, or false if it
66 // should be skipped.
67 ////////////////////////////////////////////////////////////////////
68 bool TinyWinGraphicsWindow::
69 begin_frame(FrameMode mode, Thread *current_thread) {
70  begin_frame_spam(mode);
71  if (_gsg == (GraphicsStateGuardian *)NULL) {
72  return false;
73  }
74 
75  if (!get_unexposed_draw() && !_got_expose_event) {
76  if (tinydisplay_cat.is_spam()) {
77  tinydisplay_cat.spam()
78  << "Not drawing " << this << ": unexposed.\n";
79  }
80  return false;
81  }
82 
84  DCAST_INTO_R(tinygsg, _gsg, false);
85 
86  tinygsg->_current_frame_buffer = _frame_buffer;
87  tinygsg->reset_if_new();
88 
89  _gsg->set_current_properties(&get_fb_properties());
90  return _gsg->begin_frame(current_thread);
91 }
92 
93 ////////////////////////////////////////////////////////////////////
94 // Function: TinyWinGraphicsWindow::end_frame
95 // Access: Public, Virtual
96 // Description: This function will be called within the draw thread
97 // after rendering is completed for a given frame. It
98 // should do whatever finalization is required.
99 ////////////////////////////////////////////////////////////////////
100 void TinyWinGraphicsWindow::
101 end_frame(FrameMode mode, Thread *current_thread) {
102  end_frame_spam(mode);
103  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
104 
105  if (mode == FM_render) {
106  // end_render_texture();
107  copy_to_textures();
108  }
109 
110  _gsg->end_frame(current_thread);
111 
112  if (mode == FM_render) {
113  trigger_flip();
114  clear_cube_map_selection();
115  }
116 }
117 
118 ////////////////////////////////////////////////////////////////////
119 // Function: TinyWinGraphicsWindow::end_flip
120 // Access: Public, Virtual
121 // Description: This function will be called within the draw thread
122 // after begin_flip() has been called on all windows, to
123 // finish the exchange of the front and back buffers.
124 //
125 // This should cause the window to wait for the flip, if
126 // necessary.
127 ////////////////////////////////////////////////////////////////////
128 void TinyWinGraphicsWindow::
129 end_flip() {
130  if (!_flip_ready) {
132  return;
133  }
134 
135  HBITMAP bm = CreateCompatibleBitmap(_hdc, _frame_buffer->xsize, _frame_buffer->ysize);
136  HDC bmdc = CreateCompatibleDC(_hdc);
137  SelectObject(bmdc, bm);
138 
139  int fb_xsize = get_fb_x_size();
140  int fb_ysize = get_fb_y_size();
141  int fb_ytop = _frame_buffer->ysize - fb_ysize;
142 
143  SetDIBits(_hdc, bm, fb_ytop, fb_ysize, _frame_buffer->pbuf,
144  &_bitmap_info, DIB_RGB_COLORS);
145 
146  if (fb_xsize == _frame_buffer->xsize) {
147  BitBlt(_hdc, 0, 0, fb_xsize, fb_ysize,
148  bmdc, 0, 0, SRCCOPY);
149  } else {
150  // SetStretchBltMode(_hdc, HALFTONE);
151  StretchBlt(_hdc, 0, 0, _frame_buffer->xsize, _frame_buffer->ysize,
152  bmdc, 0, 0,fb_xsize, fb_ysize,
153  SRCCOPY);
154  }
155 
156  DeleteDC(bmdc);
157  DeleteObject(bm);
158  GdiFlush();
160 }
161 
162 ////////////////////////////////////////////////////////////////////
163 // Function: TinyWinGraphicsWindow::supports_pixel_zoom
164 // Access: Published, Virtual
165 // Description: Returns true if a call to set_pixel_zoom() will be
166 // respected, false if it will be ignored. If this
167 // returns false, then get_pixel_factor() will always
168 // return 1.0, regardless of what value you specify for
169 // set_pixel_zoom().
170 //
171 // This may return false if the underlying renderer
172 // doesn't support pixel zooming, or if you have called
173 // this on a DisplayRegion that doesn't have both
174 // set_clear_color() and set_clear_depth() enabled.
175 ////////////////////////////////////////////////////////////////////
176 bool TinyWinGraphicsWindow::
177 supports_pixel_zoom() const {
178  return true;
179 }
180 
181 ////////////////////////////////////////////////////////////////////
182 // Function: TinyWinGraphicsWindow::close_window
183 // Access: Protected, Virtual
184 // Description: Closes the window right now. Called from the window
185 // thread.
186 ////////////////////////////////////////////////////////////////////
187 void TinyWinGraphicsWindow::
188 close_window() {
189  if (_gsg != (GraphicsStateGuardian *)NULL) {
190  TinyGraphicsStateGuardian *tinygsg;
191  DCAST_INTO_V(tinygsg, _gsg);
192  tinygsg->_current_frame_buffer = NULL;
193  _gsg.clear();
194  }
195 
196  ReleaseDC(_hWnd, _hdc);
197  _hdc = (HDC)0;
198  WinGraphicsWindow::close_window();
199 }
200 
201 ////////////////////////////////////////////////////////////////////
202 // Function: TinyWinGraphicsWindow::open_window
203 // Access: Protected, Virtual
204 // Description: Opens the window right now. Called from the window
205 // thread. Returns true if the window is successfully
206 // opened, or false if there was a problem.
207 ////////////////////////////////////////////////////////////////////
208 bool TinyWinGraphicsWindow::
209 open_window() {
210  if (!WinGraphicsWindow::open_window()) {
211  return false;
212  }
213 
214  // GSG Creation/Initialization
215  TinyGraphicsStateGuardian *tinygsg;
216  if (_gsg == 0) {
217  // There is no old gsg. Create a new one.
218  tinygsg = new TinyGraphicsStateGuardian(_engine, _pipe, NULL);
219  _gsg = tinygsg;
220  } else {
221  DCAST_INTO_R(tinygsg, _gsg, false);
222  }
223 
224  _hdc = GetDC(_hWnd);
225 
226  create_frame_buffer();
227  if (_frame_buffer == NULL) {
228  tinydisplay_cat.error()
229  << "Could not create frame buffer.\n";
230  return false;
231  }
232 
233  tinygsg->_current_frame_buffer = _frame_buffer;
234 
235  tinygsg->reset_if_new();
236  if (!tinygsg->is_valid()) {
237  close_window();
238  return false;
239  }
240 
241  return true;
242 }
243 
244 ////////////////////////////////////////////////////////////////////
245 // Function: WinGraphicsWindow::handle_reshape
246 // Access: Protected, Virtual
247 // Description: Called in the window thread when the window size or
248 // location is changed, this updates the properties
249 // structure accordingly.
250 ////////////////////////////////////////////////////////////////////
251 void TinyWinGraphicsWindow::
252 handle_reshape() {
253  WinGraphicsWindow::handle_reshape();
254  if (_frame_buffer != NULL) {
255  ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
256  setup_bitmap_info();
257  }
258 }
259 
260 ////////////////////////////////////////////////////////////////////
261 // Function: WinGraphicsWindow::do_fullscreen_resize
262 // Access: Protected, Virtual
263 // Description: Called in the window thread when the window size or
264 // location is changed, this updates the properties
265 // structure accordingly.
266 ////////////////////////////////////////////////////////////////////
267 bool TinyWinGraphicsWindow::
268 do_fullscreen_resize(int x_size, int y_size) {
269  bool result = WinGraphicsWindow::do_fullscreen_resize(x_size, y_size);
270  ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
271  setup_bitmap_info();
272  return result;
273 }
274 
275 ////////////////////////////////////////////////////////////////////
276 // Function: TinyWinGraphicsWindow::create_frame_buffer
277 // Access: Private
278 // Description: Creates a suitable frame buffer for the current
279 // window size.
280 ////////////////////////////////////////////////////////////////////
281 void TinyWinGraphicsWindow::
282 create_frame_buffer() {
283  if (_frame_buffer != NULL) {
284  ZB_close(_frame_buffer);
285  _frame_buffer = NULL;
286  }
287 
288  _frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), ZB_MODE_RGBA, 0, 0, 0, 0);
289  setup_bitmap_info();
290 }
291 
292 ////////////////////////////////////////////////////////////////////
293 // Function: TinyWinGraphicsWindow::setup_bitmap_info
294 // Access: Private
295 // Description: Determines the BITMAPINFO stuff for blitting the
296 // frame buffer to the window.
297 ////////////////////////////////////////////////////////////////////
298 void TinyWinGraphicsWindow::
299 setup_bitmap_info() {
300  _bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
301  _bitmap_info.bmiHeader.biWidth = _frame_buffer->xsize;
302  _bitmap_info.bmiHeader.biHeight = -_frame_buffer->ysize;
303  _bitmap_info.bmiHeader.biPlanes = 1;
304  _bitmap_info.bmiHeader.biBitCount = 32;
305  _bitmap_info.bmiHeader.biCompression = BI_RGB;
306  _bitmap_info.bmiHeader.biSizeImage = _frame_buffer->linesize * _frame_buffer->ysize;
307  _bitmap_info.bmiHeader.biXPelsPerMeter = 0;
308  _bitmap_info.bmiHeader.biYPelsPerMeter = 0;
309  _bitmap_info.bmiHeader.biClrUsed = 0;
310  _bitmap_info.bmiHeader.biClrImportant = 0;
311 }
312 
313 #endif // WIN32
virtual void clear(DrawableRegion *clearable)
Clears the framebuffer within the current DisplayRegion, according to the flags indicated by the give...
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
bool reset_if_new()
Calls reset() to initialize the GSG, but only if it hasn&#39;t been called yet.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
An abstract base class for glGraphicsWindow and dxGraphicsWindow (and, in general, graphics windows that interface with the Microsoft Windows API).
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:58
This is a base class for the various different classes that represent the result of a frame of render...
A thread; that is, a lightweight process.
Definition: thread.h:51
Encapsulates all the communication with a particular instance of a given rendering backend...
bool is_valid() const
Returns true if the GSG has been correctly initialized within a graphics context, false if there has ...
This class is the main interface to controlling the render process.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
An interface to the TinyPanda software rendering code within this module.