Panda3D
osxGraphicsBuffer.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file osxGraphicsBuffer.cxx
10  */
11 
12 #include "osxGraphicsBuffer.h"
14 #include "config_osxdisplay.h"
15 #include "osxGraphicsPipe.h"
16 
17 #include "graphicsPipe.h"
18 #include "glgsg.h"
19 #include "pStatTimer.h"
20 
21 TypeHandle osxGraphicsBuffer::_type_handle;
22 
23 /**
24  *
25  */
26 osxGraphicsBuffer::
27 osxGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
28  const std::string &name,
29  const FrameBufferProperties &fb_prop,
30  const WindowProperties &win_prop,
31  int flags,
33  GraphicsOutput *host) :
34  GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
35 {
36  osxGraphicsPipe *osx_pipe;
37  DCAST_INTO_V(osx_pipe, _pipe);
38 
39  _pbuffer = nullptr;
40 
41  // Since the pbuffer never gets flipped, we get screenshots from the same
42  // buffer we draw into.
43  _screenshot_buffer_type = _draw_buffer_type;
44 }
45 
46 /**
47  *
48  */
49 osxGraphicsBuffer::
50 ~osxGraphicsBuffer() {
51  nassertv(_pbuffer == nullptr);
52 }
53 
54 /**
55  * This function will be called within the draw thread before beginning
56  * rendering for a given frame. It should do whatever setup is required, and
57  * return true if the frame should be rendered, or false if it should be
58  * skipped.
59  */
61 begin_frame(FrameMode mode, Thread *current_thread) {
62  PStatTimer timer(_make_current_pcollector);
63 
64  begin_frame_spam(mode);
65  if (_gsg == nullptr) {
66  return false;
67  }
68  nassertr(_pbuffer != nullptr, false);
69 
71  DCAST_INTO_R(osxgsg, _gsg, false);
72  if (!aglSetPBuffer(osxgsg->get_context(), _pbuffer, 0, 0, 0)) {
73  report_agl_error("aglSetPBuffer");
74  return false;
75  }
76 
77  if (!aglSetCurrentContext(osxgsg->get_context())) {
78  report_agl_error("aglSetCurrentContext");
79  return false;
80  }
81 
82  osxgsg->reset_if_new();
83 
84  if (mode == FM_render) {
85  CDLockedReader cdata(_cycler);
86  for (size_t i = 0; i != cdata->_textures.size(); ++i) {
87  const RenderTexture &rt = cdata->_textures[i];
88  RenderTextureMode rtm_mode = rt._rtm_mode;
89  if (rtm_mode == RTM_bind_or_copy) {
90  CDWriter cdataw(_cycler, cdata, false);
91  nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
92  cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
93  }
94  }
95  clear_cube_map_selection();
96  }
97  _gsg->set_current_properties(&get_fb_properties());
98  return _gsg->begin_frame(current_thread);
99 }
100 
101 /**
102  * This function will be called within the draw thread after rendering is
103  * completed for a given frame. It should do whatever finalization is
104  * required.
105  */
107 end_frame(FrameMode mode, Thread *current_thread) {
108  end_frame_spam(mode);
109  nassertv(_gsg != nullptr);
110 
111  if (mode == FM_render) {
112  copy_to_textures();
113  }
114 
115  _gsg->end_frame(current_thread);
116 
117  if (mode == FM_render) {
118  trigger_flip();
119  clear_cube_map_selection();
120  }
121 }
122 
123 /**
124  * Closes the buffer right now. Called from the window thread.
125  */
126 void osxGraphicsBuffer::
127 close_buffer() {
128  if (_gsg != nullptr) {
129  // aglSetPBuffer(osxgsg->get_context(), _pbuffer, 0, 0, 0);
130  _gsg.clear();
131  }
132  if (_pbuffer != nullptr) {
133  aglDestroyPBuffer(_pbuffer);
134  _pbuffer = nullptr;
135  }
136  _is_valid = false;
137 }
138 
139 /**
140  * Opens the buffer right now. Called from the window thread. Returns true
141  * if the buffer is successfully opened, or false if there was a problem.
142  */
143 bool osxGraphicsBuffer::
144 open_buffer() {
145  if (_gsg == 0) {
146  _gsg = new osxGraphicsStateGuardian(_engine, _pipe, nullptr);
147  }
148 
149  if (_pbuffer == nullptr) {
150  GLenum target = GL_TEXTURE_RECTANGLE_ARB;
151  if (_size[0] == Texture::up_to_power_2(_size[0]) &&
152  _size[1] == Texture::up_to_power_2(_size[1])) {
153  // It's a power-of-two size, so we can use GL_TEXTURE_2D as the target.
154  // Dunno, but maybe this will be more likely to work on some hardware.
155  target = GL_TEXTURE_2D;
156  }
157  if (!aglCreatePBuffer(_size.get_x(), _size.get_y(), target, GL_RGBA, 0, &_pbuffer)) {
158  report_agl_error("aglCreatePBuffer");
159  close_buffer();
160  return false;
161  }
162  }
163 
164  osxGraphicsStateGuardian *osxgsg;
165  DCAST_INTO_R(osxgsg, _gsg, false);
166 
167  OSStatus stat = osxgsg->build_gl(false, true, _fb_properties);
168  if (stat != noErr) {
169  return false;
170  }
171 
172  if (!aglSetPBuffer(osxgsg->get_context(), _pbuffer, 0, 0, 0)) {
173  report_agl_error("aglSetPBuffer");
174  close_buffer();
175  return false;
176  }
177 
178  if (!aglSetCurrentContext(osxgsg->get_context())) {
179  report_agl_error("aglSetCurrentContext");
180  return false;
181  }
182 
183  osxgsg->reset_if_new();
184  if (!osxgsg->is_valid()) {
185  close_buffer();
186  return false;
187  }
188 
189  /*
190  if (!osxgsg->get_fb_properties().verify_hardware_software
191  (_fb_properties, osxgsg->get_gl_renderer())) {
192  close_buffer();
193  return false;
194  }
195  _fb_properties = osxgsg->get_fb_properties();
196  */
197 
198  _is_valid = true;
199  return true;
200 }
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
An offscreen buffer for rendering into.
This class is the main interface to controlling the render process.
This is a base class for the various different classes that represent the result of a frame of render...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
Encapsulates all the communication with a particular instance of a given rendering backend.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
Definition: texture.cxx:2008
A thread; that is, a lightweight process.
Definition: thread.h:46
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
A container for the various kinds of properties we might ask to have on a graphics window before we o...
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.
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.
This graphics pipe represents the interface for creating OpenGL graphics windows on the various OSX's...
A tiny specialization on GLGraphicsStateGuardian to add some wgl-specific information.
OSStatus build_gl(bool full_screen, bool pbuffer, FrameBufferProperties &fb_props)
This function will build up a context for a gsg.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.