]>
Commit | Line | Data |
---|---|---|
4fcb208a SC |
1 | /* |
2 | IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in | |
3 | consideration of your agreement to the following terms, and your use, installation or modification | |
4 | of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, | |
5 | please do not use, install or modify this Apple software. | |
03647350 | 6 | |
4fcb208a SC |
7 | In consideration of your agreement to abide by the following terms, and subject to these |
8 | terms, Apple grants you a personal, non-exclusive license, under Apple\xd5s copyrights in | |
9 | this original Apple software (the "Apple Software"), to use and modify the Apple Software, | |
10 | with or without modifications, in source and/or binary forms; provided that if you redistribute | |
11 | the Apple Software in its entirety and without modifications, you must retain this notice and | |
12 | the following text and disclaimers in all such redistributions of the Apple Software. | |
13 | Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used | |
14 | to endorse or promote products derived from the Apple Software without specific prior | |
15 | written permission from Apple. Except as expressly tated in this notice, no other rights or | |
16 | licenses, express or implied, are granted by Apple herein, including but not limited | |
17 | to any patent rights that may be infringed by your derivative works or by other works | |
18 | in which the Apple Software may be incorporated. | |
03647350 | 19 | |
4fcb208a SC |
20 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, |
21 | EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, | |
22 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS | |
23 | USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. | |
03647350 | 24 | |
4fcb208a SC |
25 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL |
26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |
27 | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, | |
28 | REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND | |
29 | WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR | |
30 | OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | |
32 | ||
2059576f SC |
33 | #include "wx/wxprec.h" |
34 | ||
afd5d91c SC |
35 | #if wxOSX_USE_COCOA_OR_CARBON |
36 | ||
4fcb208a SC |
37 | #import <CoreFoundation/CoreFoundation.h> |
38 | #import <ApplicationServices/ApplicationServices.h> | |
39 | #import <OpenGL/OpenGL.h> | |
40 | #import <OpenGL/gl.h> | |
41 | ||
bab9aa28 | 42 | #include "wx/osx/core/private.h" |
4fcb208a SC |
43 | #include "wx/osx/private/glgrab.h" |
44 | ||
45 | extern CGColorSpaceRef wxMacGetGenericRGBColorSpace(); | |
46 | ||
47 | /* | |
48 | * perform an in-place swap from Quadrant 1 to Quadrant III format | |
49 | * (upside-down PostScript/GL to right side up QD/CG raster format) | |
50 | * We do this in-place, which requires more copying, but will touch | |
51 | * only half the pages. (Display grabs are BIG!) | |
52 | * | |
53 | * Pixel reformatting may optionally be done here if needed. | |
54 | */ | |
55 | static void swizzleBitmap(void * data, int rowBytes, int height) | |
56 | { | |
57 | int top, bottom; | |
58 | void * buffer; | |
59 | void * topP; | |
60 | void * bottomP; | |
61 | void * base; | |
03647350 VZ |
62 | |
63 | ||
4fcb208a SC |
64 | top = 0; |
65 | bottom = height - 1; | |
66 | base = data; | |
67 | buffer = malloc(rowBytes); | |
03647350 VZ |
68 | |
69 | ||
4fcb208a SC |
70 | while ( top < bottom ) |
71 | { | |
72 | topP = (void *)((top * rowBytes) + (intptr_t)base); | |
73 | bottomP = (void *)((bottom * rowBytes) + (intptr_t)base); | |
03647350 VZ |
74 | |
75 | ||
4fcb208a SC |
76 | /* |
77 | * Save and swap scanlines. | |
78 | * | |
79 | * This code does a simple in-place exchange with a temp buffer. | |
80 | * If you need to reformat the pixels, replace the first two bcopy() | |
81 | * calls with your own custom pixel reformatter. | |
82 | */ | |
83 | bcopy( topP, buffer, rowBytes ); | |
84 | bcopy( bottomP, topP, rowBytes ); | |
85 | bcopy( buffer, bottomP, rowBytes ); | |
03647350 | 86 | |
4fcb208a SC |
87 | ++top; |
88 | --bottom; | |
89 | } | |
90 | free( buffer ); | |
91 | } | |
92 | ||
93 | ||
94 | /* | |
95 | * Given a display ID and a rectangle on that display, generate a CGImageRef | |
96 | * containing the display contents. | |
97 | * | |
98 | * srcRect is display-origin relative. | |
99 | * | |
100 | * This function uses a full screen OpenGL read-only context. | |
101 | * By using OpenGL, we can read the screen using a DMA transfer | |
102 | * when it's in millions of colors mode, and we can correctly read | |
103 | * a microtiled full screen OpenGL context, such as a game or full | |
104 | * screen video display. | |
105 | * | |
106 | * Returns a CGImageRef. When you are done with the CGImageRef, release it | |
107 | * using CFRelease(). | |
108 | * Returns NULL on an error. | |
109 | */ | |
03647350 | 110 | |
4fcb208a SC |
111 | CGImageRef grabViaOpenGL(CGDirectDisplayID display, CGRect srcRect) |
112 | { | |
113 | CGContextRef bitmap; | |
114 | CGImageRef image; | |
115 | void * data; | |
116 | long bytewidth; | |
117 | GLint width, height; | |
118 | long bytes; | |
03647350 | 119 | |
4fcb208a SC |
120 | CGLContextObj glContextObj; |
121 | CGLPixelFormatObj pixelFormatObj ; | |
122 | GLint numPixelFormats ; | |
123 | CGLPixelFormatAttribute attribs[] = | |
124 | { | |
125 | kCGLPFAFullScreen, | |
126 | kCGLPFADisplayMask, | |
127 | (CGLPixelFormatAttribute) 0, /* Display mask bit goes here */ | |
128 | (CGLPixelFormatAttribute) 0 | |
129 | } ; | |
03647350 VZ |
130 | |
131 | ||
4fcb208a SC |
132 | if ( display == kCGNullDirectDisplay ) |
133 | display = CGMainDisplayID(); | |
134 | attribs[2] = (CGLPixelFormatAttribute) CGDisplayIDToOpenGLDisplayMask(display); | |
03647350 VZ |
135 | |
136 | ||
4fcb208a SC |
137 | /* Build a full-screen GL context */ |
138 | CGLChoosePixelFormat( attribs, &pixelFormatObj, &numPixelFormats ); | |
139 | if ( pixelFormatObj == NULL ) // No full screen context support | |
140 | return NULL; | |
141 | CGLCreateContext( pixelFormatObj, NULL, &glContextObj ) ; | |
142 | CGLDestroyPixelFormat( pixelFormatObj ) ; | |
143 | if ( glContextObj == NULL ) | |
144 | return NULL; | |
03647350 VZ |
145 | |
146 | ||
4fcb208a SC |
147 | CGLSetCurrentContext( glContextObj ) ; |
148 | CGLSetFullScreen( glContextObj ) ; | |
03647350 VZ |
149 | |
150 | ||
4fcb208a | 151 | glReadBuffer(GL_FRONT); |
03647350 VZ |
152 | |
153 | ||
c22ace4d VZ |
154 | width = (GLint)srcRect.size.width; |
155 | height = (GLint)srcRect.size.height; | |
03647350 VZ |
156 | |
157 | ||
4fcb208a SC |
158 | bytewidth = width * 4; // Assume 4 bytes/pixel for now |
159 | bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes | |
160 | bytes = bytewidth * height; // width * height | |
03647350 | 161 | |
4fcb208a SC |
162 | /* Build bitmap context */ |
163 | data = malloc(height * bytewidth); | |
164 | if ( data == NULL ) | |
165 | { | |
166 | CGLSetCurrentContext( NULL ); | |
167 | CGLClearDrawable( glContextObj ); // disassociate from full screen | |
168 | CGLDestroyContext( glContextObj ); // and destroy the context | |
169 | return NULL; | |
170 | } | |
171 | bitmap = CGBitmapContextCreate(data, width, height, 8, bytewidth, | |
172 | wxMacGetGenericRGBColorSpace(), kCGImageAlphaNoneSkipFirst /* XRGB */); | |
03647350 VZ |
173 | |
174 | ||
4fcb208a SC |
175 | /* Read framebuffer into our bitmap */ |
176 | glFinish(); /* Finish all OpenGL commands */ | |
177 | glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */ | |
178 | glPixelStorei(GL_PACK_ROW_LENGTH, 0); | |
179 | glPixelStorei(GL_PACK_SKIP_ROWS, 0); | |
180 | glPixelStorei(GL_PACK_SKIP_PIXELS, 0); | |
03647350 | 181 | |
4fcb208a SC |
182 | /* |
183 | * Fetch the data in XRGB format, matching the bitmap context. | |
184 | */ | |
185 | glReadPixels((GLint)srcRect.origin.x, (GLint)srcRect.origin.y, width, height, | |
186 | GL_BGRA, | |
187 | #ifdef __BIG_ENDIAN__ | |
188 | GL_UNSIGNED_INT_8_8_8_8_REV, // for PPC | |
189 | #else | |
190 | GL_UNSIGNED_INT_8_8_8_8, // for Intel! http://lists.apple.com/archives/quartz-dev/2006/May/msg00100.html | |
191 | #endif | |
192 | data); | |
193 | /* | |
194 | * glReadPixels generates a quadrant I raster, with origin in the lower left | |
195 | * This isn't a problem for signal processing routines such as compressors, | |
196 | * as they can simply use a negative 'advance' to move between scanlines. | |
197 | * CGImageRef and CGBitmapContext assume a quadrant III raster, though, so we need to | |
198 | * invert it. Pixel reformatting can also be done here. | |
199 | */ | |
200 | swizzleBitmap(data, bytewidth, height); | |
03647350 VZ |
201 | |
202 | ||
4fcb208a SC |
203 | /* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */ |
204 | image = CGBitmapContextCreateImage(bitmap); | |
03647350 | 205 | |
4fcb208a SC |
206 | /* Get rid of bitmap */ |
207 | CFRelease(bitmap); | |
208 | free(data); | |
03647350 VZ |
209 | |
210 | ||
4fcb208a SC |
211 | /* Get rid of GL context */ |
212 | CGLSetCurrentContext( NULL ); | |
213 | CGLClearDrawable( glContextObj ); // disassociate from full screen | |
214 | CGLDestroyContext( glContextObj ); // and destroy the context | |
03647350 | 215 | |
4fcb208a SC |
216 | /* Returned image has a reference count of 1 */ |
217 | return image; | |
218 | } | |
219 | ||
afd5d91c | 220 | #endif |