1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
/* $Id: toglNSOpenGL.c,v 1.1 2012/10/24 22:52:31 mgltools Exp $ */
/* vi:set sw=4 expandtab: */
/*
* Togl - a Tk OpenGL widget
*
* Copyright (C) 1996-2002 Brian Paul and Ben Bederson
* Copyright (C) 2005-2009 Greg Couch
* See the LICENSE file for copyright details.
*/
static NSOpenGLPixelFormat *
togl_pixelFormat(Togl *togl)
{
NSOpenGLPixelFormatAttribute attribs[32];
int na = 0;
NSOpenGLPixelFormat *pix;
#if 0
if (togl->MultisampleFlag && !hasMultisampling) {
Tcl_SetResult(togl->Interp,
TCL_STUPID "multisampling not supported", TCL_STATIC);
return NULL;
}
#endif
if (togl->PbufferFlag && !togl->RgbaFlag) {
Tcl_SetResult(togl->Interp,
TCL_STUPID "puffer must be RGB[A]", TCL_STATIC);
return NULL;
}
attribs[na++] = NSOpenGLPFAMinimumPolicy;
/* ask for hardware-accelerated onscreen */
attribs[na++] = NSOpenGLPFAAccelerated;
attribs[na++] = NSOpenGLPFANoRecovery;
if (togl->RgbaFlag) {
/* RGB[A] mode */
attribs[na++] = NSOpenGLPFAColorSize;
attribs[na++] = togl->RgbaRed + togl->RgbaGreen + togl->RgbaBlue;
/* NSOpenGL does not take separate red,green,blue sizes. */
if (togl->AlphaFlag) {
attribs[na++] = NSOpenGLPFAAlphaSize;
attribs[na++] = togl->AlphaSize;
}
} else {
/* Color index mode */
Tcl_SetResult(togl->Interp,
TCL_STUPID "Color index mode not supported", TCL_STATIC);
return NULL;
}
if (togl->DepthFlag) {
attribs[na++] = NSOpenGLPFADepthSize;
attribs[na++] = togl->DepthSize;
}
if (togl->DoubleFlag) {
attribs[na++] = NSOpenGLPFADoubleBuffer;
}
if (togl->StencilFlag) {
attribs[na++] = NSOpenGLPFAStencilSize;
attribs[na++] = togl->StencilSize;
}
if (togl->AccumFlag) {
attribs[na++] = NSOpenGLPFAAccumSize;
attribs[na++] = togl->AccumRed + togl->AccumGreen + togl->AccumBlue + (togl->AlphaFlag ? togl->AccumAlpha : 0);
}
if (togl->MultisampleFlag) {
attribs[na++] = NSOpenGLPFAMultisample;
attribs[na++] = NSOpenGLPFASampleBuffers;
attribs[na++] = 1;
attribs[na++] = NSOpenGLPFASamples;
attribs[na++] = 2;
}
if (togl->AuxNumber != 0) {
attribs[na++] = NSOpenGLPFAAuxBuffers;
attribs[na++] = togl->AuxNumber;
}
if (togl->Stereo == TOGL_STEREO_NATIVE) {
attribs[na++] = NSOpenGLPFAStereo;
}
if (togl->FullscreenFlag) {
attribs[na++] = NSOpenGLPFAFullScreen;
}
attribs[na++] = 0; /* End of attributes. */
pix = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
if (pix == nil) {
Tcl_SetResult(togl->Interp, TCL_STUPID "couldn't choose pixel format",
TCL_STATIC);
return NULL;
}
return pix;
}
static int
togl_describePixelFormat(Togl *togl)
{
NSOpenGLPixelFormat *pfmt = togl->PixelFormat;
/* fill in RgbaFlag, DoubleFlag, and Stereo */
GLint has_rgba, has_doublebuf, has_depth, has_accum, has_alpha,
has_stencil, has_stereo, has_multisample;
GLint vscr = 0;
[pfmt getValues:&has_rgba forAttribute:NSOpenGLPFAColorSize forVirtualScreen:vscr];
[pfmt getValues:&has_doublebuf forAttribute:NSOpenGLPFADoubleBuffer forVirtualScreen:vscr];
[pfmt getValues:&has_depth forAttribute:NSOpenGLPFADepthSize forVirtualScreen:vscr];
[pfmt getValues:&has_accum forAttribute:NSOpenGLPFAAccumSize forVirtualScreen:vscr];
[pfmt getValues:&has_alpha forAttribute:NSOpenGLPFAAlphaSize forVirtualScreen:vscr];
[pfmt getValues:&has_stencil forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:vscr];
[pfmt getValues:&has_stereo forAttribute:NSOpenGLPFAStereo forVirtualScreen:vscr];
[pfmt getValues:&has_multisample forAttribute:NSOpenGLPFASampleBuffers forVirtualScreen:vscr];
togl->RgbaFlag = (has_rgba != 0);
togl->DoubleFlag = (has_doublebuf != 0);
togl->DepthFlag = (has_depth != 0);
togl->AccumFlag = (has_accum != 0);
togl->AlphaFlag = (has_alpha != 0);
togl->StencilFlag = (has_stencil != 0);
togl->Stereo = (has_stereo ? TOGL_STEREO_NATIVE : TOGL_STEREO_NONE);
togl->MultisampleFlag = (has_multisample != 0);
return True;
}
#define isPow2(x) (((x) & ((x) - 1)) == 0)
static NSOpenGLPixelBuffer *
togl_createPbuffer(Togl *togl)
{
GLint min_size[2], max_size[2];
Bool hasPbuffer;
const char *extensions;
GLint target;
GLint virtualScreen;
NSOpenGLPixelBuffer *pbuf;
extensions = (const char *) glGetString(GL_EXTENSIONS);
hasPbuffer = (strstr(extensions, "GL_APPLE_pixel_buffer") != NULL);
if (!hasPbuffer) {
Tcl_SetResult(togl->Interp,
TCL_STUPID "pbuffers are not supported", TCL_STATIC);
return NULL;
}
glGetIntegerv(GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE, min_size);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_size);
virtualScreen = [togl->Ctx currentVirtualScreen];
for (;;) {
/* make sure we don't exceed the maximum size because if we do,
* NSOpenGLPixelBuffer allocationmay succeed and later uses of
* the pbuffer fail
*/
if (togl->Width < min_size[0])
togl->Width = min_size[0];
else if (togl->Width > max_size[0]) {
if (togl->LargestPbufferFlag)
togl->Width = max_size[0];
else {
Tcl_SetResult(togl->Interp,
TCL_STUPID "pbuffer too large", TCL_STATIC);
return NULL;
}
}
if (togl->Height < min_size[1])
togl->Height = min_size[1];
else if (togl->Height > max_size[1]) {
if (togl->LargestPbufferFlag)
togl->Height = max_size[1];
else {
Tcl_SetResult(togl->Interp,
TCL_STUPID "pbuffer too large", TCL_STATIC);
return NULL;
}
}
if (isPow2(togl->Width) && isPow2(togl->Height))
target = GL_TEXTURE_2D;
else
target = GL_TEXTURE_RECTANGLE_ARB;
pbuf = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:target
textureInternalFormat:(togl->AlphaFlag ? GL_RGBA : GL_RGB)
textureMaxMipMapLevel:0
pixelsWide:togl->Width pixelsHigh:togl->Height];
if (pbuf != nil) {
/* setPixelBuffer allocates the framebuffer space */
[togl->Ctx setPixelBuffer:pbuf cubeMapFace:0 mipMapLevel:0
currentVirtualScreen:virtualScreen];
return pbuf;
}
if (!togl->LargestPbufferFlag
|| togl->Width == min_size[0] || togl->Height == min_size[1]) {
Tcl_SetResult(togl->Interp,
TCL_STUPID "unable to create pbuffer", TCL_STATIC);
return NULL;
}
/* largest unavailable, try something smaller */
togl->Width = togl->Width / 2 + togl->Width % 2;
togl->Height = togl->Width / 2 + togl->Height % 2;
}
}
static void
togl_destroyPbuffer(Togl *togl)
{
[togl->pbuf release];
}
|