-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlisting7.html
executable file
·1045 lines (911 loc) · 54.2 KB
/
listing7.html
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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<html>
<head>
<!-- BEGIN META TAG INFO -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="home" href="http://developer.apple.com/">
<link rel="find" href="http://developer.apple.com/search/">
<link rel="stylesheet" type="text/css" href="../../documentation/css/adcstyle.css" title="fonts">
<script language="JavaScript" src="../../documentation/js/adc.js" type="text/javascript"></script>
<!-- END META TAG INFO -->
<!-- BEGIN TITLE -->
<title>OpenGL Image - /OpenGL_Image_Utilities.c</title>
<!-- END TITLE -->
<script language="JavaScript">
function JumpToNewPage() {
window.location=document.scpopupmenu.gotop.value;
return true;
}
</script>
</head>
<!-- BEGIN BODY OPEN -->
<body>
<!--END BODY OPEN -->
<!-- START CENTER OPEN -->
<center>
<!-- END CENTER OPEN -->
<!-- BEGIN LOGO AND SEARCH -->
<!--#include virtual="/includes/adcnavbar"-->
<!-- END LOGO AND SEARCH -->
<!-- START BREADCRUMB -->
<div id="breadcrumb">
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td scope="row"><img width="340" height="10" src="images/1dot.gif" alt=""></td>
<td><img width="340" height="10" src="images/1dot.gif" alt=""></td>
</tr>
<tr valign="middle">
<td align="left" colspan="2">
<a href="http://developer.apple.com/">ADC Home</a> > <a href="../../referencelibrary/index.html">Reference Library</a> > <a href="../../samplecode/index.html">Sample Code</a> > <a href="../../samplecode/LegacyTechnologies/index.html">Legacy Documents</a> > <a href="../../samplecode/LegacyTechnologies/idxGraphicsImaging-date.html">Graphics & Imaging</a> > <A HREF="javascript:location.replace('index.html');">OpenGL Image</A> >
</td>
</tr>
<tr>
<td colspan="2" scope="row"><img width="680" height="35" src="images/1dot.gif" alt=""></td>
</tr>
</table>
</div>
<!-- END BREADCRUMB -->
<div style="width:100%; position:fixed;"><div align="center" id="watermark" style="position: relative; margin-left:auto; margin-right:auto; z-index:20; width:500px;"><div class="legacybox"><h1>Legacy Document<span class=closebutton><a href="javascript:closeWatermark()"><img src="../../images/closebutton.png" width="14" height="14" border="0" alt="close button"></a></span></h1>
<p><strong>Important: </strong>This document is part of the Legacy section of the ADC Reference Library. This information should not be used for new development.</p>
<div class="reflibtopic">
<p>Current information on this Reference Library topic can be found here:</p>
<ul>
<li><a href="http://developer.apple.com/referencelibrary/GraphicsImaging/idxOpenGL-date.html" target="_blank">Graphics & Imaging > OpenGL</a></li>
</ul>
</div>
</div></div></div>
<!-- START MAIN CONTENT -->
<!-- START TITLE GRAPHIC AND INTRO-->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td><h1><div id="pagehead">OpenGL Image</div></h1></td>
</tr>
</table>
<!-- END TITLE GRAPHIC AND INTRO -->
<!-- START WIDE COLUMN -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr align="left" valign="top">
<td id="scdetails">
<h2>/OpenGL_Image_Utilities.c</h2>
<form name="scpopupmenu" onSubmit="return false;" method=post>
<p><strong>View Source Code:</strong>
<select name="gotop" onChange="JumpToNewPage();" style="width:340px"><option selected value="ingnore">Select File</option>
<option value="listing1.html">/Carbon Include.h</option>
<option value="listing2.html">/Carbon.r</option>
<option value="listing3.html">/main.c</option>
<option value="listing4.html">/OpenGL_Image.h</option>
<option value="listing5.html">/OpenGL_Image_Loading.c</option>
<option value="listing6.html">/OpenGL_Image_Options-Dialog.c</option>
<option value="listing7.html">/OpenGL_Image_Utilities.c</option></select>
</p>
</form>
<p><strong><a href="OpenGL_Image.zip">Download Sample</a></strong> (“OpenGL_Image.zip”, 340.7K)<BR>
<strong><a href="OpenGL_Image.dmg">Download Sample</a></strong> (“OpenGL_Image.dmg”, 444.3K)</p>
<!--
<p><strong><a href="#">Download Sample</a></strong> (“filename.sit”, 500K)</p>
-->
</td>
</tr>
<tr>
<td scope="row"><img width="680" height="10" src="images/1dot.gif" alt=""><br>
<img height="1" width="680" src="images/1dot_919699.gif" alt=""><br>
<img width="680" height="20" src="images/1dot.gif" alt=""></td>
</tr>
<tr>
<td scope="row">
<!--googleon: index -->
<pre class="sourcecodebox">/* * OpenGL_Image_Utilities.c * OpenGL Image * * Created by ggs on Fri May 11 2001. Copyright: Copyright © 2001 Apple Computer, Inc., All Rights Reserved Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */#ifdef __APPLE_CC__ // project builder #include <Carbon/Carbon.h> // standard carbon #include <OpenGL/gl.h> // for OpenGL API #include <OpenGL/glext.h> // for OpenGL extension support #else // CodeWarrior #include <FixMath.h> // for X2Fix #include <fp.h> // for trig functions #include <DriverServices.h> #include <gl.h> // for OpenGL API #include <glext.h> // for OpenGL extension support #include <stdio.h> // standard input/output (sprintf) #include <string.h> // for string handling (strstr)#endif#include "aglString.h" // opengl string handling#include "Carbon_SetupGL.h" // standard setup code (SetupGL)#include "Carbon_Error_Handler.h" // standard SetupGL error handling#include "OpenGL_Image.h" // our header// drag globalsPoint gptDragStart = {0, 0}; // starting point at mouse down for dragWindowRef gDragWindow = NULL; // the window in which the mouse is draggingshort gDragType = 0; // either kDrag or kRotation to indicate what type of drag the user is doing// ================================== static void DrawGLTexelGrid (float textureWidth, float textureHeight, float imageWidth, float imageHeight, float zoom); // in pixels static long GetNextTextureSize (long textureDimension, long maxTextureSize, Boolean textureRectangle); static long GetTextureNumFromTextureDim (long textureDimension, long maxTextureSize, Boolean texturesOverlap, Boolean textureRectangle); static void DrawGLImageTile (unsigned long drawType, float imageWidth, float imageHeight, float zoom, float textureWidth, float textureHeight, float offsetX, float offsetY, float endX, float endY, Boolean texturesOverlap, Boolean textureRectangle); pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData); EventLoopTimerUPP GetTimerUPP (void);// ==================================// private// draws grid lines in current color between each texel in the texture as it corresponds to orginal image// i.e., draws grid lines based on texels but constrains output to image dimensionsstatic void DrawGLTexelGrid (float textureWidth, float textureHeight, float imageWidth, float imageHeight, float zoom) // in pixels{ long i; // iterator float perpenCoord, coord, coordStep; // perpendicular coordinate, dawing (iteratoring) coordinate, coordiante step amount per line glBegin (GL_LINES); // draw using lines // vertical lines perpenCoord = 0.5f * imageHeight * zoom; // 1/2 height of image in world space coord = -0.5f * imageWidth * zoom; // starting scaled coordinate for half of image width (world space) coordStep = imageWidth / textureWidth * zoom; // space between each line (maps texture size to image size) for (i = 0; i <= textureWidth; i++) // ith column { glVertex3f (coord, -perpenCoord, 0.0f); // draw from current column, top of image to... glVertex3f (coord, perpenCoord, 0.0f); // current column, bottom of image coord += coordStep; // step to next column } // horizontal lines perpenCoord = 0.5f * imageWidth * zoom; // 1/2 width of image in world space coord = -0.5f * imageHeight * zoom; // scaled coordinate for half of image height (actual drawing coords) coordStep = imageHeight / textureHeight * zoom; // space between each line (maps texture size to image size) for (i = 0; i <= textureHeight; i++) // ith row { glVertex3f (-perpenCoord, coord, 0.0f); // draw from current row, left edge of image to... glVertex3f (perpenCoord, coord, 0.0f);// current row, right edge of image coord += coordStep; // step to next row } glEnd(); // end our set of lines}// ---------------------------------// returns the largest power of 2 texture <= textureDimension and <= gMaxTextureSize// or in the case of texture rectangle returns the next texture size (can be non-power of two)static long GetNextTextureSize (long textureDimension, long maxTextureSize, Boolean textureRectangle){ long targetTextureSize = maxTextureSize; // start at max texture size if (textureRectangle) { if (textureDimension >= targetTextureSize) // the texture dimension is greater than the target texture size (i.e., it fits) return targetTextureSize; // return corresponding texture size else return textureDimension; // jusr return the dimension } else { do // while we have txture sizes check for texture value being equal or greater { if (textureDimension >= targetTextureSize) // the texture dimension is greater than the target texture size (i.e., it fits) return targetTextureSize; // return corresponding texture size } while (targetTextureSize >>= 1); // step down to next texture size smaller } return 0; // no textures fit so return zero}// ---------------------------------// returns the nuber of textures need to represent a size of textureDimension given// requirement for power of 2 textures and gMaxTextureSize as the maximum texture size// for the overlap case each texture effectively covers two less pixels so must iterate through using whole statementstatic long GetTextureNumFromTextureDim (long textureDimension, long maxTextureSize, Boolean texturesOverlap, Boolean textureRectangle) { // start at max texture size // loop through each texture size, removing textures in turn which are less than the remaining texture dimension // each texture has 2 pixels of overlap (one on each side) thus effective texture removed is 2 less than texture size long i = 0; // initially no textures long bitValue = maxTextureSize; // start at max texture size long texOverlapx2 = texturesOverlap ? 2 : 0; textureDimension -= texOverlapx2; // ignore texture border since we are using effective texure size (by subtracting 2 from the initial size) if (textureRectangle) { // count number of full textures while (textureDimension > (bitValue - texOverlapx2)) // while our texture dimension is greater than effective texture size (i.e., minus the border) { i++; // count a texture textureDimension -= bitValue - texOverlapx2; // remove effective texture size } // add one partial texture i++; } else { do { while (textureDimension >= (bitValue - texOverlapx2)) // while our texture dimension is greater than effective texture size (i.e., minus the border) { i++; // count a texture textureDimension -= bitValue - texOverlapx2; // remove effective texture size } } while ((bitValue >>= 1) > texOverlapx2); // step down to next texture while we are greater than two (less than 4 can't be used due to 2 pixel overlap) if (textureDimension > 0x0) // if any textureDimension is left there is an error, because we can't texture these small segments and in anycase should not have image pixels left ReportErrorNum ("GetTextureNumFromTextureDim error: Texture to small to draw, should not ever get here, texture size remaining:", textureDimension); } return i; // return textures counted} // ---------------------------------// draws a single texture piece of the image// offset is the start point in the image and end is the end point// all is relative to orginal image size so center around center of image and zoom as requiredstatic void DrawGLImageTile (unsigned long drawType, float imageWidth, float imageHeight, float zoom, float textureWidth, float textureHeight, float offsetX, float offsetY, float endX, float endY, Boolean texturesOverlap, Boolean textureRectangle){ float startXDraw = (offsetX - imageWidth * 0.5f) * zoom; // left edge of poly: offset is in image local coordinates convert to world coordinates float endXDraw = (endX - imageWidth * 0.5f) * zoom; // right edge of poly: offset is in image local coordinates convert to world coordinates float startYDraw = (offsetY - imageHeight * 0.5f) * zoom; // top edge of poly: offset is in image local coordinates convert to world coordinates float endYDraw = (endY - imageHeight * 0.5f) * zoom; // bottom edge of poly: offset is in image local coordinates convert to world coordinates float texOverlap = texturesOverlap ? 1.0f : 0.0f; // size of texture overlap, switch based on whether we are using overlap or not float startXTexCoord = texOverlap / (textureWidth + 2.0f * texOverlap); // texture right edge coordinate (stepped in one pixel for border if required) float endXTexCoord = 1.0f - startXTexCoord; // texture left edge coordinate (stepped in one pixel for border if required) float startYTexCoord = texOverlap / (textureHeight + 2.0f * texOverlap); // texture top edge coordinate (stepped in one pixel for border if required) float endYTexCoord = 1.0f - startYTexCoord; // texture bottom edge coordinate (stepped in one pixel for border if required) if (textureRectangle) { startXTexCoord = texOverlap; // texture right edge coordinate (stepped in one pixel for border if required) endXTexCoord = textureWidth + texOverlap; // texture left edge coordinate (stepped in one pixel for border if required) startYTexCoord = texOverlap; // texture top edge coordinate (stepped in one pixel for border if required) endYTexCoord = textureHeight + texOverlap; // texture bottom edge coordinate (stepped in one pixel for border if required) } if (endX > (imageWidth + 0.5)) // handle odd image sizes, (+0.5 is to ensure there is no fp resolution problem in comparing two fp numbers) { endXDraw = (imageWidth * 0.5f) * zoom; // end should never be past end of image, so set it there if (textureRectangle) endXTexCoord -= 1.0f; else endXTexCoord = 1.0f - 2.0f * startXTexCoord; // for the last texture in odd size images there are two texels of padding so step in 2 } if (endY > (imageHeight + 0.5f)) // handle odd image sizes, (+0.5 is to ensure there is no fp resolution problem in comparing two fp numbers) { endYDraw = (imageHeight * 0.5f) * zoom; // end should never be past end of image, so set it there if (textureRectangle) endYTexCoord -= 1.0f; else endYTexCoord = 1.0f - 2.0f * startYTexCoord; // for the last texture in odd size images there are two texels of padding so step in 2 } glBegin (drawType); // draw either tri strips of line strips (so this will drw either two tris or 3 lines) glTexCoord2f (startXTexCoord, startYTexCoord); // draw upper left in world coordinates glVertex3d (startXDraw, startYDraw, 0.0); glTexCoord2f (endXTexCoord, startYTexCoord); // draw lower left in world coordinates glVertex3d (endXDraw, startYDraw, 0.0); glTexCoord2f (startXTexCoord, endYTexCoord); // draw upper right in world coordinates glVertex3d (startXDraw, endYDraw, 0.0); glTexCoord2f (endXTexCoord, endYTexCoord); // draw lower right in world coordinates glVertex3d (endXDraw, endYDraw, 0.0); glEnd(); // finish strips if (drawType == GL_LINE_STRIP) // draw top and bottom lines which were not draw with above { glBegin (GL_LINES); glVertex3d(startXDraw, endYDraw, 0.0); // top edge glVertex3d(startXDraw, startYDraw, 0.0); glVertex3d(endXDraw, startYDraw, 0.0); // bottom edge glVertex3d(endXDraw, endYDraw, 0.0); glEnd(); }}// ---------------------------------// idle timer to window auto rotation updatespascal void IdleTimer (EventLoopTimerRef inTimer, void* userData){ #pragma unused (inTimer) pRecImage pWindowInfo = NULL; WindowRef window = (WindowRef) userData; if (window) pWindowInfo = (pRecImage) GetWRefCon (window); if (pWindowInfo) DrawGL (window);}// ---------------------------------// builds timer UPPEventLoopTimerUPP GetTimerUPP (void){ static EventLoopTimerUPP sTimerUPP = NULL; if (sTimerUPP == NULL) sTimerUPP = NewEventLoopTimerUPP (IdleTimer); return sTimerUPP;}#pragma mark -// ==================================// public// disposes OpenGL context, and associated texture listOSStatus DisposeGLForWindow (WindowRef window){ if (window) { pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // get gl data stored in refcon SetWRefCon (window, NULL); // ensure the refcon is not used again if (NULL == pWindowInfo) // if this is non-existant return paramErr; // then drop out if (NULL != pWindowInfo->aglContext) { aglSetCurrentContext (pWindowInfo->aglContext); // ensaure the context we are working with is set to current aglUpdateContext (pWindowInfo->aglContext); // ensaure the context we are working with is set to current glFinish (); // ensure all gl commands are complete glDeleteTextures (pWindowInfo->textureX * pWindowInfo->textureY, pWindowInfo->pTextureName); // delete the complete set of textures used for the window DestroyGLFromWindow (&pWindowInfo->aglContext, &pWindowInfo->glInfo); // preoperly destroy GL context and any associated structures pWindowInfo->aglContext = NULL; // ensure we don't use invlad context } if (NULL != pWindowInfo->pTextureName) { DisposePtr ((Ptr) pWindowInfo->pTextureName); // dispose of the allocate4d texture name storage pWindowInfo->pTextureName = NULL; // ensure we do not use it again } if (pWindowInfo->pImageBuffer) // MUST preserve the buffer if texturing from client memory { DisposePtr ((Ptr) pWindowInfo->pImageBuffer); // or image buffer pWindowInfo->pImageBuffer = NULL; } DisposePtr ((Ptr) pWindowInfo); return noErr; // we are good to go } else return paramErr; // NULL window ref passed in}// ---------------------------------// builds the GL context and associated state for the window// loads image into a texture or textures// disposes of GWorld and image buffer when finished loading texturesOSStatus BuildGLForWindow (WindowRef window){ GrafPtr portSave = NULL; // port which is set on entrance to this routine pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // the info structure for the window stored in the refcon short i; // iterator short fNum; // font number GLenum textureTarget = GL_TEXTURE_2D; if (!pWindowInfo->aglContext) // if we get here and do not have a context built, build one { GetPort (&portSave); // save current port SetPort ((GrafPtr) GetWindowPort (window)); // set port to the current window // set parameters for Carbon SetupGL pWindowInfo->glInfo.fAcceleratedMust = false; // must renderer be accelerated? pWindowInfo->glInfo.VRAM = 0 * 1048576; // minimum VRAM (if not zero this is always required) pWindowInfo->glInfo.textureRAM = 0 * 1048576; // minimum texture RAM (if not zero this is always required) if (!CheckMacOSX ()) pWindowInfo->glInfo.fDraggable = false; // is this a draggable window else pWindowInfo->glInfo.fDraggable = true; // is this a draggable window pWindowInfo->glInfo.fmt = 0; // output pixel format i = 0; // first attribute in array pWindowInfo->glInfo.aglAttributes [i++] = AGL_RGBA; // RGB + Alpha pixels pWindowInfo->glInfo.aglAttributes [i++] = AGL_DOUBLEBUFFER; // doble buffered context pWindowInfo->glInfo.aglAttributes [i++] = AGL_ACCELERATED; // require hardware acceleration pWindowInfo->glInfo.aglAttributes [i++] = AGL_NO_RECOVERY; // Mac OS X 10.0.4 has problems with the GL (disregards UNPACK_ROW_LENGTH) resulting from using no recovery // normally we would use no recovery to ensure the minimum pixel size textures are stored by GL. pWindowInfo->glInfo.aglAttributes [i++] = AGL_NONE; // end parameter list BuildGLFromWindow (window, &(pWindowInfo->aglContext), &(pWindowInfo->glInfo), NULL); // build opengl context for our window if (!pWindowInfo->aglContext) // if could not create context DestroyGLFromWindow (&pWindowInfo->aglContext, &pWindowInfo->glInfo); // ensure context is destroyed correctly else // we have a valid context { GLint swap = 0; // swap interval (i.e., VBL sync) setting 1 = sync, 0 = no sync Rect rectPort; // window port rectangle long width = pWindowInfo->imageWidth, height = pWindowInfo->imageHeight; // image width and height GDHandle device; // GDevice to find the constrain the window to Rect deviceRect, availRect, rect; // rect of device which window is on (mostly, area wise at least). avialable area for window (minus dock and menu if req), working rect GetWindowGreatestAreaDevice (window, kWindowContentRgn, &device, &deviceRect); // find device the window is mostly on GetAvailableWindowPositioningBounds (device, &availRect); // get the geretest available area for te windoew (mminus doc and menu if applicable) if (width > (availRect.right - availRect.left)) // adjust window width if it is greater than available area (orginally set to image width, see above) width = (availRect.right - availRect.left); if (height > (availRect.bottom - availRect.top)) // adjust window height if it is greater than available area (orginally set to image width, see above) height = (availRect.bottom - availRect.top); SizeWindow (window, (short) width, (short) height, true); // size the window to new width and height ConstrainWindowToScreen(window, kWindowStructureRgn, kWindowConstrainMayResize, NULL, &rect); // ensure window structure region is on the screen GetWindowPortBounds (window, &rectPort); // get port rect for viewport reset aglSetCurrentContext (pWindowInfo->aglContext); // set our GL context to this one aglUpdateContext (pWindowInfo->aglContext); // update the context to account for the resize InvalWindowRect (window, &rectPort); // inval the entire window to ensure we get a redraw glViewport (0, 0, rectPort.right - rectPort.left, rectPort.bottom - rectPort.top); // reset viewport to entier window area aglSetInteger (pWindowInfo->aglContext, AGL_SWAP_INTERVAL, &swap); // set swap interval to account for vbl syncing or not // set correct texture target #ifdef GL_TEXTURE_RECTANGLE_EXT // if building on 10.0 or 9 this will be undefined if (pWindowInfo->fNPOTTextures) textureTarget = GL_TEXTURE_RECTANGLE_EXT; #endif // Set texture mapping parameters glEnable (textureTarget); // enable texturing glClearColor(0.1f, 0.1f, 0.2f, 1.0f); // set clear color buffer to dark gray glClear (GL_COLOR_BUFFER_BIT); // clear just to color buffer aglSwapBuffers (pWindowInfo->aglContext); // swap the cleared buffer to front GetFNum ("\pMonaco", &fNum); // get font number for named font pWindowInfo->fontList = BuildFontGL (pWindowInfo->aglContext, fNum, normal, 9); // build display list for fonts for this context (see aglString for more info) // if we can use texture rectangle #ifdef GL_TEXTURE_RECTANGLE_EXT // if building on 10.0 or 9 this will be undefined if (pWindowInfo->fNPOTTextures) glEnable(GL_TEXTURE_RECTANGLE_EXT); #endif glPixelStorei (GL_UNPACK_ROW_LENGTH, pWindowInfo->textureWidth); // set image width in groups (pixels), accounts for border this ensures proper image alignment row to row // get number of textures x and y // extract the number of horiz. textures needed to tile image pWindowInfo->textureX = GetTextureNumFromTextureDim (pWindowInfo->textureWidth, pWindowInfo->maxTextureSize, pWindowInfo->fOverlapTextures, pWindowInfo->fNPOTTextures); // extract the number of horiz. textures needed to tile image pWindowInfo->textureY = GetTextureNumFromTextureDim (pWindowInfo->textureHeight, pWindowInfo->maxTextureSize, pWindowInfo->fOverlapTextures, pWindowInfo->fNPOTTextures); pWindowInfo->pTextureName = (GLuint *) NewPtrClear ((long) sizeof (GLuint) * pWindowInfo->textureX * pWindowInfo->textureY); // allocate storage for texture name lists glGenTextures (pWindowInfo->textureX * pWindowInfo->textureY, pWindowInfo->pTextureName); // generate textures names need to support tiling { long x, y, k = 0, offsetY, offsetX = 0, currWidth, currHeight; // texture iterators, texture name iterator, image offsets for tiling, current texture width and height for (x = 0; x < pWindowInfo->textureX; x++) // for all horizontal textures { currWidth = GetNextTextureSize (pWindowInfo->textureWidth - offsetX, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures); // use remaining to determine next texture size // (basically greatest power of 2 which fits into remaining space) offsetY = 0; // reset vertical offest for every column for (y = 0; y < pWindowInfo->textureY; y++) // for all vertical textures { // buffer pointer is at base + rows * row size + columns unsigned char * pBuffer = pWindowInfo->pImageBuffer + offsetY * pWindowInfo->textureWidth * (pWindowInfo->imageDepth >> 3) + offsetX * (pWindowInfo->imageDepth >> 3); currHeight = GetNextTextureSize (pWindowInfo->textureHeight - offsetY, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures); // use remaining to determine next texture size glBindTexture (textureTarget, pWindowInfo->pTextureName[k++]); if (pWindowInfo->fAGPTexturing) glTexParameterf (textureTarget, GL_TEXTURE_PRIORITY, 0.0f); // AGP texturing else glTexParameterf (textureTarget, GL_TEXTURE_PRIORITY, 1.0f); #ifdef GL_UNPACK_CLIENT_STORAGE_APPLE if (pWindowInfo->fClientTextures) glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, 1); else glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, 0); #endif glTexParameteri (textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (textureTarget, GL_TEXTURE_WRAP_S, gpOpenGLCaps->edgeClampParam); glTexParameteri (textureTarget, GL_TEXTURE_WRAP_T, gpOpenGLCaps->edgeClampParam); glReportError (); // report any errors so far glTexImage2D (textureTarget, 0, GL_RGBA, currWidth, currHeight, 0, GL_BGRA_EXT, pWindowInfo->imageDepth == 32 ? GL_UNSIGNED_INT_8_8_8_8_REV : GL_UNSIGNED_SHORT_1_5_5_5_REV, pBuffer); // texture with current width and height at pBuffer location in image buffer with image size as GL_UNPACK_ROW_LENGTH glReportError (); // report any errors offsetY += currHeight - 2 * pWindowInfo->fOverlapTextures; // offset in for the amount of texture used, // since we are overlapping the effective texture used is 2 texels less than texture width } offsetX += currWidth - 2 * pWindowInfo->fOverlapTextures; // offset in for the amount of texture used, // since we are overlapping the effective texture used is 2 texels less than texture width } } if (false == pWindowInfo->fClientTextures) // MUST preserve the buffer if texturing from client memory { DisposePtr ((Ptr) pWindowInfo->pImageBuffer); // or image buffer pWindowInfo->pImageBuffer = NULL; } } SetPort (portSave); //reset port } return noErr; // we done}// ---------------------------------// Handle updating context for window moves and resizingOSStatus ResizeMoveGLWindow (WindowRef window){ OSStatus err = noErr; // no errors to start Rect rectPort; // new port rect if (NULL != window) // if we have a window { pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // get GL info if (NULL != pWindowInfo) // if we have gl info for the window if (!aglUpdateContext (pWindowInfo->aglContext)) // update the context to ensure gl knows about the move or resize aglReportError (); // report any error with update context GetWindowPortBounds (window, &rectPort); // find new bounds err = InvalWindowRect (window, &rectPort); // inval entire bounds to ensure a redraw (which will be superfluous on moves but not a big deal if (noErr != err) ReportErrorNum ("ResizeMoveGLWindow error with InvalWindowRect on window: ", err); // should not get erro here, but who knows } else err = paramErr; // bad window return err; // return any error }// ---------------------------------// resets tracking of mouse drag when wmouse is releasedvoid MouseUpGLWindow (void){ gptDragStart.v = 0; // reset tracking variables to idle state gptDragStart.h = 0; gDragWindow = NULL;}// ---------------------------------// starts tracking of mouse down for drag calculatons// need to record drag window local position of the mouse and whether we are dragging or rotatingvoid MouseDownGLWindow (WindowRef window, Point mousePoint, UInt32 modifiers){ GrafPtr portSave; if (NULL != window) // check for valid window { GetPort (&portSave); // save current port SetPort (GetWindowPort (window)); // set window port (for global to local call) GlobalToLocal (&mousePoint); //convert mouse coordinates to local coordintes prior to recording gptDragStart = mousePoint; // record start point gDragWindow = window; // record window we are dragging in gDragType = kDrag; // default is to drag if (modifiers & cmdKey) // if option key is down gDragType = kRotation; // rotate instead of dragging else if (modifiers & optionKey) gDragType = kZoom; // rotate instead of dragging SetPort (portSave); // reset port }}// ---------------------------------// main working functioning hamdling live drag and rotation// moves center based on mouse delta from last check or rotates image based on nagular chnage of mouse (from image center)void DragGLWindow (Point dragPoint){ GrafPtr portSave; // port to save Rect rectPort; // reactangle for current point float fPi = 3.14159265f; // our PI approximation if (NULL != gDragWindow) // use window as latch for dragging being live { pRecImage pWindowInfo = (pRecImage) GetWRefCon (gDragWindow); // get the gl info from the ref con of the window GetPort (&portSave); // save current port SetPort (GetWindowPort (gDragWindow)); // set port to our drag window GlobalToLocal (&dragPoint); // convert current point to window local (as start point is also window local) if (pWindowInfo) // if we have valid gl info for the window { GetWindowPortBounds (gDragWindow, &rectPort); // get our bounds rect if (gDragType == kDrag) // if we are dragging (as opposed to rotating { pWindowInfo->centerX += dragPoint.h - gptDragStart.h; // just offset the center of the window by the delta (start to current) pWindowInfo->centerY += dragPoint.v - gptDragStart.v; } else if (gDragType == kRotation) // if we are rotating { float imageCenterX = rectPort.left + (rectPort.right - rectPort.left) / 2 + pWindowInfo->centerX; // find the image center relative to port float imageCenterY = rectPort.top + (rectPort.bottom - rectPort.top) / 2 + pWindowInfo->centerY; float deltaX, deltaY; // delta from drag point to image center float angle1, angle2; // angular representation of start and current angles off vertical for mouse points (relative to image center deltaX = imageCenterX - dragPoint.h; // find delta vector current drag point to image center deltaY = imageCenterY - dragPoint.v; if (deltaX == 0.0) // if vector is vertical if (deltaY < 0.0) angle1 = 0.0f; // and Y is negative, the angle is 0 (i.e., pointing up) else angle1 = fPi; // else Y must be zero or poistive so vector in PI radians (i.e., pointing down) else // if X is not 0, thus no disparate case { angle1 = (float) atan (deltaY / deltaX); // the angle (0 to PI / 2) is the arctangent of rise over run (Y / X) if (deltaX < 0.0) angle1 += 1.5 * fPi; // if X is negative then add 3 / 2 PI (270¡) to the angle from above else angle1 += 0.5 * fPi; // otherwise rotate by 1 / 2 PI (90¡) to angle } deltaX = imageCenterX - gptDragStart.h; // find delta vector drag start point to image center deltaY = imageCenterY - gptDragStart.v; if (deltaX == 0.0) // if vector is vertical if (deltaY < 0.0) angle2 = 0.0f; // and Y is negative, the angle is 0 (i.e., pointing up) else angle2 = fPi; // else Y must be zero or poistive so vector in PI radians (i.e., pointing down) else { angle2 = (float) atan (deltaY / deltaX); // the angle (0 to PI / 2) is the arctangent of rise over run (Y / X) if (deltaX < 0.0) angle2 += 1.5 * fPi; // if X is negative then add 3 / 2 PI (270¡) to the angle from above else angle2 += 0.5 * fPi; // otherwise rotate by 1 / 2 PI (90¡) to angle } angle2 -= angle1; // find angle delta (the difference between the start angle and the current angle if (angle2 > fPi) angle2 -= fPi * 2.0; // correct for shortest path if (angle2 < -fPi) angle2 += fPi * 2.0; pWindowInfo->rotation -= angle2 * 180 / fPi; // convert to degrees and increment ratation angle while (pWindowInfo->rotation >= 360.0) pWindowInfo->rotation -= 360.0; // ensure within -360 to 360 while (pWindowInfo->rotation <= -360.0) pWindowInfo->rotation += 360.0; } else if (gDragType == kZoom) // if we are rotating { float zoomDelta = (float)(dragPoint.v - gptDragStart.v) * 0.01f; // just offset the center of the window by the delta (start to current) zoomDelta = 1.0f - zoomDelta; if (zoomDelta < 0.0001f) // prevetns negative zoom values (which would invert the image) zoomDelta = 0.0001f; pWindowInfo->zoom *= zoomDelta; pWindowInfo->centerX *= zoomDelta; pWindowInfo->centerY *= zoomDelta; } gptDragStart = dragPoint; // reset point to the current point so next pass through will work incrementally InvalWindowRect (gDragWindow, &rectPort); // ensure window will be redrawn } SetPort (portSave); // reset port }}// ---------------------------------void StartRotation (WindowRef window){ if (window) { pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // get gl data stored in refcon if (pWindowInfo) { if (pWindowInfo->timer) RemoveEventLoopTimer(pWindowInfo->timer); pWindowInfo->timer = NULL; InstallEventLoopTimer (GetCurrentEventLoop(), 0, pWindowInfo->timerInterval, GetTimerUPP (), (void *) window, &(pWindowInfo->timer)); } }}// ---------------------------------void StopRotation (WindowRef window){ if (window) { pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // get gl data stored in refcon if (pWindowInfo) { if (pWindowInfo->timer) RemoveEventLoopTimer(pWindowInfo->timer); pWindowInfo->timer = NULL; } }}// ---------------------------------// main GL drawing routine, should be valid window passed in (will setupGL if require). Draw image, then grid, then edges, then informationvoid DrawGL (WindowRef window){ Rect rectPort; // rectangle for port pRecImage pWindowInfo; // the gl info for the target window long width, height, yRaster = 1; // width and height or the port and the row of the raster position char cstr [256]; // string to output to screen long effectiveTextureMod = 0; // texture size modification (inset) to account for borders long x, y, k = 0, offsetY, offsetX = 0, currTextureWidth, currTextureHeight; GLenum textureTarget = GL_TEXTURE_2D; if (NULL == window) // if we do not have a window return; // drop out pWindowInfo = (pRecImage) GetWRefCon (window); // get the gl info for the window if (NULL == pWindowInfo) // if this is non-existant return; // then drop out if (NULL == pWindowInfo->aglContext) // try to buld the context if we don't have one (safety check) BuildGLForWindow (window); if (NULL == pWindowInfo->aglContext) // if we still don't have one then drop out return; // adjust timer if (pWindowInfo->spinning) { AbsoluteTime currTime = UpTime (); float frameRate, deltaTime = (float) AbsoluteDeltaToDuration (currTime, pWindowInfo->time); if (0 > deltaTime) // if negative microseconds deltaTime /= -1000000.0; else // else milliseconds deltaTime /= 1000.0; frameRate = (pWindowInfo->frames + 1) / deltaTime; if (frameRate * pWindowInfo->timerInterval > 1.0f) // if timer too slow, increase rate { pWindowInfo->timerInterval *= 0.80; // reduce interval RemoveEventLoopTimer(pWindowInfo->timer); InstallEventLoopTimer (GetCurrentEventLoop(), 0, pWindowInfo->timerInterval, GetTimerUPP (), (void *) window, &(pWindowInfo->timer)); } // spin pWindowInfo->rotation += 1.0; while (pWindowInfo->rotation >= 360.0) pWindowInfo->rotation -= 360.0; // ensure within -360 to 360 while (pWindowInfo->rotation <= -360.0) pWindowInfo->rotation += 360.0; } if (pWindowInfo->fOverlapTextures) effectiveTextureMod = 2; // if we overlap then we need to inset the textures passed to the drawing code // set texture target#ifdef GL_TEXTURE_RECTANGLE_EXT if (pWindowInfo->fNPOTTextures) textureTarget = GL_TEXTURE_RECTANGLE_EXT;#endif aglSetCurrentContext (pWindowInfo->aglContext); // ensaure the context we are working with is set to current aglUpdateContext (pWindowInfo->aglContext); // ensaure the context we are working with is set to current GetWindowPortBounds (window, &rectPort); // get the current port (window) bounds width = rectPort.right - rectPort.left; // find width height = rectPort.bottom - rectPort.top; // and height glViewport (0, 0, width, height); // set the viewport to cover entire window glMatrixMode (GL_PROJECTION); // set projection matrix glLoadIdentity (); // to indetity glMatrixMode (GL_MODELVIEW); // set modelview matrix glLoadIdentity (); // to identity glReportError (); // report any GL errors so far // set the model view matrix for an orthographic view scaled to one screen pixel equal image pixel (independent of image zoom) glScalef (2.0f / width, -2.0f / height, 1.0f); // scale to port per pixel scale glTranslatef (pWindowInfo->centerX, pWindowInfo->centerY, 0.0f); // translate for image movement glRotatef (pWindowInfo->rotation, 0.0f, 0.0f, 1.0f); // ratate matrix for image rotation glReportError (); // report any GL errors glClear (GL_COLOR_BUFFER_BIT); // clear the color buffer before drawing // draw image glEnable (textureTarget); // enable texturing glColor3f (1.0f, 1.0f, 1.0f); // white polygons // offset x and y are used to draw the polygon and need to represent the texture effective edges (without borders) // so walk the texture size images adjusting for each border for (x = 0; x < pWindowInfo->textureX; x++) // for all horizontal textures { // use remaining to determine next texture size currTextureWidth = GetNextTextureSize (pWindowInfo->textureWidth - offsetX, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures) - effectiveTextureMod; // current effective texture width for drawing offsetY = 0; // start at top for (y = 0; y < pWindowInfo->textureY; y++) // for a complete column { // use remaining to determine next texture size currTextureHeight = GetNextTextureSize (pWindowInfo->textureHeight - offsetY, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures) - effectiveTextureMod; // effective texture height for drawing glBindTexture(textureTarget, pWindowInfo->pTextureName[k++]); // work through textures in same order as stored, setting each texture name as current in turn glReportError (); // report any errors DrawGLImageTile (GL_TRIANGLE_STRIP, pWindowInfo->imageWidth, pWindowInfo->imageHeight, pWindowInfo->zoom, currTextureWidth, currTextureHeight, // draw this single texture on two tris offsetX, offsetY, pWindowInfo->fTileTextures ? currTextureWidth + offsetX : pWindowInfo->imageWidth, pWindowInfo->fTileTextures ? currTextureHeight + offsetY : pWindowInfo->imageHeight, pWindowInfo->fOverlapTextures, pWindowInfo->fNPOTTextures); glReportError (); // report any errors offsetY += currTextureHeight; // offset drawing position for next texture vertically } offsetX += currTextureWidth; // offset drawing position for next texture horizontally } glReportError (); // report any errors glDisable (textureTarget); // done with texturing // draw texel grid glColor3f (0.0f, 0.0f, 1.0f); // draw texel grid in blue if (pWindowInfo->grid) // if drawing is on { long vertMod = effectiveTextureMod; // find the current mod to get to the effective texture size long horizMod = effectiveTextureMod; if (pWindowInfo->fTileTextures) // if we are tiling we have to account for odd size images { // if the image size is odd then we know that we had to add an extra border pixel // account for this when drawing thegrid to ensure we draw the right amount of texels vertMod += (pWindowInfo->imageHeight & 0x01) ? 1 : 0; horizMod += (pWindowInfo->imageWidth & 0x01) ? 1 : 0; } // draw grid showing the actual texels draw to the screen each frame DrawGLTexelGrid (pWindowInfo->textureWidth - horizMod, pWindowInfo->textureHeight - vertMod, pWindowInfo->imageWidth, pWindowInfo->imageHeight, pWindowInfo->zoom); } glReportError (); // report any errors // draw polygon edges glColor3f (0.0f, 1.0f, 0.0f); // draw in green for polygon edges if (pWindowInfo->lines) // if edges turned on { // offset x and y are used to draw the polygon and need to represent the texture effective edges (without borders) // so walk the texture size images adjusting for each border offsetX = 0; for (x = 0; x < pWindowInfo->textureX; x++) // for all horizontal textures { // use remaining to determine next texture size currTextureWidth = GetNextTextureSize (pWindowInfo->textureWidth - offsetX, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures) - effectiveTextureMod; // current effective texture width for drawing offsetY = 0; // start at top for (y = 0; y < pWindowInfo->textureY; y++) // for a complete column { // use remaining to determine next texture size currTextureHeight = GetNextTextureSize (pWindowInfo->textureHeight - offsetY, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures) - effectiveTextureMod; // effective texture height for drawing DrawGLImageTile (GL_LINE_STRIP, pWindowInfo->imageWidth, pWindowInfo->imageHeight, pWindowInfo->zoom, currTextureWidth, currTextureHeight, // draw this single texture on two tris offsetX, offsetY, pWindowInfo->fTileTextures ? currTextureWidth + offsetX : pWindowInfo->imageWidth, pWindowInfo->fTileTextures ? currTextureHeight + offsetY : pWindowInfo->imageHeight, pWindowInfo->fOverlapTextures, pWindowInfo->fNPOTTextures); offsetY += currTextureHeight; // offset drawing position for next texture vertically } offsetX += currTextureWidth; // offset drawing position for next texture horizontally } } glReportError (); // report any errors // draw info if (pWindowInfo->info) // if we are drawing the information overlay { glLoadIdentity (); // reset model view matrix to identity (eliminates rotation basically) glScalef (2.0f / width, -2.0f / height, 1.0f); // scale to port per pixel scale glTranslatef (-(width) / 2.0f, -(height) / 2.0f, 0.0f); // translate center to upper left glColor3f (1.0f, 1.0f, 0.0f);// draw in yellow // center tick glBegin (GL_LINES); // draw center tick mark glVertex3f(width / 2.0f - 4.5f, height / 2.0f, 0.0f); glVertex3f(width / 2.0f + 4.5f, height / 2.0f, 0.0f); glVertex3f(width / 2.0f, height / 2.0f - 4.5f, 0.0f); glVertex3f(width / 2.0f, height / 2.0f + 4.5f, 0.0f); glEnd(); glRasterPos3d (10, yRaster++ * 12, 0); // set raster postion of bottom of text, incrementing for next line sprintf (cstr, "Image: (%ld x %ld x %ld)", pWindowInfo->imageWidth, pWindowInfo->imageHeight, pWindowInfo->imageDepth); DrawCStringGL (cstr, pWindowInfo->fontList); // draw image size and depth glRasterPos3d (10, yRaster++ * 12, 0); // set raster postion of bottom of text, incrementing for next line sprintf (cstr, "Textures: (%ld x %ld) Texels: (%ld x %ld)", pWindowInfo->textureX, pWindowInfo->textureY, pWindowInfo->textureWidth, pWindowInfo->textureHeight); DrawCStringGL (cstr, pWindowInfo->fontList); // draw texture info (1 x 1 with X texels for single texture code, X x Y for Z texels for tiled code if (pWindowInfo->fOverlapTextures) DrawCStringGL (" -overlapped-" , pWindowInfo->fontList); glRasterPos3d (10, yRaster++ * 12, 0); // set raster postion of bottom of text, incrementing for next line sprintf (cstr, "Window: (%ld x %ld)", width, height); DrawCStringGL (cstr, pWindowInfo->fontList); // draw window size glRasterPos3d (10, yRaster++ * 12, 0); // set raster postion of bottom of text, incrementing for next line sprintf (cstr, "Position: (%0.1f, %0.1f) at %0.1f deg", pWindowInfo->centerX / pWindowInfo->zoom, pWindowInfo->centerY / pWindowInfo->zoom, pWindowInfo->rotation); DrawCStringGL (cstr, pWindowInfo->fontList); // draw position information glRasterPos3d (10, yRaster++ * 12, 0); // set raster postion or bottom of text, incrementing for next line sprintf (cstr, "Zoom: %0.2f", pWindowInfo->zoom); DrawCStringGL (cstr, pWindowInfo->fontList); // draw zoom level yRaster = (height - 1) / 12; glRasterPos3d (10, yRaster-- * 12, 0); // set raster postion of bottom of text, incrementing for next line DrawCStringGL ((char*) glGetString (GL_RENDERER), pWindowInfo->fontList); // drag renderer string DrawCStringGL (", ", pWindowInfo->fontList); // drag version string DrawCStringGL ((char*) glGetString (GL_VERSION), pWindowInfo->fontList); // drag version string if (pWindowInfo->fClientTextures || pWindowInfo->fAGPTexturing) { glRasterPos3d (10, yRaster-- * 12, 0); // set raster postion of bottom of text, incrementing for next line if (pWindowInfo->fClientTextures) DrawCStringGL ("<Client Storage> ", pWindowInfo->fontList); // draw zoom level if (pWindowInfo->fAGPTexturing) DrawCStringGL ("<AGP Texturing Hint>", pWindowInfo->fontList); // draw zoom level } // print frames per second and texturing rate if (pWindowInfo->spinning) { AbsoluteTime currTime = UpTime (); float deltaTime = (float) AbsoluteDeltaToDuration (currTime, pWindowInfo->time); if (0 > deltaTime) // if negative microseconds deltaTime /= -1000000.0; else // else milliseconds deltaTime /= 1000.0; (pWindowInfo->frames)++; if (0.5 <= deltaTime) // has update interval passed { double rate = pWindowInfo->frames / deltaTime; sprintf (pWindowInfo->cstrTime, "%0.0f FPS (%ld frames in %0.3f secs)", rate, pWindowInfo->frames, deltaTime); pWindowInfo->time = currTime; // reset for next time interval pWindowInfo->frames = 0; } glRasterPos3d (10, yRaster-- * 12, 0); // set raster postion or bottom of text, incrementing for next line DrawCStringGL (pWindowInfo->cstrTime, pWindowInfo->fontList); } glReportError (); } aglSwapBuffers (pWindowInfo->aglContext);}</pre>
<!--googleoff: index -->
</td>
</tr>
</table>
<!-- END WIDE COLUMN -->
<!-- END MAIN CONTENT -->
<table width="680" border="0" cellpadding="0" cellspacing="0">
<tr>
<td><div style="width: 100%; height: 1px; background-color: #919699; margin-top: 5px; margin-bottom: 15px"></div></td>
</tr>
<tr>
<td align="center"><br/>
<table border="0" cellpadding="0" cellspacing="0" class="graybox">
<tr>
<th>Did this document help you?</th>
</tr>
<tr>
<td>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=1&url=/samplecode/OpenGL_Image/listing7.html%3Fid%3DDTS10000538-1.0&media=dvd" target=_new>Yes</a>: Tell us what works for you.</div>
<div style="margin-bottom: 8px"><a href="http://developer.apple.com/feedback/?v=2&url=/samplecode/OpenGL_Image/listing7.html%3Fid%3DDTS10000538-1.0&media=dvd" target=_new>It’s good, but:</a> Report typos, inaccuracies, and so forth.</div>
<div><a href="http://developer.apple.com/feedback/?v=3&url=/samplecode/OpenGL_Image/listing7.html%3Fid%3DDTS10000538-1.0&media=dvd" target=_new>It wasn’t helpful</a>: Tell us what would have helped.</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- START BOTTOM APPLE NAVIGATION -->
<!--#include virtual="/includes/footer"-->
<!-- END BOTTOM APPLE NAVIGATION -->
<!-- START CENTER CLOSE -->
</center>
<!-- END CENTER CLOSE -->
</body>
</html>