Panda3D
 All Classes Functions Variables Enumerations
tinyOsxGraphicsPipe.cxx
00001 // Filename: tinyOsxGraphicsPipe.cxx
00002 // Created by:  drose (12May08)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pandabase.h"
00016 
00017 #if defined(IS_OSX) && !defined(BUILD_IPHONE)
00018 
00019 #include "tinyOsxGraphicsPipe.h"
00020 #include "config_tinydisplay.h"
00021 #include "tinyOsxGraphicsWindow.h"
00022 #include "tinyGraphicsBuffer.h"
00023 #include "pnmImage.h"
00024 #include "subprocessWindow.h"
00025 #include "nativeWindowHandle.h"
00026 
00027 TypeHandle TinyOsxGraphicsPipe::_type_handle;
00028   
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: TinyOsxGraphicsPipe::Constructor
00031 //       Access: Public
00032 //  Description: 
00033 ////////////////////////////////////////////////////////////////////
00034 TinyOsxGraphicsPipe::
00035 TinyOsxGraphicsPipe() {
00036   CGRect display_bounds = CGDisplayBounds(kCGDirectMainDisplay);
00037   _display_width = CGRectGetWidth(display_bounds);
00038   _display_height = CGRectGetHeight(display_bounds);
00039 }
00040 
00041 ////////////////////////////////////////////////////////////////////
00042 //     Function: TinyOsxGraphicsPipe::Destructor
00043 //       Access: Public, Virtual
00044 //  Description: 
00045 ////////////////////////////////////////////////////////////////////
00046 TinyOsxGraphicsPipe::
00047 ~TinyOsxGraphicsPipe() {
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: TinyOsxGraphicsPipe::get_interface_name
00052 //       Access: Published, Virtual
00053 //  Description: Returns the name of the rendering interface
00054 //               associated with this GraphicsPipe.  This is used to
00055 //               present to the user to allow him/her to choose
00056 //               between several possible GraphicsPipes available on a
00057 //               particular platform, so the name should be meaningful
00058 //               and unique for a given platform.
00059 ////////////////////////////////////////////////////////////////////
00060 string TinyOsxGraphicsPipe::
00061 get_interface_name() const {
00062   return "TinyPanda";
00063 }
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: TinyOsxGraphicsPipe::pipe_constructor
00067 //       Access: Public, Static
00068 //  Description: This function is passed to the GraphicsPipeSelection
00069 //               object to allow the user to make a default
00070 //               TinyOsxGraphicsPipe.
00071 ////////////////////////////////////////////////////////////////////
00072 PT(GraphicsPipe) TinyOsxGraphicsPipe::
00073 pipe_constructor() {
00074   return new TinyOsxGraphicsPipe;
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: TinyOsxGraphicsPipe::create_cg_image
00079 //       Access: Public, Static
00080 //  Description: Creates a new Quartz bitmap image with the data in
00081 //               the indicated PNMImage.  The caller should eventually
00082 //               free this image via CGImageRelease.
00083 ////////////////////////////////////////////////////////////////////
00084 CGImageRef TinyOsxGraphicsPipe::
00085 create_cg_image(const PNMImage &pnm_image) {
00086   size_t width = pnm_image.get_x_size();
00087   size_t height = pnm_image.get_y_size();
00088 
00089 #ifdef PGM_BIGGRAYS
00090   size_t bytes_per_component = 2;
00091 #else
00092   size_t bytes_per_component = 1;
00093 #endif
00094   size_t bits_per_component = bytes_per_component * 8;
00095   size_t num_components = pnm_image.get_num_channels();
00096 
00097   size_t bits_per_pixel = num_components * bits_per_component;
00098   size_t bytes_per_row = num_components * bytes_per_component * width;
00099 
00100   size_t num_bytes = bytes_per_row * height;
00101   bool has_alpha;
00102   bool is_grayscale;
00103 
00104   CFStringRef color_space_name = NULL;
00105   switch (pnm_image.get_color_type()) {
00106   case PNMImage::CT_grayscale:
00107     color_space_name = kCGColorSpaceGenericGray;
00108     has_alpha = false;
00109     is_grayscale = true;
00110     break;
00111 
00112   case PNMImage::CT_two_channel:
00113     color_space_name = kCGColorSpaceGenericGray;
00114     has_alpha = true;
00115     is_grayscale = true;
00116     break;
00117 
00118   case PNMImage::CT_color:
00119     color_space_name = kCGColorSpaceGenericRGB;
00120     has_alpha = false;
00121     is_grayscale = false;
00122     break;
00123 
00124   case PNMImage::CT_four_channel:
00125     color_space_name = kCGColorSpaceGenericRGB;
00126     has_alpha = true;
00127     is_grayscale = false;
00128     break;
00129 
00130   case PNMImage::CT_invalid:
00131     // Shouldn't get here.
00132     nassertr(false, NULL);
00133     break;
00134   }
00135   nassertr(color_space_name != NULL, NULL);
00136 
00137   CGColorSpaceRef color_space = CGColorSpaceCreateWithName(color_space_name);
00138   nassertr(color_space != NULL, NULL);
00139 
00140   CGBitmapInfo bitmap_info = 0;
00141 #ifdef PGM_BIGGRAYS
00142   bitmap_info |= kCGBitmapByteOrder16Host;
00143 #endif
00144   if (has_alpha) {
00145     bitmap_info |= kCGImageAlphaLast;
00146   }
00147 
00148   // Now convert the pixel data to a format friendly to
00149   // CGImageCreate().
00150   char *char_array = (char *)PANDA_MALLOC_ARRAY(num_bytes);
00151 
00152   xelval *dp = (xelval *)char_array;
00153   for (size_t yi = 0; yi < height; ++yi) {
00154     for (size_t xi = 0; xi < width; ++xi) {
00155       if (is_grayscale) {
00156         *dp++ = (xelval)(pnm_image.get_gray(xi, yi) * PGM_MAXMAXVAL);
00157       } else {
00158         *dp++ = (xelval)(pnm_image.get_red(xi, yi) * PGM_MAXMAXVAL);
00159         *dp++ = (xelval)(pnm_image.get_green(xi, yi) * PGM_MAXMAXVAL);
00160         *dp++ = (xelval)(pnm_image.get_blue(xi, yi) * PGM_MAXMAXVAL);
00161       }
00162       if (has_alpha) {
00163         *dp++ = (xelval)(pnm_image.get_alpha(xi, yi) * PGM_MAXMAXVAL);
00164       }
00165     }
00166   }
00167   nassertr((void *)dp == (void *)(char_array + num_bytes), NULL);
00168 
00169   CGDataProviderRef provider = 
00170     CGDataProviderCreateWithData(NULL, char_array, num_bytes, release_data);
00171   nassertr(provider != NULL, NULL);
00172 
00173   CGImageRef image = CGImageCreate
00174     (width, height, bits_per_component, bits_per_pixel, bytes_per_row,
00175      color_space, bitmap_info, provider,
00176      NULL, false, kCGRenderingIntentDefault);
00177   nassertr(image != NULL, NULL);
00178 
00179   CGColorSpaceRelease(color_space);
00180   CGDataProviderRelease(provider);
00181 
00182   return image;
00183 }
00184 
00185 ////////////////////////////////////////////////////////////////////
00186 //     Function: TinyOsxGraphicsPipe::release_data
00187 //       Access: Private, Static
00188 //  Description: This callback is assigned to delete the data array
00189 //               allocated within create_cg_image().
00190 ////////////////////////////////////////////////////////////////////
00191 void TinyOsxGraphicsPipe::
00192 release_data(void *info, const void *data, size_t size) {
00193   char *char_array = (char *)data;
00194   PANDA_FREE_ARRAY(char_array);
00195 }
00196 
00197 ////////////////////////////////////////////////////////////////////
00198 //     Function: TinyOsxGraphicsPipe::make_output
00199 //       Access: Protected, Virtual
00200 //  Description: Creates a new window or buffer on the pipe, if possible.
00201 //               This routine is only called from GraphicsEngine::make_output.
00202 ////////////////////////////////////////////////////////////////////
00203 PT(GraphicsOutput) TinyOsxGraphicsPipe::
00204 make_output(const string &name,
00205             const FrameBufferProperties &fb_prop,
00206             const WindowProperties &win_prop,
00207             int flags,
00208             GraphicsEngine *engine,
00209             GraphicsStateGuardian *gsg,
00210             GraphicsOutput *host,
00211             int retry,
00212             bool &precertify) {
00213   
00214   if (!_is_valid) {
00215     return NULL;
00216   }
00217 
00218   TinyGraphicsStateGuardian *tinygsg = 0;
00219   if (gsg != 0) {
00220     DCAST_INTO_R(tinygsg, gsg, NULL);
00221   }
00222 
00223   // First thing to try: a TinyOsxGraphicsWindow
00224 
00225   if (retry == 0) {
00226     if (((flags&BF_require_parasite)!=0)||
00227         ((flags&BF_refuse_window)!=0)||
00228         ((flags&BF_resizeable)!=0)||
00229         ((flags&BF_size_track_host)!=0)||
00230         ((flags&BF_rtt_cumulative)!=0)||
00231         ((flags&BF_can_bind_color)!=0)||
00232         ((flags&BF_can_bind_every)!=0)) {
00233       return NULL;
00234     }
00235     if ((flags & BF_fb_props_optional)==0) {
00236       if ((fb_prop.get_aux_rgba() > 0)||
00237           (fb_prop.get_aux_hrgba() > 0)||
00238           (fb_prop.get_aux_float() > 0)) {
00239         return NULL;
00240       }
00241     }
00242     WindowHandle *window_handle = win_prop.get_parent_window();
00243     if (window_handle != NULL) {
00244       tinydisplay_cat.info()
00245         << "Got parent_window " << *window_handle << "\n";
00246 #ifdef SUPPORT_SUBPROCESS_WINDOW
00247       WindowHandle::OSHandle *os_handle = window_handle->get_os_handle();
00248       if (os_handle != NULL && 
00249           os_handle->is_of_type(NativeWindowHandle::SubprocessHandle::get_class_type())) {
00250         return new SubprocessWindow(engine, this, name, fb_prop, win_prop,
00251                                     flags, gsg, host);
00252       }
00253 #endif  // SUPPORT_SUBPROCESS_WINDOW
00254     }
00255     return new TinyOsxGraphicsWindow(engine, this, name, fb_prop, win_prop,
00256                                      flags, gsg, host);
00257   }
00258   
00259   // Second thing to try: a TinyGraphicsBuffer
00260   if (retry == 1) {
00261     if (((flags&BF_require_parasite)!=0)||
00262         ((flags&BF_require_window)!=0)) {
00263       return NULL;
00264     }
00265     return new TinyGraphicsBuffer(engine, this, name, fb_prop, win_prop, flags, gsg, host);
00266   }
00267   
00268   // Nothing else left to try.
00269   return NULL;
00270 }
00271 
00272 #endif  // IS_OSX
 All Classes Functions Variables Enumerations