Panda3D
 All Classes Functions Variables Enumerations
tinyOsxGraphicsPipe.cxx
1 // Filename: tinyOsxGraphicsPipe.cxx
2 // Created by: drose (12May08)
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 #if defined(IS_OSX) && !defined(BUILD_IPHONE) && defined(HAVE_CARBON) && !__LP64__
18 
19 #include "tinyOsxGraphicsPipe.h"
20 #include "config_tinydisplay.h"
21 #include "tinyOsxGraphicsWindow.h"
22 #include "tinyGraphicsBuffer.h"
23 #include "pnmImage.h"
24 #include "subprocessWindow.h"
25 #include "nativeWindowHandle.h"
26 
27 TypeHandle TinyOsxGraphicsPipe::_type_handle;
28 
29 ////////////////////////////////////////////////////////////////////
30 // Function: TinyOsxGraphicsPipe::Constructor
31 // Access: Public
32 // Description:
33 ////////////////////////////////////////////////////////////////////
34 TinyOsxGraphicsPipe::
35 TinyOsxGraphicsPipe() {
36  CGRect display_bounds = CGDisplayBounds(kCGDirectMainDisplay);
37  _display_width = CGRectGetWidth(display_bounds);
38  _display_height = CGRectGetHeight(display_bounds);
39 }
40 
41 ////////////////////////////////////////////////////////////////////
42 // Function: TinyOsxGraphicsPipe::Destructor
43 // Access: Public, Virtual
44 // Description:
45 ////////////////////////////////////////////////////////////////////
46 TinyOsxGraphicsPipe::
47 ~TinyOsxGraphicsPipe() {
48 }
49 
50 ////////////////////////////////////////////////////////////////////
51 // Function: TinyOsxGraphicsPipe::get_interface_name
52 // Access: Published, Virtual
53 // Description: Returns the name of the rendering interface
54 // associated with this GraphicsPipe. This is used to
55 // present to the user to allow him/her to choose
56 // between several possible GraphicsPipes available on a
57 // particular platform, so the name should be meaningful
58 // and unique for a given platform.
59 ////////////////////////////////////////////////////////////////////
60 string TinyOsxGraphicsPipe::
61 get_interface_name() const {
62  return "TinyPanda";
63 }
64 
65 ////////////////////////////////////////////////////////////////////
66 // Function: TinyOsxGraphicsPipe::pipe_constructor
67 // Access: Public, Static
68 // Description: This function is passed to the GraphicsPipeSelection
69 // object to allow the user to make a default
70 // TinyOsxGraphicsPipe.
71 ////////////////////////////////////////////////////////////////////
72 PT(GraphicsPipe) TinyOsxGraphicsPipe::
73 pipe_constructor() {
74  return new TinyOsxGraphicsPipe;
75 }
76 
77 ////////////////////////////////////////////////////////////////////
78 // Function: TinyOsxGraphicsPipe::create_cg_image
79 // Access: Public, Static
80 // Description: Creates a new Quartz bitmap image with the data in
81 // the indicated PNMImage. The caller should eventually
82 // free this image via CGImageRelease.
83 ////////////////////////////////////////////////////////////////////
84 CGImageRef TinyOsxGraphicsPipe::
85 create_cg_image(const PNMImage &pnm_image) {
86  size_t width = pnm_image.get_x_size();
87  size_t height = pnm_image.get_y_size();
88 
89 #ifdef PGM_BIGGRAYS
90  size_t bytes_per_component = 2;
91 #else
92  size_t bytes_per_component = 1;
93 #endif
94  size_t bits_per_component = bytes_per_component * 8;
95  size_t num_components = pnm_image.get_num_channels();
96 
97  size_t bits_per_pixel = num_components * bits_per_component;
98  size_t bytes_per_row = num_components * bytes_per_component * width;
99 
100  size_t num_bytes = bytes_per_row * height;
101  bool has_alpha;
102  bool is_grayscale;
103 
104  CFStringRef color_space_name = NULL;
105  switch (pnm_image.get_color_type()) {
106  case PNMImage::CT_grayscale:
107  color_space_name = kCGColorSpaceGenericGray;
108  has_alpha = false;
109  is_grayscale = true;
110  break;
111 
112  case PNMImage::CT_two_channel:
113  color_space_name = kCGColorSpaceGenericGray;
114  has_alpha = true;
115  is_grayscale = true;
116  break;
117 
118  case PNMImage::CT_color:
119  color_space_name = kCGColorSpaceGenericRGB;
120  has_alpha = false;
121  is_grayscale = false;
122  break;
123 
124  case PNMImage::CT_four_channel:
125  color_space_name = kCGColorSpaceGenericRGB;
126  has_alpha = true;
127  is_grayscale = false;
128  break;
129 
130  case PNMImage::CT_invalid:
131  // Shouldn't get here.
132  nassertr(false, NULL);
133  break;
134  }
135  nassertr(color_space_name != NULL, NULL);
136 
137  CGColorSpaceRef color_space = CGColorSpaceCreateWithName(color_space_name);
138  nassertr(color_space != NULL, NULL);
139 
140  CGBitmapInfo bitmap_info = 0;
141 #ifdef PGM_BIGGRAYS
142  bitmap_info |= kCGBitmapByteOrder16Host;
143 #endif
144  if (has_alpha) {
145  bitmap_info |= kCGImageAlphaLast;
146  }
147 
148  // Now convert the pixel data to a format friendly to
149  // CGImageCreate().
150  char *char_array = (char *)PANDA_MALLOC_ARRAY(num_bytes);
151 
152  xelval *dp = (xelval *)char_array;
153  for (size_t yi = 0; yi < height; ++yi) {
154  for (size_t xi = 0; xi < width; ++xi) {
155  if (is_grayscale) {
156  *dp++ = (xelval)(pnm_image.get_gray(xi, yi) * PGM_MAXMAXVAL);
157  } else {
158  *dp++ = (xelval)(pnm_image.get_red(xi, yi) * PGM_MAXMAXVAL);
159  *dp++ = (xelval)(pnm_image.get_green(xi, yi) * PGM_MAXMAXVAL);
160  *dp++ = (xelval)(pnm_image.get_blue(xi, yi) * PGM_MAXMAXVAL);
161  }
162  if (has_alpha) {
163  *dp++ = (xelval)(pnm_image.get_alpha(xi, yi) * PGM_MAXMAXVAL);
164  }
165  }
166  }
167  nassertr((void *)dp == (void *)(char_array + num_bytes), NULL);
168 
169  CGDataProviderRef provider =
170  CGDataProviderCreateWithData(NULL, char_array, num_bytes, release_data);
171  nassertr(provider != NULL, NULL);
172 
173  CGImageRef image = CGImageCreate
174  (width, height, bits_per_component, bits_per_pixel, bytes_per_row,
175  color_space, bitmap_info, provider,
176  NULL, false, kCGRenderingIntentDefault);
177  nassertr(image != NULL, NULL);
178 
179  CGColorSpaceRelease(color_space);
180  CGDataProviderRelease(provider);
181 
182  return image;
183 }
184 
185 ////////////////////////////////////////////////////////////////////
186 // Function: TinyOsxGraphicsPipe::release_data
187 // Access: Private, Static
188 // Description: This callback is assigned to delete the data array
189 // allocated within create_cg_image().
190 ////////////////////////////////////////////////////////////////////
191 void TinyOsxGraphicsPipe::
192 release_data(void *info, const void *data, size_t size) {
193  char *char_array = (char *)data;
194  PANDA_FREE_ARRAY(char_array);
195 }
196 
197 ////////////////////////////////////////////////////////////////////
198 // Function: TinyOsxGraphicsPipe::make_output
199 // Access: Protected, Virtual
200 // Description: Creates a new window or buffer on the pipe, if possible.
201 // This routine is only called from GraphicsEngine::make_output.
202 ////////////////////////////////////////////////////////////////////
203 PT(GraphicsOutput) TinyOsxGraphicsPipe::
204 make_output(const string &name,
205  const FrameBufferProperties &fb_prop,
206  const WindowProperties &win_prop,
207  int flags,
208  GraphicsEngine *engine,
210  GraphicsOutput *host,
211  int retry,
212  bool &precertify) {
213 
214  if (!_is_valid) {
215  return NULL;
216  }
217 
218  TinyGraphicsStateGuardian *tinygsg = 0;
219  if (gsg != 0) {
220  DCAST_INTO_R(tinygsg, gsg, NULL);
221  }
222 
223  // First thing to try: a TinyOsxGraphicsWindow
224 
225  if (retry == 0) {
226  if (((flags&BF_require_parasite)!=0)||
227  ((flags&BF_refuse_window)!=0)||
228  ((flags&BF_resizeable)!=0)||
229  ((flags&BF_size_track_host)!=0)||
230  ((flags&BF_rtt_cumulative)!=0)||
231  ((flags&BF_can_bind_color)!=0)||
232  ((flags&BF_can_bind_every)!=0)) {
233  return NULL;
234  }
235  if ((flags & BF_fb_props_optional)==0) {
236  if ((fb_prop.get_aux_rgba() > 0)||
237  (fb_prop.get_aux_hrgba() > 0)||
238  (fb_prop.get_aux_float() > 0)) {
239  return NULL;
240  }
241  }
242  WindowHandle *window_handle = win_prop.get_parent_window();
243  if (window_handle != NULL) {
244  tinydisplay_cat.info()
245  << "Got parent_window " << *window_handle << "\n";
246 #ifdef SUPPORT_SUBPROCESS_WINDOW
247  WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
248  if (os_handle != NULL &&
249  os_handle->is_of_type(NativeWindowHandle::SubprocessHandle::get_class_type())) {
250  return new SubprocessWindow(engine, this, name, fb_prop, win_prop,
251  flags, gsg, host);
252  }
253 #endif // SUPPORT_SUBPROCESS_WINDOW
254  }
255  return new TinyOsxGraphicsWindow(engine, this, name, fb_prop, win_prop,
256  flags, gsg, host);
257  }
258 
259  // Second thing to try: a TinyGraphicsBuffer
260  if (retry == 1) {
261  if (((flags&BF_require_parasite)!=0)||
262  ((flags&BF_require_window)!=0)) {
263  return NULL;
264  }
265  return new TinyGraphicsBuffer(engine, this, name, fb_prop, win_prop, flags, gsg, host);
266  }
267 
268  // Nothing else left to try.
269  return NULL;
270 }
271 
272 #endif // IS_OSX
This object represents a window on the desktop, not necessarily a Panda window.
Definition: windowHandle.h:40
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
Definition: pnmImage.h:68
int get_num_channels() const
Returns the number of channels in the image.
float get_red(int x, int y) const
Returns the red component color at the indicated pixel.
Definition: pnmImage.I:889
float get_blue(int x, int y) const
Returns the blue component color at the indicated pixel.
Definition: pnmImage.I:913
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:63
float get_gray(int x, int y) const
Returns the gray component color at the indicated pixel.
Definition: pnmImage.I:928
int get_x_size() const
Returns the number of pixels in the X direction.
An offscreen graphics buffer.
float get_alpha(int x, int y) const
Returns the alpha component color at the indicated pixel.
Definition: pnmImage.I:941
int get_y_size() const
Returns the number of pixels in the Y direction.
float get_green(int x, int y) const
Returns the green component color at the indicated pixel.
Definition: pnmImage.I:901
A container for the various kinds of properties we might ask to have on a graphics window before we o...
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:58
ColorType get_color_type() const
Returns the image type of the image, as an enumerated value.
This is a base class for the various different classes that represent the result of a frame of render...
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:85
OSHandle * get_os_handle() const
Returns the OS-specific handle stored internally to the WindowHandle wrapper.
Definition: windowHandle.I:41
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.