2 // "$Id: Fl_Gl_Device_Plugin.cxx 8368 2011-02-04 23:32:53Z manolo $"
4 // implementation of class Fl_Gl_Device_Plugin for the Fast Light Tool Kit (FLTK).
6 // Copyright 2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems to:
25 // http://www.fltk.org/str.php
29 #include <FL/Fl_Printer.H>
30 #include <FL/Fl_Gl_Window.H>
31 #include "Fl_Gl_Choice.H"
34 #include "FL/fl_draw.H"
37 #if defined(__APPLE__)
38 static void imgProviderReleaseData (void *info
, const void *data
, size_t size
)
44 static void print_gl_window(Fl_Gl_Window
*glw
, int x
, int y
, int height
)
48 const int bytesperpixel
= 3;
49 #elif defined(__APPLE__)
50 CGContextRef save_gc
= fl_gc
;
51 const int bytesperpixel
= 4;
53 _XGC
*save_gc
= fl_gc
;
54 const int bytesperpixel
= 3;
56 Fl_Surface_Device
*save_surface
= Fl_Surface_Device::surface();
58 Fl_Display_Device::display_device()->set_current();
61 Fl_Window
*win
= (Fl_Window
*)glw
;
62 while( win
->window() ) win
= win
->window();
73 // Read OpenGL context pixels directly.
74 // For extra safety, save & restore OpenGL states that are changed
75 glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT
);
76 glPixelStorei(GL_PACK_ALIGNMENT
, 4); /* Force 4-byte alignment */
77 glPixelStorei(GL_PACK_ROW_LENGTH
, 0);
78 glPixelStorei(GL_PACK_SKIP_ROWS
, 0);
79 glPixelStorei(GL_PACK_SKIP_PIXELS
, 0);
80 // Read a block of pixels from the frame buffer
81 int mByteWidth
= glw
->w() * bytesperpixel
;
82 mByteWidth
= (mByteWidth
+ 3) & ~3; // Align to 4 bytes
83 uchar
*baseAddress
= (uchar
*)malloc(mByteWidth
* glw
->h());
84 glReadPixels(0, 0, glw
->w(), glw
->h(),
86 GL_RGB
, GL_UNSIGNED_BYTE
,
87 #elif defined(__APPLE__)
88 GL_BGRA
, GL_UNSIGNED_INT_8_8_8_8_REV
,
89 #else // FIXME Linux/Unix
90 GL_RGB
, GL_UNSIGNED_BYTE
,
94 save_surface
->set_current();
96 #if defined(__APPLE__)
97 // kCGBitmapByteOrder32Host and CGBitmapInfo are supposed to arrive with 10.4
98 // but some 10.4 don't have kCGBitmapByteOrder32Host, so we play a little #define game
99 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4
100 #define kCGBitmapByteOrder32Host 0
101 #define CGBitmapInfo CGImageAlphaInfo
102 #elif ! defined(kCGBitmapByteOrder32Host)
103 #ifdef __BIG_ENDIAN__
104 #define kCGBitmapByteOrder32Host (4 << 12)
105 #else /* Little endian. */
106 #define kCGBitmapByteOrder32Host (2 << 12)
109 CGColorSpaceRef cSpace
= CGColorSpaceCreateDeviceRGB();
110 CGDataProviderRef provider
= CGDataProviderCreateWithData(NULL
, baseAddress
, mByteWidth
* glw
->h(), imgProviderReleaseData
);
111 CGImageRef image
= CGImageCreate(glw
->w(), glw
->h(), 8, 8*bytesperpixel
, mByteWidth
, cSpace
,
112 (CGBitmapInfo
)(kCGImageAlphaNoneSkipFirst
| kCGBitmapByteOrder32Host
),
113 provider
, NULL
, false, kCGRenderingIntentDefault
);
114 if(image
== NULL
) return;
115 CGContextSaveGState(fl_gc
);
116 CGContextTranslateCTM(fl_gc
, 0, height
);
117 CGContextScaleCTM(fl_gc
, 1.0f
, -1.0f
);
118 CGRect rect
= { { x
, height
- y
- glw
->h() }, { glw
->w(), glw
->h() } };
119 Fl_X::q_begin_image(rect
, 0, 0, glw
->w(), glw
->h());
120 CGContextDrawImage(fl_gc
, rect
, image
);
122 CGContextRestoreGState(fl_gc
);
123 CGImageRelease(image
);
124 CGColorSpaceRelease(cSpace
);
125 CGDataProviderRelease(provider
);
127 fl_draw_image(baseAddress
+ (glw
->h() - 1) * mByteWidth
, x
, y
, glw
->w(), glw
->h(), bytesperpixel
, - mByteWidth
);
133 This class will make sure that OpenGL printing is available if fltk_gl
134 was linked to the program.
136 class Fl_Gl_Device_Plugin
: public Fl_Device_Plugin
{
138 Fl_Gl_Device_Plugin() : Fl_Device_Plugin(name()) { }
139 virtual const char *name() { return "opengl.device.fltk.org"; }
140 virtual int print(Fl_Widget
*w
, int x
, int y
, int height
) {
141 Fl_Gl_Window
*glw
= w
->as_gl_window();
143 print_gl_window(glw
, x
, y
, height
);
148 static Fl_Gl_Device_Plugin Gl_Device_Plugin
;
150 // The purpose of this variable, used in Fl_Gl_Window.cxx, is only to force this file to be loaded
151 // whenever Fl_Gl_Window.cxx is loaded, that is, whenever fltk_gl is.
152 FL_EXPORT
int fl_gl_load_plugin
= 0;
155 // End of "$Id: Fl_Gl_Device_Plugin.cxx 8368 2011-02-04 23:32:53Z manolo $".