00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00031
00032
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
00043
00044
00045
00046 TinyOsxGraphicsPipe::
00047 ~TinyOsxGraphicsPipe() {
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 string TinyOsxGraphicsPipe::
00061 get_interface_name() const {
00062 return "TinyPanda";
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072 PT(GraphicsPipe) TinyOsxGraphicsPipe::
00073 pipe_constructor() {
00074 return new TinyOsxGraphicsPipe;
00075 }
00076
00077
00078
00079
00080
00081
00082
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
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
00149
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
00187
00188
00189
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
00199
00200
00201
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
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
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
00269 return NULL;
00270 }
00271
00272 #endif // IS_OSX