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 }
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
An offscreen buffer for rendering into.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
OSStatus build_gl(bool full_screen, bool pbuffer, FrameBufferProperties &fb_props)
This function will build up a context for a gsg.
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...
static int up_to_power_2(int value)
Returns the smallest power of 2 greater than or equal to value.
Definition: texture.cxx:1983
A thread; that is, a lightweight process.
Definition: thread.h:46
Encapsulates all the communication with a particular instance of a given rendering backend.
This class is the main interface to controlling the render process.
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 frameBuffer before...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.