Panda3D
wglGraphicsBuffer.cxx
1 // Filename: wglGraphicsBuffer.cxx
2 // Created by: drose (08Feb04)
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 "wglGraphicsBuffer.h"
16 #include "wglGraphicsPipe.h"
17 #include "config_wgldisplay.h"
18 #include "glgsg.h"
19 #include "pStatTimer.h"
20 
21 #include <wingdi.h>
22 
23 TypeHandle wglGraphicsBuffer::_type_handle;
24 
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: wglGraphicsBuffer::Constructor
28 // Access: Public
29 // Description:
30 ////////////////////////////////////////////////////////////////////
31 wglGraphicsBuffer::
32 wglGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
33  const string &name,
34  const FrameBufferProperties &fb_prop,
35  const WindowProperties &win_prop,
36  int flags,
38  GraphicsOutput *host) :
39  GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
40 {
41  _pbuffer = (HPBUFFERARB)0;
42  _pbuffer_dc = (HDC)0;
43  release_pbuffer();
44 
45  // Since the pbuffer never gets flipped, we get screenshots from the
46  // same buffer we draw into.
47  _screenshot_buffer_type = _draw_buffer_type;
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: wglGraphicsBuffer::Destructor
52 // Access: Public, Virtual
53 // Description:
54 ////////////////////////////////////////////////////////////////////
55 wglGraphicsBuffer::
56 ~wglGraphicsBuffer() {
57 }
58 
59 ////////////////////////////////////////////////////////////////////
60 // Function: wglGraphicsBuffer::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 ////////////////////////////////////////////////////////////////////
69 begin_frame(FrameMode mode, Thread *current_thread) {
70 
71  begin_frame_spam(mode);
72  if (_gsg == (GraphicsStateGuardian *)NULL) {
73  return false;
74  }
75 
77  DCAST_INTO_R(wglgsg, _gsg, false);
78 
79  HGLRC context = wglgsg->get_context(_pbuffer_dc);
80  if (context == 0) {
81  return false;
82  }
83 
84  if (_pbuffer_bound) {
85  if (_fb_properties.is_single_buffered()) {
86  wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
87  } else {
88  wglgsg->_wglReleaseTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
89  }
90  }
91 
92  if (!rebuild_bitplanes()) {
93  wglGraphicsPipe::wgl_make_current(0, 0, &_make_current_pcollector);
94  return false;
95  }
96 
97  wglGraphicsPipe::wgl_make_current(_pbuffer_dc, context,
98  &_make_current_pcollector);
99 
100  if (mode == FM_render) {
101  CDLockedReader cdata(_cycler);
102  for (size_t i = 0; i != cdata->_textures.size(); ++i) {
103  const RenderTexture &rt = cdata->_textures[i];
104  RenderTextureMode rtm_mode = rt._rtm_mode;
105  RenderTexturePlane plane = rt._plane;
106  if (rtm_mode == RTM_bind_or_copy && plane != RTP_color) {
107  CDWriter cdataw(_cycler, cdata, false);
108  nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
109  cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
110  }
111  }
112  clear_cube_map_selection();
113  }
114 
115  _gsg->set_current_properties(&get_fb_properties());
116  return _gsg->begin_frame(current_thread);
117 }
118 
119 ////////////////////////////////////////////////////////////////////
120 // Function: wglGraphicsBuffer::end_frame
121 // Access: Public, Virtual
122 // Description: This function will be called within the draw thread
123 // after rendering is completed for a given frame. It
124 // should do whatever finalization is required.
125 ////////////////////////////////////////////////////////////////////
127 end_frame(FrameMode mode, Thread *current_thread) {
128  end_frame_spam(mode);
129  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
130 
131  if (mode == FM_render) {
132  copy_to_textures();
133  bind_texture_to_pbuffer();
134  }
135 
136  _gsg->end_frame(current_thread);
137 
138  if (mode == FM_render) {
139  trigger_flip();
140  clear_cube_map_selection();
141  }
142 }
143 
144 ////////////////////////////////////////////////////////////////////
145 // Function: GraphicsOutput::bind_texture_to_pbuffer
146 // Access: Private
147 // Description: Looks for the appropriate texture,
148 // and binds that texture to the pbuffer.
149 ////////////////////////////////////////////////////////////////////
150 void wglGraphicsBuffer::
151 bind_texture_to_pbuffer() {
152  wglGraphicsStateGuardian *wglgsg;
153  DCAST_INTO_V(wglgsg, _gsg);
154 
155  // Find the color texture, if there is one. That one can be bound to
156  // the framebuffer. All others must be marked RTM_copy_to_texture.
157 
158  int tex_index = -1;
159  CDLockedReader cdata(_cycler);
160  for (size_t i = 0; i != cdata->_textures.size(); ++i) {
161  const RenderTexture &rt = cdata->_textures[i];
162  RenderTexturePlane plane = rt._plane;
163  if (plane == RTP_color && rt._rtm_mode == RTM_bind_or_copy) {
164  tex_index = i;
165  break;
166  }
167  }
168 
169  if (tex_index >= 0) {
170  const RenderTexture &rt = cdata->_textures[tex_index];
171  Texture *tex = rt._texture;
172  if ((_pbuffer_bound != 0)&&(_pbuffer_bound != tex)) {
173  _pbuffer_bound->release(wglgsg->get_prepared_objects());
174  _pbuffer_bound = 0;
175  }
177 
178  if (tex->get_match_framebuffer_format()) {
179  if (_fb_properties.get_alpha_bits()) {
180  tex->set_format(Texture::F_rgba);
181  } else {
182  tex->set_format(Texture::F_rgb);
183  }
184  }
185  TextureContext *tc = tex->prepare_now(0, _gsg->get_prepared_objects(), _gsg);
186  nassertv(tc != (TextureContext *)NULL);
187  CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
188  GLenum target = wglgsg->get_texture_target(tex->get_texture_type());
189  if (target == GL_NONE) {
190  CDWriter cdataw(_cycler, cdata, false);
191  nassertv(cdata->_textures.size() == cdataw->_textures.size());
192  cdataw->_textures[tex_index]._rtm_mode = RTM_copy_texture;
193  return;
194  }
195  GLP(BindTexture)(target, gtc->_index);
196  if (_fb_properties.is_single_buffered()) {
197  wglgsg->_wglBindTexImageARB(_pbuffer, WGL_FRONT_LEFT_ARB);
198  } else {
199  wglgsg->_wglBindTexImageARB(_pbuffer, WGL_BACK_LEFT_ARB);
200  }
201  _pbuffer_bound = tex;
202  } else {
203  if (_pbuffer_bound != 0) {
204  _pbuffer_bound->release(wglgsg->get_prepared_objects());
205  _pbuffer_bound = 0;
206  }
207  }
208 }
209 
210 ////////////////////////////////////////////////////////////////////
211 // Function: wglGraphicsBuffer::select_target_tex_page
212 // Access: Public, Virtual
213 // Description: Called internally when the window is in
214 // render-to-a-texture mode and we are in the process of
215 // rendering the six faces of a cube map. This should
216 // do whatever needs to be done to switch the buffer to
217 // the indicated face.
218 ////////////////////////////////////////////////////////////////////
221  wglGraphicsStateGuardian *wglgsg;
222  DCAST_INTO_V(wglgsg, _gsg);
223 
224  nassertv(wglgsg->_wglSetPbufferAttribARB != NULL);
225 
226  static const int max_attrib_list = 64;
227  int iattrib_list[max_attrib_list];
228  int ni = 0;
229 
230  iattrib_list[ni++] = WGL_CUBE_MAP_FACE_ARB;
231  iattrib_list[ni++] = WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + page;
232 
233  // Terminate the list.
234  nassertv(ni <= max_attrib_list);
235  iattrib_list[ni] = 0;
236 
237  wglgsg->_wglSetPbufferAttribARB(_pbuffer, iattrib_list);
238 }
239 
240 ////////////////////////////////////////////////////////////////////
241 // Function: wglGraphicsBuffer::process_events
242 // Access: Public, Virtual
243 // Description: Do whatever processing is necessary to ensure that
244 // the window responds to user events. Also, honor any
245 // requests recently made via request_properties()
246 //
247 // This function is called only within the window
248 // thread.
249 ////////////////////////////////////////////////////////////////////
253 
254  MSG msg;
255 
256  // Handle all the messages on the queue in a row. Some of these
257  // might be for another window, but they will get dispatched
258  // appropriately.
259  while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
260  process_1_event();
261  }
262 }
263 
264 ////////////////////////////////////////////////////////////////////
265 // Function: wglGraphicsBuffer::get_supports_render_texture
266 // Access: Published, Virtual
267 // Description: Returns true if this particular GraphicsOutput can
268 // render directly into a texture, or false if it must
269 // always copy-to-texture at the end of each frame to
270 // achieve this effect.
271 ////////////////////////////////////////////////////////////////////
274  if (_gsg == (GraphicsStateGuardian *)NULL) {
275  return false;
276  }
277 
278  wglGraphicsStateGuardian *wglgsg;
279  DCAST_INTO_R(wglgsg, _gsg, false);
280  return wglgsg->get_supports_wgl_render_texture();
281 }
282 
283 ////////////////////////////////////////////////////////////////////
284 // Function: wglGraphicsBuffer::close_buffer
285 // Access: Protected, Virtual
286 // Description: Closes the buffer right now. Called from the window
287 // thread.
288 ////////////////////////////////////////////////////////////////////
289 void wglGraphicsBuffer::
290 close_buffer() {
291  if (_gsg != (GraphicsStateGuardian *)NULL) {
292  wglGraphicsStateGuardian *wglgsg;
293  DCAST_INTO_V(wglgsg, _gsg);
294 
295  _gsg.clear();
296  }
297 
298  release_pbuffer();
299 
300  _is_valid = false;
301 }
302 
303 ////////////////////////////////////////////////////////////////////
304 // Function: wglGraphicsBuffer::open_buffer
305 // Access: Protected, Virtual
306 // Description: Opens the window right now. Called from the window
307 // thread. Returns true if the window is successfully
308 // opened, or false if there was a problem.
309 ////////////////////////////////////////////////////////////////////
310 bool wglGraphicsBuffer::
311 open_buffer() {
312 
313  // pbuffers don't seem to work correctly in double-buffered
314  // mode. Besides, the back buffer is a pointless waste of space.
315  // So always use a single-buffered gsg.
316 
317  _fb_properties.set_back_buffers(0);
318  _draw_buffer_type = RenderBuffer::T_front;
319  _screenshot_buffer_type = RenderBuffer::T_front;
320 
321  // GSG creation/initialization.
322 
323  wglGraphicsStateGuardian *wglgsg;
324  if (_gsg == 0) {
325  // There is no old gsg. Create a new one.
326  wglgsg = new wglGraphicsStateGuardian(_engine, _pipe, NULL);
327  wglgsg->choose_pixel_format(_fb_properties, true);
328  _gsg = wglgsg;
329  } else {
330  // If the old gsg has the wrong pixel format, create a
331  // new one that shares with the old gsg.
332  DCAST_INTO_R(wglgsg, _gsg, false);
333  if ((!wglgsg->get_fb_properties().subsumes(_fb_properties))||
334  (!wglgsg->get_fb_properties().is_single_buffered())||
335  (!wglgsg->pfnum_supports_pbuffer())) {
336  wglgsg = new wglGraphicsStateGuardian(_engine, _pipe, wglgsg);
337  wglgsg->choose_pixel_format(_fb_properties, true);
338  _gsg = wglgsg;
339  }
340  }
341 
342  // Use the temp window to initialize the gsg.
343 
344  HDC twindow_dc = wglgsg->get_twindow_dc();
345  if (twindow_dc == 0) {
346  // If we couldn't make a window, we can't get a GL context.
347  _gsg = NULL;
348  return false;
349  }
350  HGLRC context = wglgsg->get_context(twindow_dc);
351  if (context == 0) {
352  _gsg = NULL;
353  return false;
354  }
355  wglGraphicsPipe::wgl_make_current(twindow_dc, context,
356  &_make_current_pcollector);
357  wglgsg->reset_if_new();
358  wglgsg->report_my_gl_errors();
360  (_fb_properties,wglgsg->get_gl_renderer())) {
361  _gsg = NULL;
362  return false;
363  }
364  _fb_properties = wglgsg->get_fb_properties();
365 
366  // Now that we have fully made a window and used that window to
367  // create a rendering context, we can attempt to create a pbuffer.
368  // This might fail if the pbuffer extensions are not supported.
369 
370  if (!rebuild_bitplanes()) {
371  wglGraphicsPipe::wgl_make_current(0, 0, &_make_current_pcollector);
372  _gsg = NULL;
373  return false;
374  }
375 
376  _is_valid = true;
377 
378  return true;
379 }
380 
381 ////////////////////////////////////////////////////////////////////
382 // Function: wglGraphicsBuffer::release_pbuffer
383 // Access: Private
384 // Description: Destroys the pbuffer if it has been created. The
385 // intent is that this may allow it to be recreated
386 // with different options.
387 ////////////////////////////////////////////////////////////////////
388 void wglGraphicsBuffer::
389 release_pbuffer() {
390  if (_gsg == 0) {
391  return;
392  }
393 
394  wglGraphicsStateGuardian *wglgsg;
395  DCAST_INTO_V(wglgsg, _gsg);
396 
397  if (_pbuffer_bound != 0) {
398  _pbuffer_bound->release(wglgsg->get_prepared_objects());
399  _pbuffer_bound = 0;
400  }
401  wglGraphicsPipe::wgl_make_current(0, 0, NULL);
402  if (_pbuffer_dc) {
403  wglgsg->_wglReleasePbufferDCARB(_pbuffer, _pbuffer_dc);
404  }
405  if (_pbuffer) {
406  wglgsg->_wglDestroyPbufferARB(_pbuffer);
407  }
408  _pbuffer = (HPBUFFERARB)0;
409  _pbuffer_dc = (HDC)0;
410  _pbuffer_mipmap = false;
411  _pbuffer_sizex = 0;
412  _pbuffer_sizey = 0;
413  _pbuffer_type = Texture::TT_2d_texture;
414 }
415 
416 ////////////////////////////////////////////////////////////////////
417 // Function: wglGraphicsBuffer::rebuild_bitplanes
418 // Access: Private
419 // Description: Once the GL context has been fully realized, attempts
420 // to create an offscreen pbuffer if the graphics API
421 // supports it. Returns true if successful, false on
422 // failure.
423 ////////////////////////////////////////////////////////////////////
424 bool wglGraphicsBuffer::
425 rebuild_bitplanes() {
426  wglGraphicsStateGuardian *wglgsg;
427  DCAST_INTO_R(wglgsg, _gsg, false);
428 
429  if (!wglgsg->_supports_pbuffer) {
430  wgldisplay_cat.info()
431  << "PBuffers not supported by GL implementation.\n";
432  return false;
433  }
434 
435  // Find the texture to bind to the color buffer.
436  Texture *bindtexture = NULL;
437  for (int i=0; i<count_textures(); i++) {
438  if ((get_rtm_mode(i) == RTM_bind_or_copy)&&
439  (get_texture(i)->get_format() != Texture::F_depth_stencil)) {
440  bindtexture = get_texture(i);
441  break;
442  }
443  }
444 
445  // If we already have a pbuffer, and if it's lost, then
446  // force the rebuild.
447 
448  if (_pbuffer_dc) {
449  int flag = 0;
450  wglgsg->_wglQueryPbufferARB(_pbuffer, WGL_PBUFFER_LOST_ARB, &flag);
451  if (flag != 0) {
452  release_pbuffer();
453  }
454  }
455 
456  // Determine what pbuffer attributes are needed
457  // for currently-applicable textures.
458 
459  if ((_host != 0)&&(_creation_flags & GraphicsPipe::BF_size_track_host)) {
460  if (_host->get_size() != _size) {
461  set_size_and_recalc(_host->get_x_size(),
462  _host->get_y_size());
463  }
464  }
465  int desired_x = get_x_size();
466  int desired_y = get_y_size();
467  if ((bindtexture != 0)&&(Texture::get_textures_power_2() != ATS_none)) {
468  desired_x = Texture::up_to_power_2(desired_x);
469  desired_y = Texture::up_to_power_2(desired_y);
470  }
471  bool desired_mipmap = false;
472  Texture::TextureType desired_type = Texture::TT_2d_texture;
473  if (bindtexture != 0) {
474  desired_mipmap = bindtexture->uses_mipmaps();
475  desired_type = bindtexture->get_texture_type();
476  }
477 
478  if ((_pbuffer != 0)&&
479  (_pbuffer_sizex == desired_x)&&
480  (_pbuffer_sizey == desired_y)&&
481  (_pbuffer_mipmap == desired_mipmap)&&
482  (_pbuffer_type == desired_type)) {
483  // the pbuffer we already have is fine. Do not rebuild.
484  return true;
485  }
486 
487  // Release the old pbuffer, if there was one.
488 
489  release_pbuffer();
490 
491  // Allocate the new pbuffer.
492 
493  int pfnum = wglgsg->get_pfnum();
494 
495  static const int max_attrib_list = 64;
496  int iattrib_list[max_attrib_list];
497  int ni = 0;
498 
499  if (_fb_properties.get_alpha_bits()) {
500  iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
501  iattrib_list[ni++] = WGL_TEXTURE_RGBA_ARB;
502  } else {
503  iattrib_list[ni++] = WGL_TEXTURE_FORMAT_ARB;
504  iattrib_list[ni++] = WGL_TEXTURE_RGB_ARB;
505  }
506 
507  if (desired_mipmap) {
508  iattrib_list[ni++] = WGL_MIPMAP_TEXTURE_ARB;
509  iattrib_list[ni++] = 1;
510  }
511 
512  switch (desired_type) {
513  case Texture::TT_cube_map:
514  iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
515  iattrib_list[ni++] = WGL_TEXTURE_CUBE_MAP_ARB;
516  break;
517 
518  case Texture::TT_1d_texture:
519  iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
520  iattrib_list[ni++] = WGL_TEXTURE_1D_ARB;
521  break;
522 
523  default:
524  iattrib_list[ni++] = WGL_TEXTURE_TARGET_ARB;
525  iattrib_list[ni++] = WGL_TEXTURE_2D_ARB;
526  }
527 
528  // Terminate the list.
529  nassertr(ni <= max_attrib_list, false);
530  iattrib_list[ni] = 0;
531 
532  HDC twindow_dc = wglgsg->get_twindow_dc();
533  if (twindow_dc == 0) {
534  return false;
535  }
536 
537  HGLRC context = wglgsg->get_context(twindow_dc);
538  if (context == 0) {
539  return false;
540  }
541  wglGraphicsPipe::wgl_make_current(twindow_dc, context,
542  &_make_current_pcollector);
543 
544  _pbuffer = wglgsg->_wglCreatePbufferARB(twindow_dc, pfnum,
545  desired_x, desired_y, iattrib_list);
546 
547  if (_pbuffer == 0) {
548  wgldisplay_cat.info()
549  << "Attempt to create pbuffer failed.\n";
550  return false;
551  }
552 
553  _pbuffer_dc = wglgsg->_wglGetPbufferDCARB(_pbuffer);
554  _pbuffer_mipmap = desired_mipmap;
555  _pbuffer_type = desired_type;
556  _pbuffer_sizex = desired_x;
557  _pbuffer_sizey = desired_y;
558 
559  return true;
560 }
561 
562 ////////////////////////////////////////////////////////////////////
563 // Function: wglGraphicsBuffer::process_1_event
564 // Access: Private, Static
565 // Description: Handles one event from the message queue.
566 ////////////////////////////////////////////////////////////////////
567 void wglGraphicsBuffer::
568 process_1_event() {
569  MSG msg;
570 
571  if (!GetMessage(&msg, NULL, 0, 0)) {
572  // WM_QUIT received. We need a cleaner way to deal with this.
573  // DestroyAllWindows(false);
574  exit(msg.wParam); // this will invoke AtExitFn
575  }
576 
577  // Translate virtual key messages
578  TranslateMessage(&msg);
579  // Call window_proc
580  DispatchMessage(&msg);
581 }
582 
583 
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame...
Format get_format() const
Returns the format of the texture, which represents both the semantic meaning of the texels and...
Definition: texture.I:872
HDC get_twindow_dc()
Returns the DC associated with the temporary, invisible window that was created with the gsg to query...
int get_pfnum() const
Returns the pixel format number chosen for windows that use this context.
void set_size_and_recalc(int x, int y)
Changes the x_size and y_size, then recalculates structures that depend on size.
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame...
virtual Texture * get_texture(int i=0) const
Returns the nth texture into which the GraphicsOutput renders.
TextureType get_texture_type() const
Returns the overall interpretation of the texture.
Definition: texture.I:859
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:75
int get_y_size() const
Returns the visible height of the window or buffer, if it is known.
void set_format(Format format)
Changes the format value for the texture components.
Definition: texture.I:2440
This is a special class object that holds all the information returned by a particular GSG to indicat...
A tiny specialization on GLGraphicsStateGuardian to add some wgl-specific information.
bool get_match_framebuffer_format() const
Returns true if the special flag was set that indicates to the GSG that the Texture&#39;s format should b...
Definition: texture.I:2522
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the texture context only on the indicated object, if it exists there.
Definition: texture.cxx:1445
virtual void process_events()
Honor any requests recently made via request_open() or request_close().
void set_size_padded(int x=1, int y=1, int z=1)
Changes the size of the texture, padding if necessary, and setting the pad region as well...
Definition: texture.cxx:1759
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general...
Definition: texture.I:2232
A container for the various kinds of properties we might ask to have on a graphics window before we o...
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping, false otherwise.
Definition: texture.I:1319
bool get_supports_wgl_render_texture() const
Returns true if this particular GSG can render from a wglGraphicsBuffer directly into a texture...
An offscreen buffer for rendering into.
HGLRC get_context(HDC hdc)
Returns the GL context associated with the GSG.
void choose_pixel_format(const FrameBufferProperties &properties, bool need_pbuffer)
Selects a pixel format for all the windows and buffers that use this gsg.
virtual void process_events()
Do whatever processing is necessary to ensure that the window responds to user events.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:58
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
bool verify_hardware_software(const FrameBufferProperties &props, const string &renderer) const
Validates that the properties represent the desired kind of renderer (hardware or software)...
int count_textures() const
If the GraphicsOutput is set to render into a texture, returns the number of textures that are being ...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
This is a base class for the various different classes that represent the result of a frame of render...
int get_x_size() const
Returns the visible width of the window or buffer, if it is known.
TextureContext * prepare_now(int view, PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the texture on the particular GSG, if it does not already exist.
Definition: texture.cxx:1815
const FrameBufferProperties & get_fb_properties() const
Returns the properties of the pixel format that was chosen for this gsg.
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
Definition: texture.cxx:1845
A thread; that is, a lightweight process.
Definition: thread.h:51
RenderTextureMode get_rtm_mode(int i=0) const
Returns the RenderTextureMode associated with the nth render-texture.
bool pfnum_supports_pbuffer() const
Returns true if the gsg&#39;s pixel format is capable of supporting a pbuffer.
Encapsulates all the communication with a particular instance of a given rendering backend...
virtual void select_target_tex_page(int page)
Called internally when the window is in render-to-a-texture mode and we are in the process of renderi...
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
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...
virtual bool get_supports_render_texture() const
Returns true if this particular GraphicsOutput can render directly into a texture, or false if it must always copy-to-texture at the end of each frame to achieve this effect.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.