Home
OpenGL Programming on Mac OS X
Contents
1. AGL_VIRTUAL _SCREI E Z 100 Chapter 7 The AGL API for OpenGL Configuration Token Description AGL_REMOTE_PBUFFER Specifies that the renderer can render to an off line pixel buffer Type Boolean n a Default n a Policy n a AGL_NONE Token to signal the end of the pixel format parameter array Every pixel format attribute list for AGL must end with this token Type n a n a Default n a Policy n a The final piece of code we perform after our main loop has exited is to clean up our context and return Using AGL can be as simple as that If you re coding along with this example your application should be essentially complete and ready to run If you ve fol lowed this discussion successfully you ll see results as in Figure 7 2 completely covering your display There s a lot more to discuss so let s move on to our next example which in volves a windowed pixel format and event loop Windowed Application If you re writing example code in an application like we ve talked you through in the previous section create another XCode project and populate it with headers initialization methods and draw methods as seen before in Example 7 1 and Example 7 2 All of those pieces of code will remain exactly the same and the only differences are how we choose our pixel format bind it to the Ca
2. B Q Search java lang Object NSCursor A NSApplication NSBox NSObject NSDictionary P v NSDrawer NSClipView NSDocument Nsview B NsCon gt NSDocumentController NSWindow gt NSFontManager NSWindowController NSFormatter gt NSProgressindicator NSImage NSQuickDrawView NSMenu NSRulerView NSMenultem NSMovie NSResponder NSTableHeaderView NSSound NSTabView NSTableColumn NSText NSTabViewltem A WebView SCNibObjectinfo J SCNibObjectinfoManage n M I Figure 8 2 Subclassing NSOpenGLVi ew in Interface Builder Open the Resources folder and double click on the MainMenu nib icon This will open the nib file for this project in Interface Builder Now switch to Interface Builder In the MainMenu nib window click on the Classes tab and navigate through the three pane system until you finally click on NSOpenGLView The panes should look like Figure 8 2 when selected Next click on the Classes menu and Subclass NSOpenGLVi ew item to cre ate a new derived class based on the NSOpenGLView type A new text entry field will appear suggesting the name MyOpenGLView Accept the default name by pressing the Enter key or choose something more interesting and type away Your results should look similar to Figure 8 3 So what did we just do We told Interface Builder that we wanted to sub class NSOpenGLView for our own purposes NSOpenGLView is derived from the NSView class It provides the integration between
3. 132 Subclassing NSOpenGLView in Interface Builder 134 Subclassed NSOpenGLVi ew in Interface Builder 135 MyView Binding in Interface Builder 135 Context Sharing Two Windows and Two Custom NSOpenGLViews in Interface Builder sue 143 XV Figure 8 13 Figure 8 14 Figure 8 15 Figure 8 16 Figure 9 1 Figure 9 2 Figure 9 3 Figure 9 4 Figure 9 5 Figure 9 6 Figure 10 1 Figure 10 2 Figure 10 3 Figure 10 4 Figure 11 1 Figure 11 2 Figure 11 3 Figure 11 4 Figure 11 5 Figure 11 6 Figure 11 7 Figure 11 8 Figure 11 9 Figure 11 10 Figure 11 11 Figure 11 12 xvi Figures Context Sharing Two Custom NSOpenGLViews in XCode sici isse tem hea temere nada rag eher bees Context Sharing Set Visible on Launch for Second WiIndOWssirrersriris tirrr inr e ema e renean Context Sharing Two Windows Demonstrating Common Shared Data and Unshared Clear Color Context Data Results of Rendering to an FBO and Texturing a Quad with That Result GLUT API and Framework in the Overall OpenGL Infrastructure on the Mac 0 cece sence ence eters New Project Creation for GLUT Application Adding a Framework to This Project 06 00085 Resultant GLUT Project Showing Framework and Sample Code GLUT Project Results Showing Visual Selection and Rendered Object GLUT Project Results Showing Visual Selection and Rendered Object
4. Cocoa drawRect Routine for Copy to Texture Rendering GLUT Header Inclusion on the Mac ssssussn Basic GLUT Sample Application Initializing a GLUT Visual Using a String Two Sample NSImage Initialization Methods Initialize NSImages Resizing an NSImage to a Power of Two Extracting a Bitmap from an NSI Initialization and Creation of an NSImage Downloading an NSImage as an OpenGL Texture Capturing OpenGL Data as an NSImage Converting a Bitmap to an NSImage 0 08 Initialize OTMOVie ccc cece eee nee nn Draw Rectangle Method Applying Movie Frames Querying Shader Limits Enabling or Disabling the Multithreaded GL Engine Partial Buffer Object Flushing 0 eee Immediate Mode Vertex Submission Begin End Immediate Mode Vertex Submission Vertex Arrays Immediate Mode Vertex Submission Vertex Buffer Objects Inefficiencies of Not Using Vertex Array Objects Using Vertex Array Objects Using Vertex Array Range Apple Fence Extension Double Buffering Vertex Data Using the APPLE_vertex_array_range Extension Example 12 1 Example 13 1 Example 13 2 Example 13 3 Example 13 4 Example 13 5 Example 13 6 Example 13 7 Example 13 8 Example 13 9 Example 13 10 Example 13 11 Example 13 12 Example 13 13 Example C 1 Example C 2 Example C 3 Example C 4 Example C 5 Example C 6 Example C 7 Example C 8 Example C 9
5. glClearColor 0 5 8 1 glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT glMatrixMode GL MODELVIEW glLoadIdentity glRotatef myAngle 0 0 1 glTranslatef 0 0 1 gicolor3f 0 1 0 glBegin GL QUADS float ww 9 float hh 9 glTexCoord2f 0 0 glVertex3f ww hh 0 glTexCoord2f 1 0 glVertex3f ww hh 0 glTexCoord2f 1 1 glVertex3 ww hh 0 glTexCoord2f 0 1 glVertex3f ww hh 0 glEnd glutSwapBuffers void angleUpdate int delay float twopi 2 M_PI myTime myTime gt twopi 0 myTime 03 myAngle sinf twopi myTime glutTimerFunc delay angleUpdate delay glutPostRedisplay int main int argc char argv glutInit amp argc argv choose a visual and create a window glutInitDisplayString stencil 2 rgb8 double depth 16 168 Chapter 9 The GLUT API for OpenGL Configuration this is comparable to glutInitDisplayMode with the tokens below and achieves a similar effect glutInitDisplayMode GLUT RGB GLUT DOUBLE GLUT DEPTH glutInitWindowSize 450 300 glutCreateWindow GLUT Configuration Example initialize prepareOpenGL our opengl context is now valid 0 register callback functions int delay 50 glutTimerFunc delay angleUpdate delay glutDisplayFunc draw glutMainLoop GLUT is a good way to bring up a rendering window quickly an
6. Additional Topics 149 display capture is a very easy task but entails strict ordering of the tasks Essen tially the process proceeds as follows 1 Capture the display 2 Configure and display a full screen window 3 Handle events 4 Release the display It s important to ensure that both event handling and teardown or display release occur If they do not you ll probably get into a deadlock of some sort one in which either you can t do anything with your application or other ap plications move to the foreground respectively You re almost guaranteed to experience this problem once unless you re really listening to me here and you ll never repeat the mistake rebooting in the middle of your development cycle is a pretty good deterrent The specifics of display capture and release are sketched out in Example C 8 Please read Apple s developer documentation on the methods described here for additional information Because these methods are so fundamentally simple we will just show you the code and have you use it without further discussion Example 8 8 Capturing and Releasing the Display Captures all displays returning true false for success failure xy bool capturedDisplaysLoop bool error false CGDisplayErr err CGCaptureAllDisplays if err CGDisplayNoErr failure maybe another application is already fullscreen error true else your code here open fullscreen win
7. But we digress Apple has been willing to change binary formats and host plat form many times over the years but only most recently with the change to Intel hasatrue multiplatform binary been possible A regular native PowerPC appli cation can now run on an Intel processor through an emulation layer known as Rosetta Rosetta essentially translates PowerPC code into Intel code at runtime and only with relatively high performance modern CPUs has it been possible to do this at runtime The details behind this code translation layer aren t im portant but suffice it to say that the performance of application running under Rosetta isn t nearly as good as the performance of a natively compiled applica tion It s good to be sure even remarkably good but for performance critical applications and a typical OpenGL application is native code is the only way to go We ll have more to say on this later Beginning with 10 4 4 Apple developers no longer have the luxury as with prior versions of 10 X of assuming that they re running on a PowerPC Mac OS Versions 247 chip the possibility exists that an application may be running on either chip Developers must account for this possibility because it affects many things among them endianness vector code acceleration and inline assembly tweaks Primarily however it impacts performance 10 5 and Beyond Apple has announced its next revision in the Mac OS X sequence 10 5 also known
8. Number of depth bits Type Unsigned integer n a Default n a Policy Closest AGL STENCIL SIZE Number of stencil bits Type Unsigned integer n a Default n a Policy Greater than or equal to value AGL ACCUM RI ED SIZE Number of red accum bits Type Unsigned integer n a Default n a Policy Closest 96 Chapter 7 The AGL API for OpenGL Configuration Token Description AGL_ACCUM_GREEN_SIZE Number of green accum bits Type Unsigned integer n a Default n a Policy Closest AGL_ACCUM_BLUE_SIZE Number of blue accum bits Type Unsigned integer n a Default n a Policy Closest AGL ACCUM ALPHA SIZI B Number of alpha accum bits Type Unsigned integer Value Default Default Policy AGL CLOSEST POLICY AGL PIXEL SIZE Framebuffer bits per pixel including unused bits ignoring alpha buffer bits Type Unsigned integer n a Default n a Policy n a AGL MINIMUM POLICY Never choose smaller buffers than the type and size requested Type Boolean n a Default GL FALSE Policy n a AGL MAXIMUM POLICY Choose largest buffers of type and size requested Alters default policy for color depth and accumulation buffers Type Token n a Default n a
9. Policy n a AGL CLOSEST POLICY Find the pixel format most closely matching the specified size Alters default policy and size for color buffers Type Unsigned integer n a Default n a Policy Closest match Continued Pixel Format and Context 97 Table 7 2 Pixel Format Specifiers for Use with aglChoosePixelFormat Continued Token Description AGL OFFSCREEN Choose an off screen renderer Type Token n a Default n a Policy Closest match AGL_FULLSCREI tj z Choose a full screen renderer Type Token n a Default n a Policy n a AGL SAMPLI E BUFFERS ARB Number of multisample buffers Type Unsigned integer n a Default n a Policy n a AGL SAMPLES ARB Number of samples per multisample buffer Type Unsigned integer n a Default n a Policy n a AGL AUX DEPTH ST ENCIL Specify number of depth or stencil buffers for the aux buffer Type Unsigned integer n a Default n a Policy n a AGL COLOR FLOAT Select pixel buffers with color buffers that store floating point pixels Type n a n a Default n a Policy n a AGL_MULTISAMPLI TET Select pixel formats with multisample buffers Type n a n a Default n a Policy Hint prefer AGL SUP ERSAMPL
10. Type Boolean GL TRUE Default GL FALSE Policy If GL TRUE search only among double buffered pixel formats else search only single buffered pixel formats AGL STEREO Select stereo pixel formats Type Boolean GL_TRUE Default GL FALSE Policy If GL TRUE search only among stereo pixel formats else search only monoscopic pixel formats Continued Pixel Format and Context 95 Table 7 2 Pixel Format Specifiers for Use with aglChoosePixelFormat Continued Token Description AGL AUX BUFFI t n Number of aux buffers Type Unsigned integer 0 specifies no aux buffers Default n a Policy Greater than or equal to value AGL RED SIZ Number of red component bits Type Unsigned integer 0 if AGL RGBA is GL FALSI DI Default n a Policy Closest AGL_GREEN_SIZE Number of green component bits Type Unsigned integer 0 if AGL_RGBA is GL FALSI Lj Default n a Policy Closest AGL BLUE SIZE Number of blue component bits Type Unsigned integer 0 if AGL RGBA is GL FALSI Lj Default n a Policy Closest AGL ALPHA SIZE Number of alpha component bits Type Unsigned integer 0 if AGL_RGBA is GL FALSI Lj Default n a Policy Closest AGL DEPTH SIZE
11. glEnd pairs calling individual vertices in between however you will see less benefit or worse your application may be slightly slower when using the threaded engine If your application rather than being CPU bound is entirely GPU limited say from fill constraints as in a volume rendering application you will see little if any benefit from the threaded engine The simple litmus test for these conditions is to run a typical scene or model through your OpenGL application and watch the graph from Apple s CPU monitoring application Activity Monitor If the CPUs are busy when rendering this scene chances are very good that your application might benefit from enabling the multiprocessor capable OpenGL engine The threaded OpenGL engine can be dynamically enabled per context from CGL AGL or Cocoa applications The enabling is dynamic in the sense that you OpenGL for Mac OS X Rules of Thumb for Performance 203 don t have to specify a parameter at context creation time to enable it Rather you can turn the threaded engine on and off as often as you wish That said turning the multithreaded engine on or off should be done judi ciously Consider all of the state management thread management and mutex management that accompanies a switch from rendering on a single threaded basis to rendering with two threads In short it s expensive performance wise to turn the threaded engine on or off We recommended you switch it on or of
12. stayInFullScreenMode YES while stayInFullScreenMode NSAutoreleasePool pool NSAutoreleasePool alloc init Check for and process input events NSEvent event while event NSApp nextEventMatchingMask NSAnyEventMask untilDate NSDate distantPast inMode NSDefaultRunLoopMode dequeue YES switch event typel tMouseDown mouseDown event case NSLe break ftMouseUp mouseUp event case NSLe Fh H break ftMouseDragged mouseDragged event case NSLe Fh H break case NSKeyDown unichar cc event charactersIgnoringModifiers characterAtIndex 0 switch cc case 27 escape key stayInFullScreenMode NO break default break break default break The basic idea is that while in full screen mode no external UI controls Cocoa or other exist that have natural event handling mechanisms so you need to do Additional Topics 311 whatever your application requires when an event occurs This includes mouse handling key handling and external device e g joystick tablet handling Example C 9 does nothing more than simply handle the Escape key quit the render loop and return to windowed mode The example deals specifically with key events handling the Escape key by quitting full screen mode and calling out to other methods not shown for handling mouse events This structure and code should be enough of
13. Efficient Handling of Vertex Data 217 define VERTICES 1024 Define number of bytes for vertex data in our hypothetical model GLint MODEL BYTES vertex count 3 one for x y amp z sizeof GLfloat define MODEL BYTES VERTICES 3 sizeof GLfloat Pointer to our vertex data buffer GLfloat vertexData Drawing fence for coherency GLuint drawingFencel drawingFence2 Typical init routine for setting up double buffering VAR void InitVAR t Multiply MODEL BYTES by 2 to double buffer GLint totalBytes MODEL BYTES 2 Create 2 duplicate sets of vertex data arranged sequentially in memory We ll have both copies of our model stored in this one buffer vertexData GLfloat malloc totalBytes InitModelData is a hypothetical routine to initialize our model data Initialize first copy of vertex data InitModelData MODEL BYTES vertexData Initialize second copy of vertex data offset 1 2 way into the vertexData buffer InitModelData MODEL BYTES vertexData MODEL BYTES sizeof GLfloat Our data is dynamic so specify the memory is SHARED AGP mapped glVertexArrayParameteriAPPLE GL_VERTEX_ARRAY_STORAGE_HINT_APPLE GL STORAGE SHARED APPLE Configure the VAR glEnableClientState GL VERTEX ARRAY glEnableClientState GL VERTEX ARRAY RANGE APPLE glVertexPointer 3 GL FLOAT 0 vertexData glVertexArrayRange
14. Example C 10 Example C 11 Example C 12 Example C 13 Example C 14 Example C 15 Example C 16 Unpack the OS X Version Number 0005 249 Querying for Extensions in a Valid OpenGL Context 261 Querying the OpenGL Version Number 262 Querying for OpenGL Shader Extensions 263 Creating a Dictionary of All Extensions 264 Storage for the Discovered Symbols 266 Opening a Segment for Symbol Lookup 267 Looking Up Symbols sssssssssseeeeeeees 267 Our Application s OpenGL Initialization Code 267 GLEW Head ers ex esr einni eenn E aaa A LER e with 271 Our Application s OpenGL Initialization Code Usine GUE Wai sit ian gino he aaa aah E ate 271 Query for Shader Extensions Using GLEW 273 Query for OpenGL Version Information Using GLUT 274 Query for Shader Extensions Using GLUT 274 Configuration of an OpenGL View in initWithFrame 288 Cocoa drawRect Rendering Method with Sample OpenGL Content cs cca tisigridictce tonsa pices sen nunen ae cute 293 MyView h Final Header 0 cece cece eee eens 296 MyView m Final Code ees eere ke innn 296 Singleton Class Declaration for Managing a Shared Context ek ofc neat RENE OT wr ERE AS 303 Singleton Class Implementation for Managing a Shared Cone eenst ernennen DS RDeczi laine we 305 Initialization of an OpenGL Vie
15. Policy Closest NSOpenGLPFAAlphaSize Unsigned integer The value specified is the number of alpha buffer bits required Default If no value is specified pixel formats discovered may or may not have an alpha buffer Selection policy Pixel formats that most closely match this size are preferred 290 Appendix C The Cocoa API for OpenGL Configuration in Leopard Token Description NSOpenGLPFADepthSize Unsigned integer The value specified is the number of depth buffer bits required Default If no value is specified pixel formats discovered may or may not have a depth buffer Selection policy Pixel formats that most closely match this size are preferred NSOpenGLPFAStencilSize Unsigned integer The value specified is the number of stencil planes required Selection policy The smallest stencil buffer of at least the specified size is preferred NSOpenGLPFAAccumSize Unsigned integer The value specified is the number of accumulation buffer bits required Selection policy An accumulation buffer that most closely matches the specified size is preferred NSOpenGLPFAMinimumPolicy YES Change to the selection policy described Selection policy Consider only buffers greater than or equal to each specified size of the color depth and accumulation buffers NSOpenGLPFAMaximumPolicy YES Change to the selection policy described Selection
16. ing state commands until it becomes necessary to send them across the system bus to the graphics hardware The graphics hardware will then respond to the commands by changing its rendering state uploading or downloading data to system memory or rendering to the display The driver also performs caching of recently used data manages data flow for cached data e g display lists ver tex buffers and textures and essentially does all the talking to and from the hardware As an application writer it is important that you understand the basic func tions of the driver layer when you are tuning performance or on occasion sub mitting bug reports When using diagnostic tools from the CHUD framework discussed in detail later you may see functions show up in a trace that are clearly reminiscent of a particular type of graphics hardware We ll discuss and interpret traces into the OpenGL drivers in Chapter 11 Summary The software architecture of OpenGL on Mac OS X reflects both the history and the future of OpenGL as well as the diverse and ever changing Mac hardware platform itself From the dispatch table down to the device specific driver modules a basic un derstanding of the logical modules of the OpenGL implementation on Mac OS X is the key to efficient usage of the software architecture as a whole Under standing these software modules and their interactions will aid you in debug ging and allow you to make the most effective choi
17. orglReadPixels to be slow may have the same effect on your texture upload performance Recall that the internal format parameter of a g1 TexlImage call is a format request That means the implementation will try to honor it but does not have to Ultimately the request will be honored if the graphics hardware natively supports the requested format Note however that the fact that the graph ics hardware natively supports an internal format does not mean the texture upload performance for the requested internal format will be fast It may undergo an expensive CPU transformation to go from the format type to the native internal format Compressed Textures Graphics hardware from both ATI and NVIDIA supports S3TC compressed types natively but not compression of other formats into these S3TC types in hardware If you specify a compressed internal format along with an uncom pressed external format your texture data will undergo compression on the CPU before it is handed off to the GPU The Mac OS texture compressor offers very high performance at least 60MB s per CPU core on modern Mac systems Although this is a very high num ber it is not comparable to the realizable upload bandwidth of PCI Express which exceeds 2GB s If the cited numbers satisfy your texture upload per formance requirements you re free to use OpenGL to compress your textures on upload If not it is advisable to pre compress your textures and use the
18. specifically how to include and build with GLUT This concludes our coverage of GLUT on Mac OS X We now return you to your regularly scheduled Mac OS X OpenGL programming Summary 171 This page intentionally left blank Chapter 10 API Interoperability Overview This chapter will cover a variety of topics related to using some of the powerful and cool APIs on the Mac with your OpenGL application You might be won dering what we really mean when we say interoperability in the chapter title Perhaps a better term might be interfacing We re going to explore how you get data from other APIs other subsystems and other data formats you have and use into your OpenGL application on the Mac That description though general is vague so let s consider a concrete example of how this might be useful You want to play a video in a scene So how do you play a video It s conceptually simple you open a sequence of images and draw them as textures on an object But how do you open images How do you ensure that regardless of the frame rate used you still see your movie in real time This example is probably not wholly unfamiliar to anyone in computing as we ve all walked down that path from time to time And as we get older and ideally wiser it becomes more apparent that using someone else s expertise and API in these subjects makes a lot of sense Here we ll focus on using Apple s expertise in image loading media
19. taining their encouragement throughout my life Finally thanks to my cats for keeping me warm grounded and focused on the essentials of life food sleep and play XXix This page intentionally left blank About the Authors Bob Kuehne is a graphics consultant and entrepreneur and currently works as the head of a graphics consultancy Blue Newt Software Blue Newt works with clients around the world to enhance their 3D graphics applications Blue Newt helps clients move from fixed function programming to shader appli cations from single to multi pipe multi display systems and from baseline OpenGL to scenegraphs as their needs change Bob spends most of his time in modern OpenGL working with clients to design new applications develop new features and do performance engineering Before Blue Newt Bob worked for nearly eight years at SGI in a variety of roles His work included leading the OpenGL Shader project creating demos for high end multi pipe graphics systems and helping SGI developers create high performance high quality applications Bob has worked in the graphics industry and with graphics systems for more than two decades and has been developing in OpenGL since it first existed He has been a developer on the Mac since the early 1990s when he was finally able to afford one Bob has presented at numerous conferences over his career in cluding SIGGRAPH Graphic Hardware SGI Developer Forum Worldwide and the ex confe
20. CGL OpenGL CoreGraphics Figure 7 1 AGL Software Dependencies 90 Chapter 7 The AGL API for OpenGL Configuration Table 7 1 Locations of AGL Headers and Frameworks Framework path System Library Frameworks AGL framework Build flag framework AGL Header include lt AGL agl h gt With the fundamentals of AGL now described and the locations in which to fully explore the framework identified let s move directly into pixel format and context configuration Pixel Format and Context As we ve discussed in earlier chapters of this book the layer of glue between your OpenGL code and the window system of your application performs two key tasks pixel format selection and OpenGL context creation The name for that layer in this chapter at least is AGL The pixel formats describe attributes per pixel of your OpenGL rendering destination and the context binds that pixel format to your window system drawable To review a drawable is an object such as a window pixel buffer framebuffer object or other graphics target used in OpenGL rendering In this chapter we ll examine the APIs for basic pixel format selection and cre ation We ll explain all the enumerants used to specify the pixel format and the functions necessary to configure them and create contexts using those pixel formats The overview of how to use AGL to create the relevant glue code for rendering should be familiar In
21. IBindTexture GL TEXTURE 2D textureID IEnable GL TEXTURE 2D lBegin GL QUADS loat ww 9 loat hh 9 loat zz 0 0 lTexCoord2f 0 0 lVertex3f ww hh zz ITexCoord2f 1 0 lVertex3f ww hh zz lTexCoord2f 1 1 lVertex3f ww hh zz lTexCoord2f 0 1 lVertex3f ww hh zz LEnd Q Q Q Q Q Q Q Q 0 b Fh Fr Q I Q 0 giClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT So what does our example do Our goal is to render a textured quad to the screen where the texture represents an intermediate rendered result We begin by configuring our FBO and texture so that they refer to each other In the ren der loop we make the FBO active clear to yellow and then unbind the FBO Because of the magic of FBOs those results are now usable as a texture so we render a textured quad to the screen When we set up the texture environment parameters for texturing we specified GL REPLACI E to wholly replace any color on the quad with the texture image If everything works as we ve described and it does we should see the final rendered ima ge as shown in Figure 8 16 Alternative Rendering Destinations 157 Figure 8 16 Results of Rendering to an FBO and Texturing a Quad with That Result Texture Courtesy of NASA s Earth Observatory You can do a lot more with FBOs including capturing other rendering results such as depth stencil and other render targets but
22. Mac OS 10 4 NSOpenGLPFAMultisample YES Consider only renderers capable of using supersample anti aliasing NSOpenGLPFASampleBuf fers and NSOpenGLPFASamp les also need to be set Mac OS 10 4 NSOpenGLPFAAuxDepthStencil If present searches for pixel formats for each AuxBuffer that has its own depth stencil buffer NSOpenGLPFARendererID Unsigned integer ID of renderer Selection policy Prefer renderers that match the specified ID Refer to CGLRenderers h for possible values NSOpenGLPFAAccelerated YES Modify the selection policy to search for pixel formats only among hardware accelerated renderers NO default Search all renderers but adhere to the selection policy specified Selection policy Prefer accelerated renderers NSOpenGLPFAClosestPolicy YES Modify the selection policy for the color buffer to choose the closest color buffer size preferentially This policy will not take into account the color buffer size of the current graphics devices NO default No modification to selection policy NSOpenGLPFABackingStore YES Constrain the search of pixel formats to consider only renderers that have a back color buffer that is both the full size of the drawable and guaranteed to be valid after a call to a buffer flush NO default No modification to the pixel buffer search NSOpenGLPFAWindow YES default Search only among renderers that are capable o
23. OpenGL CGLMacros h Even easier you can leave CGL MACRO CONTEXT undefined and use the default CGL context name cg1 ctx CGL macros can make a profound difference in the performance of your ap plication Generally speaking the more immediate mode rendering you do the bigger the improvement produced by using CGL macros To be formulaic about it the larger the ratio of OpenGL function calls your application makes relative to the amount of data referenced by those calls the bigger your performance gains will be using CGL macros This of course doesn t mean we re advocat ing the use of immediate mode rendering for the sake of big gains with CGL macros You re much better off keeping your data in VRAM by doing as much retained mode rendering as you possibly can Summary Whether you use CGL AGL or Cocoa for your OpenGL application on the Mac having at least some knowledge of CGL will improve your understand ing of the higher level windowing system interfaces to OpenGL on OS X CGL derived functions data types and constants make many appearances in both the AGL and AppKit APIs Therefore if you keep in mind that this in formation is derived you may be able to find the more detailed documenta tion you re looking for by examining the CGL analog to whatever it is you re investigating 86 Chapter 6 The CGL API for OpenGL Configuration For example try reading the AGL reference guide segment on ag1ChoosePix elFormat and t
24. Putting It All Together 237 triangle to the screen we re hoping to guide you through an environment that is a closer match to real world performance tuning Please Tune Me goes heavy on texturing and geometry to give it some real world weight Here s some pseudocode describing this application e Create a color gradient texture for the textured quad mesh referenced below e Clear the entire application window with alpha set to 0 0 e For some number of iterations do Set the viewport to the left half of the application window Draw a randomly placed quad with an alpha value of 1 0 Draw a textured quad mesh such that it fills the entire viewport Use blending to discard all fragments from the mesh rendering that do not lie within a previously drawn quad where the framebuffer alpha is now 1 0 Set the viewport to the right half of the application window Source the left half of the window random quads mesh as a texture For all remaining texels of this texture that are still black Apply a gray color ramp to the texture Draw a teapot using texgen to apply the texture As the application runs the teapot goes from gray to a patchwork of textured regions and gray to fully textured A snapshot of this application can be seen in Figure 11 12 Please Tune Me 1 Let s get started with ptm1 c Compiling and running this example on our test system we get less than 7 a frame per second performance L
25. SOpenGLPFAClosestPolicy 131t 292t SOpenGLPFAColorFloat 131t 292t SOpenGLPFAColorSize 129t 290t SOpenGLPFADepthSize 130t 291t SOpenGLPFADoubleBuffer 129t 290t SOpenGLPFAFullScreen 130t 291t SOpenGLPFAllRenderers 129t 290t SOpenGLPFAMaximumPolicy 130t 291t SOpenGLPFAMinimumPolicy 130t 291t SOpenGLPFAMultisample 131t 292t SOpenGLPFAOffScreen 130t 291t SOpenGLPFAPixelBuffer 131t 292t SOpenGLPFARendererID 131t 292t SOpenGLPFASampleBuffers 130t 291t SOpenGLPFASamples 131t 292t SOpenGLPFAStencilSize 130t 291t SOpenGLPFAStereo 129t 290t SOpenGLPFAWindow 131t 292t SOpenGLPixelFormat 129t 290t 131t 292t NSOpenGLView 122 33 123f 124f 125f 126f 284 93 NSSlider 221 NSView 133 40 134f 135f 294 300 Oo object oriented programming and state management 197 98 Objective C 89 121 off screen drawables 82 off screen rendering 161 62 321 22 off screen surfaces 109 10 OpenGL advantages of 3 4 as specification document 8 debugging 39 41 feature support 14 15 graphics tools 228 36 229f 230f 232f 233f 234f 235f 236f 237f history of 7 8 9f platform identification 248 49 249t OpenGL Driver Monitor 235 36 235f 236f OpenGL Profiler 228 34 229f 230f 232f 233f 234f 235f OS 9 2 OS requirements 27 28 OS version identification 249 51 OS X see also Cheetah Jaguar Leopard Panther Puma 10 0 through 10 1 245 46 filesystem 38 implementation of OpenGL specifica
26. ServicePropertyStateChange n break case kIOMessageCanDevicePowerOff printf CanDevicePowerOff n break case kIOMessageDeviceWillPowerOff printf DeviceWillPowerOff n break case kIOMessageDeviceWillNotPowerOff printf DeviceWillNotPowerOff n break case kIOMessageDeviceHasPoweredOn printf DeviceHasPoweredOn n break case kIOMessageCanSystemPowerOff printf CanSystemPowerOff n break case kIOMessageSystemWillPowerOff printf SystemWillPowerOff n break case kIOMessageSystemWillNotPowerOff printf SystemWillNotPowerOff n break case kIOMessageSystemWillNotSleep printf SystemWillNotSleep n break case kIOMessageSystemHasPoweredOn printf SystemHasPoweredOn n break case kIOMessageSystemWillRestart printf SystemWillRestart n break case klIOMessageSystemWillPowerOn printf SystemWillPowerOn n break default IOAllowPowerChange root port long messageArgument printf messageType 081x arg 081x n long unsigned int messageType long unsigned int messageArgument 36 Chapter 4 Application Programming on OS X int main int argc char argv t IONotificationPortRef notify io object t anIterator float x 5 81 root port IORegisterForSystemPower amp x amp notify callback amp anIterator if root port 0 printf IORegisterForSystemPower failed n return 1 CFRunLoopAddSource CFRunLoopGetCu
27. Similarly when Cocoa arrived classes and data structures were developed again on top of CGL to provide Cocoa applications with an OpenGL interface Thus CGL lies at the heart of the window system interfaces to OpenGL on OS X and in fact is part of the OpenGL framework Because of this you might think that like the foundation of other layered APIs like Xlib or perhaps Win32 CGL can do all that the higher layers can do and more albeit with more effort on the part of the software engineer This is mostly true with one important exception Only full screen or off screen OpenGL applications can be written using exclu sively CGL For windowed applications the AGL or Cocoa interface to OpenGL is required 55 OpenGL Application CGL GLEngineO GLEngine1 GLEngineO ATI Driver SW Renderer NV Driver ATI Hardware O Q NY Hardware Figure 6 1 CGL Renderer Selection Because CGL lies beneath both AGL and the Cocoa interface to OpenGL you can freely use CGL in combination with either an AGL application or a Co coa application CGL may also be freely used with GLUT applications be cause the OS X GLUT implementation relies on Cocoa which in turn relies on CGL The only invalid combination of these four interfaces is to use the AGL or Carbon interface to OpenGL in combination with the Cocoa interface to OpenGL Generally speaking you will find that both AGL and Cocoa provide enough
28. This type is essentially meant for high streaming performance to the graphics device for video feeds The very latest and highest performance discrete graphics chips will handle 4 component 32 bit single precision floating point pixels or texels throughout the pipeline without costly conversions Pixel Pipeline and Imaging Subset State In addition to the state involved with formats and types the performance of pixel data throughput will greatly be affected by any pixel transform state that is enabled in the OpenGL pixel pipeline The OpenGL 1 0 specification in combination with the imaging subset state yields numerous stages in the pixel pipeline for applying scales biases lookups color matrices convolutions and so on If these non default states are enabled your pixel upload performance Efficient Handling of Texture Data 223 will very likely suffer simply because these states are rarely used and therefore are not represented in the silicon of the graphics hardware installed on the sys tems As a result these stages take the pixel upload off the fast path and require modification by the CPU Alignment Considerations It is quite important on any modern CPU architecture to pay attention to pixel data alignment Alignment is such an important consideration that in the opinion of the authors it more often than not usurps video memory usage as a primary performance consideration The most common mi
29. and AppKit Layered with OpenGL 16 The Mac OS OpenGL Plugin Architecture 18 Prototypical System Architecture Diagram 24 Threading Layer Cake Thread Packages on Top of POSIX on Top of Mach Threads 0 00 00s 42 OpenGL Configuration API Dependencies 50 Frame butter Strata occ nesc4eenesseewe nth ECERODEECE ERU VES 54 CGL Renderer Selection 0 cece cece e eee eee ee eee 56 AGL Software Dependencies rirani tidie 90 AGL Full Screen Example Results 0 0 00005 102 AGL Window Example Results 0 000 cee eee ee 105 AGL Pbuffer Example Results 0 00 0 e cece eee 113 AGL Render to Texture Example Results 116 Results of Rendering to a Framebuffer Object and Texturing a Quad with That Result in AGL 119 AppKit API and Framework in Overall OpenGL Infrastructure on the Mac 06 c ccc cence teen ees 122 Subclassing NSOpenGLView in Interface Builder 123 Subclassed NSOpenGLVi ew in Interface Builder 124 Instantiated OpenGL View Object in Interface Builder 124 Custom View Palette in Interface Builder 125 Adding a Custom View to a Window in Interface Builder 125 Binding a Custom View to the NSOpenGLView Subclass Object oiv eee ees oerte hr rite etse beer tira 126 Teapot Rendered with NSOpenGLView Subclass
30. and calling out to other methods not shown for handling mouse events This structure and code should be enough of a basis for you to get started If you need more detail we provide a more comprehensive example on our website www macopenglbook com Alternative Rendering Destinations In the following sections we ll explore what it takes to render an intermediate image for use later in your application You ll probably already know if this is something you re interested in If not let s discuss a case or two in which you might need to render intermediate results One example in which intermediate rendering results are useful is for render ing of reflections Suppose you ve got a scene with some watery bits and some shiny bits in it Picture a rainy street scene with puddles and a car The pud dles would reflect the buildings across the street and those shiny rims would reflect the buildings behind the viewer To reflect something on those wheels and puddles we have two options One is to use a fake scene to create the reflections and the other is to use the real scene Obviously the real scene is the better option so we ll need to generate a view of the scene that contains 152 Chapter 8 The Cocoa API for OpenGL Configuration the images to be reflected This would be the image that we d render in our intermediate buffer In another example we might want to render the same view of the street scene but perhaps after the view
31. examples include QuickTime full screen movie presentation iPhoto Finder slideshows DVD playback and FrontRow set top display The most common example of this technique in user software is found in games usually where a game takes over the display for a complete and unobstructed experience of slay ing dragons flying through canyons at Mach 0 8 or conquering the galaxy A rule of thumb to decide when full screen rendering is needed is this Any time you want to present a completely custom user interface full screen applications are one way to go In this section we ll first tackle some plumbing details neces sary to render full screen OpenGL surfaces and then demonstrate how to create and use a full screen OpenGL area Display Capture One major reason for using a full screen area is to coherently display some con tent without the distraction of other UI elements A key element of this experi ence would be blocking interruption by other applications while in this mode Apple provides hooks to allow an application to essentially take over the dis play preventing other applications from presenting their content over the top This behavior is known as display capture Display capture exists at the Core Graphics level of graphics typically a 2D layer and is not part of our discussion in this book Nonetheless the ability to capture the display is a useful albeit not required element of a full screen application even in Cocoa Performing
32. front buffer is done by calling Drawables 77 CGLError CGLFlushDrawable CGLContextObj ctx CGLFlushDrawable causes an implicit flush of the OpenGL command stream The results of all previously submitted OpenGL commands are then executed and reflected in the back buffer prior to it being copied to the front buffer As with most OpenGL implementations performing complex application logic immediately following a call to swap buffers is a good way to take advantage of the latency inherent in the swap The Mac OpenGL implementation has the ad ditional flexibility of specifying a swap interval Read the details of the context parameter kCGLCPSwapInterval on page 66 for more information on how the swap interval affects the timing of the buffer swap Now let s discuss each of three drawable types in more detail Pixel Buffers Pixel buffers pbuffers are accelerated off screen rendering drawables that are defined in many OpenGL configuration APIs like CGL These buffers exist be cause drawables for any OpenGL implementation have been resource man aged by the window system This put them outside the realm of core OpenGL Aside from being a destination for rendering CGL pbuffers can be used as a source for texturing Combine these two aspects and you have the ability to render to textures which is useful in many graphics applications More so than textures of equivalent size pbuffers are large resources and should be managed wit
33. graphics hardware purpose This caveat is important primarily because of the issues we discussed regarding bandwidth to and from the graphics hardware back in Chapter 3 For the purposes of our discussions here we assume that you do have a good reason for dragging pixels from the graphics hardware to main memory That said the major phases of this process are as follows 1 Read the pixel data from OpenGL 2 Create an NSBi tmapImageRep from that data 3 Create an NSImage from the NSBitmapImageRep In fact in the space it took to describe these steps we practically could have coded the entire process So without further ado let s look at some code The code in Example 10 7 does all three of the previously described steps and provides a physical validation of the process by writing the data to a file Example 10 7 Capturing OpenGL Data as an NSImage NSImage captureGraphicsAsImage NSRect imageArea create a bitmap image rep with allocated space to contain our pixels NSBitmapImageRep bitmap NSBitmapImageRep alloc initWithBitmapDataPlanes NULL pixelsWide imageArea size width pixelsHigh imageArea size height bitsPerSample 8 samplesPerPixel 3 hasAlpha NO isPlanar NO NO interleaved colorSpaceName NSDeviceRGBColorSpace bytesPerRow 0 bitsPerPixel 0 182 Chapter 10 API Interoperability ask the gl for the pixels storing them in our bitmap image glPixelStorei GL UN
34. rendering the main scene The results are seen in Figure 7 5 Alternative Rendering Destinations 115 000 AGL Window Figure 7 5 AGL Render to Texture Example Results One quick note We must invoke this code in this order if we want to achieve the proper results This is a key step and perhaps obvious but Example 7 11 makes clear that you must first set up the texture then draw contents into it and finally draw the main scene Example 7 11 AGL Copy Texture Render Call Sequence opengl setup and render initGLstate drawTexture draw There s really not much else to this technique Essentially you render two scenes and copy the contents of one for use as a texture by the other That ba sic idea is the premise behind all of these techniques but rarely is there as little configuration as in Example 7 11 We ve now finished our discussion of how to perform textured renders from the contents of a texture filled by another render The technique is very portable but carries some overhead concerning texture and window sizes and has some 116 Chapter 7 The AGL API for OpenGL Configuration performance limitations based on the underlying OpenGL operations This technique is a capable fallback for when framebuffer objects are not available Framebuffer Objects In this section we describe a modern and widely available technique for in termediate renders using framebuffer objects The interfaces to framebuffer obj
35. this performance hiccup could show up as a sudden drop in frame rate causing the faithful customer to get picked off by the rail gun of his or her arch nemisis Wherever possible you should attempt to group your state changes and es tablish a rendering mode Once this mode or grouping of related states is established draw with as much data as possible before changing modes This means drawing with like primitives like colors like textures and so on in as large a chunk as possible before you make state changes Object Oriented Programming and State Management While we re on the subject of minimizing state changes we d like to point out a common conflict of design interest between OpenGL and object oriented programming OOP methodology We believe strongly in the power of object oriented design for applications but unless it is applied to OpenGL program ming judiciously you can run into trouble Consider the primary goal of any OOP methodology encapsulation That is the goal is to put data and the operations that operate on that data in a common locale and to restrict the interface to data so as to avoid debugging hassles Keeping this goal in mind let s consider an example We ve decided to write an application for landscape design For our landscape design program suppose we have an object defined for trees and another object defined for leaves Our leaf class knows how to draw a single oak leaf consisting of 10 v
36. to successfully enable sharing What makes pixel formats incompatible On the Mac usually it s one thing incompatible renderers As a rule of thumb if you can choose pixel formats that use the same renderers you can share contexts created with those pixel formats Additional Topics 141 So we ve covered the how and why of sharing a context but what exactly is shared when context sharing is enabled Interestingly enough most OpenGL objects are shared but the overall context state is not That s not entirely intu itive but it correlates well with what people usually want to do You save valu able card memory by reusing heavyweight objects in multiple spots but still preserve the ability to customize each OpenGL view as needed Specifically the following entities are shared Display lists Vertex array objects VAOs Buffer objects VBOs PBOs Texture objects Vertex and fragment programs and shaders Frame buffer objects FBOs e e e e e e Now that we have an overview of how context sharing works let s walk through some code For purposes of this example we will build a two windowed version of our earlier Cocoa example in which we created a custom context In this case we ll modify the example to share the context between the two views and surfaces render some shared data a display list and visualize the data in two views each with a different color background color The plan is to demonstrate what is and wha
37. void prepareOpenGL t glMatrixMode GL PROJECTION glLoadIdentity glOrtho 1 1 1 1 1 100 NSURL url NSURL URLWithString Q http www yosemite org vryos turtlebackl jpg NSImage url image NSImage alloc initWithContentsOfURL url Cocoa Image NSImage 179 NSImage file_image NSImage alloc initWithContentsOfFile System Library Screen Savers Cosmos slideSaver Contents Resources Cosmos07 jpg resize our image to a power of 2 NSImage file_image_resized self transformImage url image toSize NSMakeSize 512 512 download an image as a texture self downloadImageAsTexture file image resized configure texture environment glTexEnvf GL TEXTURE ENV GL TEXTURE ENV MODE GL REPLACE glEnable GL TEXTURE 2D add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES We ve extended the initial example to accomplish three further tasks The first task is resizing the image using the method we developed earlier The second task is downloading the resultant scaled NSImage We ll develop the body of that method in a moment The final task is configuration of texturing in our OpenGL context to enable it and to have the texture color replace the color of the object to which it s applied The real meat of this section deals wi
38. you should use whichever API best meets your application s needs However many of the examples later in this book do express a prefer ence and are written in Objective C Cocoa Quite frankly it s the best UI toolkit out there and it s really fun to write applications using it Let s begin by reviewing the high level concepts involved for all flavors of OpenGL APIs on the Mac 45 API Introductions and Overview The Mac has a rich history of 2D and 3D graphics and the sheer number of API choices for drawing bears this out Despite the many choices available these APIs differ both in design and implementation so it s not too difficult to determine which is right for you This section discusses each API specif ically with the idea in mind that you ll be integrating it into an application That means the choices among these APIs largely revolve around how well they will integrate with the rest of your application in general and your windowing system in particular OpenGL is used consistently among these APIs and the standard OpenGL API is how you ll be rendering graphics data But when considering OpenGL setup configuration and window management the vari ous APIs differ dramatically We ll begin by looking at each API and discussing the applicability of each and then dig into the details in later chapters Mac Only APIs Four key APIs for 3D graphics are available only on the Mac Quartz Services Core OpenGL CGL
39. 13 14 hardware vs software renderers 19 history of Mac platform 2 l idle time minimization 204 7 image manipulation 140 41 imaging subset state 223 24 immediate mode rendering 198 200 immediate mode vertex submission 211 12 implicit data copies 29 instance method 146 47 intermediate rendering 152 53 321 22 IOKit 37 38 IrisGL 3 8 J Jaguar see also OS X improvements of 246 release of 17t renderer support 12t VRAM requirements in 31 K Kilgard Mark 163 L Launch Settings menu 228 29 229f Leopard see also OS X Cocoa API on 283 322 improvements of 248 Quartz in 31 release of 17t renderer support 13t threaded engine on 202 328 Index M Mac platform advantages of 3 development on 2 3 hardware 7 history of 2 user experience 2 Mach threads 41 macros in CGL 86 medical imaging limitations 27 memory requirements 31 32 video 30 31 memory bandwidth limit 25 memory bus 29 metrics 207 9 Movie Toolbox 189 90 multisampling 10t 61 multithreaded engine 202 4 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N extStep 2 northbridge of CPU 23 24 24f SImage 174 84 178f 179t SMovie 185 SOpenGLPFA Accelerated 131t 292t SOpenGLPFA AccumSize 130t 291t SOpenGLPFAAlphaSize 129t 290t SOpenGLPFA AuxBuffers 129t 290t SOpenGLPFAAuxDepthStencil 131t 292t SOpenGLPFABackingStore 131t 292t
40. 208 framebuffer objects 117 19 153 58 158f 313 18 framebuffer to texture copy 9t framebuffers 53 54 54f framework locations 50t full screen application in AGL 91 101 full screen drawables 82 83 full screen surfaces 149 308 9 function call overhead 204 G gaming limitations 27 GL_EXTENSIONS 249t GL_RENDERER 249t GL_TRIANGLE_STRIP 211 GL_VENDOR 249t GL_VERSION 249t GLARB_non_power of_two 176 GLEW 270 73 glFinishFenceAPPLE 217 global state functions in CGL 84 86 glReadPixels 241 42 242f glTextImage2D 197 GLUT 16 16f 48 and extension management 273 75 configuration of 165 70 history of 163 overview of 164 164f pixel format in 167 70 167f 169t 170t window management in 169 169t GLUT_ACCUM 169t GLUT_ALPHA 169t GLUT_DEPTH 169t GLUT_DOUBLE 169t GLUT MULTISAMPLE 169t GLUT_RGB 169t GLUT_RGBA 169t GLUT SINGLE 169t GLUT STENCIL 169t GLUT STEREO 169t glutInitDisplayString 170 170t glVertexArrayParameteri APPLE 216 GLX 51 Index 327 GPU see graphics processing unit GPU graphics bus 29 30 30t graphics device support 7 graphics processing unit GPU bandwidth limits with CPU 25 idle time minimization 204 7 increasing role of 23 information lookup 34 transistors in 23 graphics tools 228 36 229f 230f 232f 233f 234f 235f 236f 237f H hardware and data flow 24 32 image download to 180 82 on Mac platform 7 renderer support 12t 13t
41. Apple OpenGL AGL and Cocoa OpenGL NSGL If you re starting with a blank sheet of paper and writing an application from the ground up for the Mac one of these APIs is where you ll want to focus your energy for integrating OpenGL Architecturally both Cocoa OpenGL and AGL are layered on top of CGL For applications that require more comprehensive access to the underlying infrastructure direct access is always possible from either Cocoa or AGL Quartz Services Quartz Services is part of the Core Graphics framework It succeeds the Mac intosh Display Manager and convention associated with DrawSprocket The Quartz Services API controls systemwide parameters for configuring the dis play hardware on a Macintosh computer You may be interested in setting the following parameters from your OpenGL application e Refresh rate e Resolution e Pixel depth e Display capture e Gamma setting display fades Quartz Services also provides services for applications that do remote operation of OS X We won t cover this topic in our book 46 Chapter 5 OpenGL Configuration and Integration In short this API provides the functionality needed for your OpenGL applica tion to communicate with the Macintosh Quartz Window Server Core OpenGL CGL is the foundation layer of the Quartz windowing system interface to the OpenGL API As with most foundation layer APIs CGL allows the greatest amount of flexibility and control over how your OpenGL ap
42. Figure 11 1 Vertex Submission Example Application that works natively with the pixel format The video acquisition of YCBCR formatted data is a good example Another is high fidelity single component pixel data used for medical imaging In Mac OS X there are about two dozen pixel types more than a dozen pixel formats can be specified for OpenGL Consider the architecture of OpenGL on the Mac OS with regard to handling pixel data The Mac OS implementation provides an abstraction layer over mul tiple types of graphics hardware each with its own capacity for handling var ious types of pixel data If an application requests a pixel format type pairing that cannot be handled natively by the graphics hardware the hardware driver will make a request of the Mac OS OpenGL layer to convert the pixel data from the requested format into the hardware s native format 222 Chapter 11 Performance Depending on your application s performance needs this can be a very expen sive operation indeed Imagine that you re uploading a stream of pixel data to the graphics card but instead of free flowing at close to PCI express limits be tween system memory and graphics device it stops to perform a format type transformation on the way there At best you ve introduced a memcpy of the pixel data into your pixel path At worst the conversion is a very expensive one and is costly just from a CPU time perspective Determining which effective path you r
43. For dynamic data you can use the parameter GL STORAGE SHARED APPLE rather than GL STORAGE CACHED APPLE This powerful configuration instructs the GPU to fetch vertex data directly from your application making no interme diate copies along the way In any case using VAR requires more smarts that regular vertex array semantics The VAR extension requires that you tell OpenGL when you re modifying data and when you re finished with it Unlike glFlush glFlushVertexArrayRangeAPPLE simply marks a region of memory as modified or dirty in driver speak To guarantee coherency of the data you must use either the Apple Fence extension which will likely work its way into the OpenGL core in the future or a more heavy club handed way of guarantee ing coherency by calling g1Finish Using Apple Fence is quite simple Example 11 10 shows the use of fences with Apple Vertex Array Range Example 11 10 Apple Fence Extension GLuint drawCompleteFence void init glEnableClientState GL VERTEX ARRAY glEnableClientState GL VERTEX ARRAY RANGE APPLE glVertexArrayRangeAPPLE allocSize vtxCoordArray glGenFencesAPPLE 1 amp drawCompleteFence H void draw 216 Chapter 11 Performance for i 0 i lt vtxCt i stripCt glDrawArrays GL TRIANGLE STRIP i stripCt Set a fence here so that when we modify the data later we can verify that drawing with this data has completed glSe
44. IDs are the same between the contexts data sharing will be successful If your application has multiple contexts it is more likely that you will also have multiple threads If so remember to bracket your OpenGL calls in each thread with calls to CGLLockContext and CGLUnlockContext to prevent state collisions Drawables Depending on which company representative you speak to which conference you re attending the context of the meeting you re in or perhaps even the time of day or the weather different people in 3D graphics frequently use different terms for pretty much the same thing One graphics concept that has many names is the memory and state used and established as a destination for render ing In some places it s referred to as a drawable while in others a surface or perhaps a framebuffer CGL refers to this rendering destination as a drawable There are three recognized types of drawables in CGL pbuffers off screen buffers and full screen buffers The most fundamental operation for drawables is associating them with a CGL context which establishes the desti nation for rendering for OpenGL commands issued when that context is current These association functions are CGLSet PBuf fer CGLSetOffscreen and CGLSetFullscreen Removing the drawable association with a context is done with a call to CGLError CGLClearDrawable CGLContextObj ctx For double buffered drawables swapping the contents of the back buffer to the
45. NSClipView NSOpenGLView NSControl NSMovieView Figure 8 12 Context Sharing Two Windows and Two Custom NSOpenGLViews in Interface Builder eoo cocoa 2win contextshare c Aye is Debug 3 x Y No rN S Qy String Ma Active Target Active Build Configuration Action Build Build and Run Build and Debug Tasks Search gt Groups amp Files ll Code o A o COCOa 2win contextshare B G Appkit framework B P Classes 4 W Cocoa framework vi Other Sources a cocoa_2win_contextshare app a cocoa 2win contextshare Prefix i cocoa 2win contextshare Prefix jM main m K CoreData framework a jM OneOpenGLView m K Foundation framework n 4j OneOpenGLView h Info plist a iA penGLView h InfoPlist strings English im MyOpenGLView m M main m yY 4 gt 2 Resources Ej MainMenu nib English v Frameworks M MyOpenGLView h rf Linked Frameworks I MyOpenGLView m v w 2 Other Frameworks A OneOpenGLView h gt amp OpenGL framework Mj OneOpenGLView m y m gt Kx AppKit framework K OpenGL framework a gt G amp CoreData framework gt x Foundation framework a Products b Targets L gt 4 Executables M Figure 8 13 Context Sharing Two Custom NSOpenGLViews in XCode present it here and then discuss a bit more after presentation The header code lives in Example C 5 and the source code is found in Example C 6 Example 8 5 Singleton Class Declaration for Managing a Shar
46. NSView getting at the guts of how contexts are created and then do some rendering If you need precise management of a context this is the way to do it in a Cocoa application We ll end up exactly where we did before with a cozy teapot on a calming blue back ground We ll also begin where we did last time as well in XCode Launch it and we ll get started We begin with the big picture an overview of where we re going in this sec tion If you d like to try to do this chunk on your own before the walkthrough we encourage you to apply what we did in the last section to create a custom view This time however we ll create our subclass based on NSView Here are the steps 1 Create a subclass of NSView named MyView 2 Create the files for this class NSView 133 3 Create an instance of this class in MainMenu nib 4 Write code in XCode to create a custom pixel format and context 5 Write code to create the teapot and handle the OpenGL initialization We won t say any more about how to accomplish the XCode project setup and configuration at this point but rather will leave you to try to figure it out on your own The walkthrough here will take you through all the details if you d prefer to try it this way Create a new XCode project of type Cocoa Application This action will cre ate your project set it to link properly against the Cocoa frameworks and create a sample main program from which we ll begin If you don t feel li
47. OpenGL Profiler Buffer View OpenGL Driver Monitor The OpenGL Driver Monitor is used to monitor various parameters of the graphics devices available on your Mac Figure 11 10 To use this tool first choose a driver from the Monitors menu Driver Monitors submenu Next click OOO Scripts c a Save As Text Open Script Name glColorgf 1 0f 0 0f 0 0f setColorRed oec Execute Figure 11 9 OpenGL Profiler Scripts View Graphics Tools 235 ATIRadeonX1000GLDriver 3 Log ie 0 Ha 1G P h e Save As Text Clear Log Linear Min Max P 0 f Graph Table Scale amp 100 Pause Color Show Driver Monitor Parameter a Current Max END Buffer Swaps 21 147 v CPU Wait for GPU 253 1047585 ns EN gt Current Free Video Memory 91220032 92008160 b v Current Mapped AGP Memory 14061568 19517440 b a v OpenGL Contexts 9 9 Action Clear Max Values Parameters Figure 11 10 OpenGL Driver Monitor the Parameters button at the bottom right corner of the main window You ll see a long list of anything you could want to know about data traffic resource allocations and various other parameters of the driver One parameter of partic ular interest is CPU Wait for GPU which tells you whether your application is GPU bound and your application is stalled waiting for a response Driver Monitor also allows you to check the video memory currently available Pixie Pixie is a tool that magnifies a
48. OpenGL and Cocoa By subclassing it we become able to customize many aspects of its behavior in cluding pixel format selection and context sharing But we re getting ahead of ourselves First we ve got to get MyOpenGLView into a form where we can write some code We ll now use Interface Builder to instantiate a default object when the nib file is loaded create some sample code and arrange our view in the window First let s create an instance of our class Return to the MainMenu nib win dow where you should still have MyOpenGLView selected If not navigate through the hierarchy to re select it With MyOpenGLView selected click on the Classes menu and Instantiate MyOpenGLView item This will create an NSOpenGLView 123 eoo 1 MainMenu nib Instances GClasses Images Sounds Nib Q Search java lang Object NSCursor A NSApplication NSBox NSObject NSDictionary P vw NSDrawer NSClipView NSDocument f NSView B NSControl gt NSDocumentController NSWindow gt NSMovieView NSFontManager NSWindowController NSOpenGLView gt NSFormatter Ld NSProgressIndicator NSImage NSQuickDrawView NSMenu NSRulerView NSMenultem NSScrollView NSMovie NSSplitView NSResponder NSTableHeaderView NSSound NSTabView NSTableColumn NSText NSTabViewltem A WebView SCNibObjectinfo E u SCNibObjectinfoManage i 1 1 Figure 8 3 Subclassed NSOpenGLVi ew in Interface Builder instance of this class in the nib and
49. Rendering Support CGLPixelFormatAttribute attribs kCGLPFAFullScreen kCGLPFARendererID kCGLRendererGeForce3ID 0 Qu CGLPixelFormatObj pixelFormat long matchingPixelFormatsCount CGLChoosePixelFormat attribs amp pixelFormat amp matchingPixelFormatsCount Test for matching pixel formats 82 Chapter 6 The CGL API for OpenGL Configuration if pixelFormat NULL kCGLRendererGeForce3ID does NOT support full screen rendering else kCGLRendererGeForce3ID supports full screen rendering Example 6 3 is rigged because we know that kCGLRendererGeForce3 ID sup ports full screen rendering so this test should never fail Of course you could substitute your renderer of interest in this example Testing for support of any full screen renderers is a simple matter of removing the kCGLPFARenderer ID attribute and its value kCGLRendererGeForce3ID from the attribute list This leaves only the full screen attribute kCGLPFAFullScreen Assuming your context was created with a renderer that supports full screen rendering a call to CGLError CGLSetFullScreen CGLContextObj ctx will establish the associated full screen drawable as the destination for rendering Virtual Screen Management A virtual screen remember is the pairing of a hardware renderer and the physical displays that are driven by that renderer In Mac laptop comput ers for example the graphics hardware is represented b
50. SSE is found on the web as part of its overall developer tools 13 Both resources will help you understand the commands and their usage 44 Chapter 4 Application Programming on OS X Chapter 5 OpenGL Configuration and Integration This chapter explores in detail how to configure the necessary infrastructure to begin drawing with OpenGL Specifically it describes use of the various Macin tosh APIs to window systems and off screen render areas and it examines how to configure each API for the type of OpenGL data you plan to render If you ve jumped to this chapter to get details on a particular API skip the introduction and dig right in If you ve arrived here wondering which API is right for you you ll probably want to read the overview first to learn about the differences among the many windowing APIs to OpenGL on Mac OS X The OpenGL configuration APIs presented here are classified into two groups Mac specific APIs and cross platform APIs supported on the Mac Although there are many interfaces to the window system and OpenGL configuration all APIs function using the same core ideas and ultimately run on the same drivers In essence each of these interfaces uses the same concepts for its configuration though the details and capabilities of each are different We begin with the Mac specific APIs presented roughly in order of moder nity from most to least modern This is by no means a sorting meant to im ply preference
51. Time usec GLTime App Time glEvalMesh2 23 603 4996242 211 68 40 59 35 17 CGLFlushDrawable 739 4274451 5784 10 34 73 30 09 glReadPixels 738 2004254 2715 79 16 28 14 11 glUnmapBuffer 738 516350 699 66 4 20 3 64 glCallList 738 193398 262 06 1 57 1 36 glTexlmage2D 2 122039 61019 65 0 99 0 86 giBitmap 7 370 39555 5 37 0 32 0 28 glEndList 1 35017 35017 38 0 28 0 25 7 Total elapsed GL function time 12308002 95 usec Estimated time in GL 86 65 Show slice 25 of 25 gt Context ID All Contexts E Figure 11 17 ptm5 OpenGL Statistics Please Tune Me 6 The final installment in our quest for ultimate performance is ptm6 which in volves an architectural change Sticking with the g1ReadPixels track and considering some of the earlier performance tips is there any way we can avoid reading this data back and touching it with the CPU altogether The answer is yes and a fragment shader is the key to achieving this optimiza tion Simply put during readback of the pixel data we apply a gray ramp to the texture data where it does not contain the colored mesh readback information A fragment shader with a texture sampler can easily evaluate this condition and apply the gray color for us Notice that we also change the filtering mode on the teapot texture to GL NEAREST This way we don t get any interpolation bleed through when at tempting to sample our texture and assign our gray color By eliminating the readback p
52. a bug report and let Apple have a look at it Keep in mind however that OpenGL is not a pixel exact specification and minor differences between rendered images are always possible and even likely However gross differences are likely bugs so please file them There are two other renderer IDs that correspond to software renderers The software renderer preceding the current float renderer is referenced using kCGLRendererAppleSWID This older renderer is neither as fast nor as full featured as the new software renderer but could prove useful as another check when debugging or comparing results Aside from this scenario this renderer should not be used unless you wish to hamstring your application performance kCGLGenericID kCGLGenericID corresponds to the original software renderer written for OS X If you are experiencing difficulty with the new software renderer and your application doesn t use features beyond OpenGL 1 2 you may have better luck with this original renderer Although not as highly tuned the old software renderer is better tested by virtue of its age alone This older software renderer can also be used as yet another data point in fortifying a bug submission if you suspect a problem with one of the hardware renderers 62 Chapter 6 The CGL API for OpenGL Configuration kCGLRendererAppleSWID Arguably this renderer ID should not be published It serves as a placeholder and a questionable o
53. a context it s current and we re ready to finish this exercise with two methods that we ve seen before The last two methods we implement are identical to those we ve used before The prepareOpenGL and drawRect methods contain the same code as in the prior example As before they perform two tasks in your context OpenGL initialization and rendering respectively With their completion you re ready to build and run the application You should see the same teapot against a blue background as in Figure 8 8 Additional Topics So far we ve explored ways to render directly to the screen using Cocoa Now we ll dig into how to render somewhere off screen There are many reasons why you might want to do this for example to create a cube map for re flection to create shadow maps or to create another form of dynamic tex ture For off screen rendering we ll be building on the foundation from the Cocoa examples in previous sections so if you ve skipped to this point with out reading those sections you may want to review them to gather additional details Manipulating Images and Pixels in OpenGL Before we get into specific techniques let s talk about the various ways that an image of some sort can be moved around rendered and copied in OpenGL OpenGL provides two main paths for pixel data e Pixel path e Texture path These two paths are very different in the way they re ultimately available to be rendered The pixel path cons
54. a mechanism that the OpenGL Architecture Review Board cre ated for OpenGL to allow custom features beyond the scope of a particular version of OpenGL They enable the creation of new features modify existing features expose capabilities on hardware that wasn t present when the current version of OpenGL was ratified and more In essence an OpenGL extension describes features beyond the scope of the current base OpenGL version That s part of why extensions exist but there s another reason and a fundamental one at that If you ll indulge a minor rant here s the more exhaustive scoop on the why of OpenGL extensions One complaint frequently leveled against OpenGL is that it is lagging the fea ture curve or is somehow farther off the leading edge than other APIs The peo ple who make such complaints often use other platforms and other APIs we won t name names cough Direct3D cough and usually obtain new versions of their APIs every year or so This is regarded as progress and de velopers who are enthralled with this model are usually quite excited to have access to new features Unfortunately making frequent changes to the under lying API requires developers to change code implement new design patterns and stay late at work That s not such a great thing especially if you re one of those developers Not only is the perception that other APIs advance more rapidly than OpenGL false but OpenGL evolves in a way that developers h
55. a new image by simply rendering the current image in the current Quartz render area We begin by creating a new NSImage sized to our target size We next take this image and call its set Flipped method This method causes coordinate system wrangling It performs a vertical flip so that the Y 0 axis becomes the bottom of the image rather than the top as is the default Try commenting this line out and recompiling your code to demonstrate the effect of not flipping the image Figure 10 1 shows what happens in both cases In OpenGL textures have their bottom at the T 0 parameter so that S T 0 0 is the lower left corner of the image and S T 1 1 is the upper right corner Now that we ve got a new image into which we can draw new contents we make this new image become an active target for rendering by using the Cocoa Image NSImage 177 ml MvOpenGLView m cocoa nsima m MYUDerIuLvIew m cocoa nsima ooo Window Window Figure 10 1 NSImage Rendered Before setFlipped left and After setFlipped right lockFocus method lockFocus and its counterpart unlockFocus are ele ments of how Quartz rendering works and not really something we ll explore in detail The Apple documentation has lots of details on Quartz rendering so check there if you are interested in other things you can do with Quartz We then tell the current image to draw itself at the new size into the current Quartz target that is our existing n
56. advanced OpenGL topics concerning off screen rendering context sharing and more One final note to the reader before you read this chapter This chapter is de signed around Mac OS X 10 4 Tiger the most current and relevant of the Mac OS versions available at the time this book was produced However the final version of Leopard arrived late in the publishing cycle Because of this we were faced with a tough decision either update this section to show how things work in Leopard Mac OS X 10 5 and leave our Tiger 10 4 readers behind or leave our Leopard readers without updated content Neither of those answers satisfied us completely so we did the next best thing The chapter you re reading is focused on Tiger Mac OS X 10 4 and the images and text reflect that Appendix C is an updated version of this chapter with new 121 NSGL AGL CGL CoreGraphics Figure 8 1 AppKit API and Framework in Overall OpenGL Infrastructure on the Mac and relevant images workflow and text for Mac OS X 10 5 If you re looking for Mac OS X 10 4 content read on but if you re looking for the same version of this chapter addressing Leopard specific changes and with a Leopard look and feel please read Appendix C Overview The AppKit OpenGL API is part of the overall Apple OpenGL infrastructure It constitutes a layer above CGL but also has the ability to reach down into both CGL and lower layers Fig
57. are the most dynamic set of the various plug in Table2 3 Timeline of Mac OS X Releases Drawing APIs and Windowing APIs Mac OS Version Code Name Release Date 10 0 Cheetah March 24 2001 10 1 Puma September 25 2001 10 2 Jaguar August 24 2002 10 3 Panther October 24 2003 10 4 Tiger April 29 2005 10 5 Leopard October 2007 The Mac OS OpenGL Plug In Architecture 17 OpenGL Application Mac OS OpenGL Implementation Dispatch Table glAccum glAlphaFunc glBegin G 96 glWindowPos3sv SE Engine GL Engine 0 GL Engine 1 GL Engine N Plug ins O O9 Driver Plugins Software ATI NVidia 3 Renderer Renderer O O O Renderer Figure 2 3 The Mac OS OpenGL Plug in Architecture layers for two reasons e Plug ins are selectable directly by the application at pixel format selection time e Plug ins are changed out according to the physical screen on which the appli cation resides Underlying your OpenGL application at any given time is a chain of logical modules linked together to service your application according to its needs and the environment in which the application is running Renderers In the Mac OS drawing layers we ve started from the top and discussed what Apple calls the Windowing Layer Any drawing or drawing state calls made into AGL CGL and the Co
58. based on the underlying OpenGL operations This tech nique is a capable fallback for when FBOs are not available Pbuffer Off Screen and Other Intermediate Targets There exist a variety of other ways of writing intermediate rendering results for reuse in later final renderings in your OpenGL application Among these are pbuffers off screen render areas and a variety of extensions for directly Alternative Rendering Destinations 161 rendering into textures Though many other choices are possible we faced a difficult decision when writing this book either to cover them all or to cover only a subset To free up some weekends we chose the latter option To be fair since we began this project the FBO extension has really come of age and we would recommend it without hesitation for those cases when you need intermediate rendering The other techniques that we do not cover here are all genealogical predecessors to the FBO extension and in many ways are inferior to it Specif ically off screen render areas regardless of the interface CGL AGL or Cocoa are software renderers and so have only nominal performance They should be avoided for interactive or real time applications Pbuffers are complex and un wieldy to implement Although they often perform at native hardware speeds the complexity of managing the interface is not worth the headache if you can write to a modern render target like an FBO instead The pure simplicity
59. be set to zero The level will be set to the mipmap level that was last specified in a call to CGLSet PBuf fer 80 Chapter 6 The CGL API for OpenGL Configuration Texturing with Pixel Buffers as the Source If you wish to specify that your pbuffer is to be used as the current texture call CGLError CGLTexImagePBuffer CGLContextObj ctx CGLPBufferObj pbuffer unsigned long sourceBuffer The semantics for this call are the undisputed champion of complexity of all calls in CGL and with good reason CGLTexImagePBuf fer is most similar to one of the glTexImage N D calls of OpenGL That is it defines the texture source for the currently bound texture ID to use the contents of the pbuffer for rendering The ctx argument refers to the main rendering context that is using the pbuffer as a data source for texturing It does not refer to a context that you may have dedicated to your pbuffer which you would have then specified in a call to CGLSet Pbuf fer Having two such contexts is the typical pbuffer us age scenario It requires a context switch from your main rendering context to your pbuffer context whenever you wish to change the destination of rendered output from say the visible screen to your pbuffer This context switch is a con siderable performance disadvantage to using pbuffers as compared with frame buffer objects Some key differences in standard OpenGL texturing must be considered when us
60. bool has so glutExtensionSupported GL ARB shader objects bool has lang glutExtensionSupported GL ARB shading language 100 has shading has vs amp amp has fs amp amp has so return has_shading The second piece of extension resolution performed by GLUT is the op tional binding of functions from the active GL library The entry point glutGet ProcAddress allows this binding with a simple API You just pass in the name of your entry point of interest and a non NULL result indicates suc cess and the function pointer As we mentioned earlier Apple has an implicit policy of not requiring ex plicit function lookup if the extension exists Sometimes however your infra structure for a cross platform application may require this capability GLUT is probably not the best layer for performing this task because you ll probably 274 Chapter 13 OpenGL Extensions end up linking in GLUT as an additional framework Your memory footprint may increase as might your load times The dlopen d1sym route is prefer able given that Apple probably does something like this internally in its imple mentation of this function Although various implementations of GLUT exist in source form all of them indicate that glutGetProcAddress works only for Windows and X11 However despite the fact that Apple doesn t document this function in the manual pages this API really does work and yields correct results If you so choos
61. buffer Similarly g1Bu ferData and g1BufferSubData canbe used to directly modify a VBO s contents in much the same way that a call to g1TexImage2D or gl TexSubImage2D would be used to modify a texture Which Methods Should You Use to Submit Vertices for Drawing As of OpenGL 2 0 you should consider methods of vertex submission other than VBOs to be syntactic sugar If you re drawing 10 triangles on the screen once by all means use immediate mode rendering without vertex arrays For the rest of your applications leverage VBOs and exploit their versatility and performance This approach will continue to pay dividends if you end up us ing the buffer object extension the heart of VBOs for pixel buffer objects as well Efficient Handling of Vertex Data 213 Apple s Methods of Vertex Submission Past and Present If you re starting a new application or if you re porting a relatively modern and well written OpenGL application there s a good chance that you can just learn the nuances of good VBO etiquette and forget about the now fairly complex history of submitting vertices using Apple s OpenGL implementation You may have noticed some limitations in the previous section with meth ods prior to VBOs for submitting vertices in OpenGL Apple noticed them too and responded with many of its own extensions to OpenGL Thankfully most of these extensions are also recognized as nece
62. can go ahead and call anything you d like there Keep in mind that this method will be called only once so from that point on you ll have to manage your OpenGL state changes on the fly The second method to implement is drawRect This method will be called ev ery time a scene redraw is necessary you will do the bulk of your OpenGL work there As part of the drawRect signature you will be handed an NSRect containing the current origin and size of the drawing area in pixels With that introduction out of the way we ll simply point you at the code Example C 2 to add to your MyOpenGLView m file somewhere between the implementation and end tokens Once you ve added this code recompile and run the code again and you should see something like Figure C 6 Example C 2 Cocoa drawRect Rendering Method with Sample OpenGL Content void drawRect NSRect rect t adjust viewing parameters glViewport 0 0 GLsizei rect size width GLsizei rect size height giclearColor 0 5 8 0 glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT glMatrixMode GL MODELVIEW NSOpenGLView 293 eoo Window Figure C 6 Teapot Rendered with NSOpenGLVi ew with Subclass glLoadIdentity glTranslatef 0 0 1 GLfloat green 4 0 1 0 0 glMaterialfv GL FRONT AND BACK GL AMBIENT AND DIFFUSE green glutSolidTeapot 5 self openGLContext flushBuffer end If you see a teapot succes
63. ceseczxeee e Re RR ey Re 240 Please Pune Me Ais ace dese aue react RISI m rede rmt breed es 241 Please Tune Me 5 icerseilda b o RR RR E Op RU RMPRPEDRIdSR REP 241 Please Tube MeO ice Rr A RF ed eed RP Eer EUR E 243 DUMINGTY niodo ide tend pep bee RII epp Vides Hep 243 Contents xi Chapter 12 Mac Platform Compatibility Mac OS Versions 200 e cece ee cee eee 10 0 through 40 1 22d or bp wvietst wives a RO a 10 2 Jaguar rr or rote e pe prebee sc e ERE AA 10 3 Panther sseoecsece spere aee rer T eere eve TOA Tiger 25 10 5 and Beyond cc sabes bie eink od eae EP E EE eee OpenGL Platform Identification Mac OS Version Identification 2000 Chapter 13 OpenGL Extensions OVETVICW S uh dente cacti on ah daca E deste edet sete ae Extension Design and API Integration Extension Styles and Types sees eee Identification Selection Query and Usage Selecting Extensions 00 eee eee eee eee eee Utilization and Binding 00 0 eee Extension Management Libraries Appendix A X11 APIs for OpenGL Configuration Install a DIO Es dei ar per a dae EUER IN t UE dedo ined Building X11 Applications on OS X XXI Color Models bete bea PTT PIER Appendix B Glossary Appendix C The Cocoa API for OpenGL Configuration in Leopard Mac OS X 10 5
64. common example of this technique in user software is found in games usually where a game takes over the display for a complete and unobstructed experience of slay ing dragons flying through canyons at Mach 0 8 or conquering the galaxy A rule of thumb to decide when full screen rendering is needed is this Any time you want to present a completely custom user interface full screen applications are one way to go In this section we ll first tackle some plumbing details neces sary to render full screen OpenGL surfaces and then demonstrate how to create and use a full screen OpenGL area Display Capture One major reason for using a full screen area is to coherently display some con tent without the distraction of other UI elements A key element of this experi ence would be blocking interruption by other applications while in this mode Apple provides hooks to allow an application to essentially take over the dis play preventing other applications from presenting their content over the top This behavior is known as display capture Display capture exists at the Core Graphics level of graphics typically a 2D layer and is not part of our discussion in this book Nonetheless the ability to capture the display is a useful albeit not required element of a full screen application even in Cocoa Performing display capture is a very easy task but entails strict ordering of the tasks Essen tially the process proceeds as follows 1 Capt
65. container for reading the contents of the left side of the application window for later use as a texture on the teapot Because this is a VRAM managed resource the readback operation is extremely fast Notice that with the binding of the PBO the data argument for glReadPixels is 0 because the PBO is now being used as the destination for the read With the texture contents stored in the VBO we still need to map the ob ject and update it to preserve the gray ramp color teapot semantics de scribed earlier This is simply a matter of mapping modifying and unmap ping the PBO Later when we wish to texture with the VBO we bind it by using GL PIXEL UNPACK BUFFER rather than the GL PIXEL PACK BUFFER binding that we used when reading the pixels Using PBOs for readback and as a texture source has brought Please Tune Me to more than 60 frames per second Pretty soon we ll have to change the name to Please Admire Me So what does our profile look like now Figure 11 17 We see what appears to be some more deferral overhead in the big spike at CGLFlushDrawable We also have a big chunk sitting at g1EvalMesh2 which is a result of our call to glutSolidTeapot Sticking with things under our immediate control despite our PBO usage we re still seeing a 16 percent hit in g1ReadPixels 242 Chapter 11 Performance AAA Statistics a gt Save As Text Clear GL Function of Calls Total Time usec Avg
66. data caches in this case Keeping caches hot is paramount to high performance streaming of data through the system The other undesirable artifact of making these state changes is that you always affect two pieces of hardware when you make such changes Both the CPU and the GPU and their respective memories are affected When the data struc tures inside OpenGL are altered those changes inevitably have to be commu nicated to the GPU This communication means more graphics bus traffic in 196 Chapter 11 Performance the system and all the synchronization overhead inherent in bringing this state up to date Consider also that deferral of updates is often a good strategy for any synchro nization task in a system You may therefore be introducing costs into the equa tion that are realized at a later and sometimes unpredictable time For exam ple often the cost of a state change is not realized until a drawing command is called that relies on that state Textures are a good example Defining a new texture with a g1 TexImage2D call sets up the texturing state on the cur rently bound texture object but the data passed into this function the actual pixels making up this texture are not uploaded to the graphics adapter until the application draws using this texture Thus the first time you draw with that texture bound you could experience a much longer than usual draw time as the data is transferred to VRAM For game developers
67. do with events while you re in a full screen mode Example 8 9 Custom Controller Event Handling Loop in a Full Screen Context stayInFullScreenMode YES while stayInFullScreenMode NSAutoreleasePool pool NSAutoreleasePool alloc init Check for and process input events NSEvent event while event NSApp nextEventMatchingMask NSAnyEventMask untilDate NSDate distantPast inMode NSDefaultRunLoopMode dequeue YES switch event typel case NSLeftMouseDown self mouseDown event break case NSLeftMouseUp self mouseUp event break case NSLeftMouseDragged self mouseDragged event break Additional Topics 151 case NSKeyDown unichar cc event charactersIgnoringModifiers characterAtIndex 0 switch cc case 27 escape key stayInFullScreenMode NO break default break break default break The basic idea is that while in full screen mode no external UI controls Cocoa or other exist that have natural event handling mechanisms so you need to do whatever your application requires when an event occurs This includes mouse handling key handling and external device e g joystick tablet handling Example 8 9 does nothing more than simply handle the Escape key quit the render loop and return to windowed mode The example deals specifically with key events handling the Escape key by quitting full screen mode
68. extensions that enable you to use the full capabilities of that graphics card Furthermore if you stick to writing to the base of a core OpenGL version say 1 4 you can be assured that your results will be correct barring bugs on a variety of platforms provided all of those platforms support that same version Not to beat this point to death but the OpenGL extension mechanism and by implication the core design of OpenGL exists to help developers quickly write software that works wherever an application needs to be along the feature functionality continuum Before we explore the actual extension mechanisms and methods we should explain how extensions become parts of core OpenGL An evolutionary process 1 This argument is the topic of an ongoing debate among OpenGL and DirectX programmers and all we ve just done is pour a little more gasoline on the fire Of course the truth of the situation lies somewhere in the middle However despite the intense feelings on both sides OpenGL has a well defined and clear mechanism for handling growth and has done so very successfully for quite a long time 254 Chapter 13 OpenGL Extensions takes once bleeding edge features and over time migrates them so that they become part of the OpenGL standard Thus your application that uses extensions to OpenGL today may in the future be able to satisfy its needs us ing a particular version of core OpenGL But let s back up a step and describe h
69. fact this process aside from the specifics of what function calls to use remains the same as that for CGL Specifically you perform four simple steps 1 Describe create and find a matching pixel format AGLPixelFormat aglChoosePixelFormat 2 Create an OpenGL context AGLContext aglCreateContext using the pixel format created in step 1 3 Bind that context to a drawable AGLDrawable aglSetDrawable 4 Initialize OpenGL handle events and render Here we ll look at the relevant application code to create and use a win dowed AGL application and a full screen AGL application as examples of the creation and use of pixel formats and contexts In the Cocoa chapter Chapter 8 we ll spend time walking through how to configure and create an XCode project for that set of examples For now however we ll leave it to you to create an XCode project on your own to insert these samples Carbon event Pixel Format and Context 91 management and plumbing are well beyond our scope But without further ado let s begin the construction of our application Full Screen Application We will begin by creating a full screen AGL application so we must create a new XCode project and configure it to depend on the key libraries neces sary for OpenGL and AGL on the Mac that is the AGL framework and OpenGL framework frameworks Once it is configured we can create a main c program You ll next want to add code to include the Open
70. flexibility that you may not need any of the additional control that CGL allows If you re doing simple prototyping of graphics techniques you ll probably find GLUT to be the easiest API with which to get up and running CGL shares many things with other windowing interfaces to OpenGL pixel format selection context creation and manipulation and a pbuffer interface to name a few On OS X CGL also has to shoulder the burden of require ments that arise out of having a plug in renderer architecture that supports a heterogeneous set of installed graphics devices Figure 6 1 Dragging a win dow from one display to another is a simple matter if both displays are being driven by a single graphics device it s quite another matter if the displays are on different devices with widely varying capabilities On any OpenGL implemen tation the context state that is maintained internally is a reflection of the capa bilities of the underlying hardware Imagine how that context state varies when you drag a window from a display supported by a high end graphics device built by one graphics hardware vendor to a display supported by a low end device built from another Linking with CGL is easy it s part of OpenGL framework which is typically found in System Library Frameworks but may also be in a path specific to your SDK installation Because CGL is part of the OpenGL framework its 56 Chapter 6 The CGL API for OpenGL Configuration headers are fou
71. for Anti Aliased Pixel Format NSImage Rendered Before set Flipped left and After setFlipped right 0 cece eee eee First Frame of the Movie Subsequent Frames of the Movie Subsequent Frames of the Movie 0 ce eee eees Vertex Submission Example Application OpenGL Profiler Main Window with Launch Settings Open OpenGL Profiler Breakpoints View OpenGL Profiler Statistics View OpenGL Profiler Trace View esses OpenGL Profiler Resources View ssessessssss OpenGL Pixel Format View 0 000 c eee c eee eee ee OpenGL Profiler Buffer View cesses OpenGL Profiler Scripts View Performance Tuning Exercise Application Please Tune Me Figure 11 13 Figure 11 14 Figure 11 15 Figure 11 16 Figure 11 17 Figure 13 1 Figure 13 2 Figure C 1 Figure C 2 Figure C 3 Figure C 4 Figure C 5 Figure C 6 Figure C 7 Figure C 8 Figure C 9 Figure C 10 Figure C 11 Ptml OpenGL Stats voc coc ceeded cee eve ree eerie eh nn 239 ptm2 OpenGL Statistics icis scies h ea owes cae 240 ptm3 OpenGL Statistics eise 6 cece cece cece eee ees 241 ptm4 OpenGL Statistics 6 eee eiei ee eee ees 242 ptm5 OpenGL Statistics 0 0 cece eee eed 243 Shader Extension Application Results if Successful 263 Shader Extension Application Results if Unsuccessful 264 AppKit API and Framework in Overall OpenGL Infrastructure on the Mac iisssssssssseeeh 28
72. formats CGL will maintain at any given time The default number is 5 but it can be de creased or increased to match the number of pixel formats your application uses Most applications use only a single pixel format so memory conscious applications of this general kind can set the kCGLGOFormatCacheSize to 1 As a point of reference at the time of this writing each of these pixel format data structures was approximately 60 bytes in size This value of course is sub ject to change at any time It is not likely that it will ever be less than its present value however You may clear the CGL format cache at any time by using kCGLGOClearFormatCache This will free the memory of the format cache but has no effect on future allocations For persistent control of these alloca tions use kCGLGOFormatCacheSize As it is essentially an operation rather than a parameter CGLGetOption will return false for this constant kCGLGORetainRenderers is used to retain renderers in the Mac OpenGL en gine s plug in renderers list Plug in renderers maintain a reference count for all contexts that are referencing them When the last context referencing a ren derer is destroyed the renderer is normally unloaded from the plug in list and its memory freed This behavior though good in the general case is not suit able if your application frequently creates and destroys contexts that are unique to a single renderer in the plug in list Setting kCGLGORetainRendere
73. handling and in general APIs to manage this external data and exchange and use it in our OpenGL applications One of the mantras that we return to repeatedly when discussing the Mac is this It just works That mantra is true with many Mac APIs as well Of course not all of them are simple or sometimes even sensible in the way they seem to work but they do just work In this chapter we ll explore some of the more modern APIs for graphics data such as Cocoa s NSImage a class allowing arbi trary image loading and manipulation and QuickTime an API for playback of a wide variety of time based media While in previous chapters we ve taken great pains to demonstrate all of the possible APIs and techniques for interacting with 173 OpenGL in this chapter we ll focus solely on the most actively developed and most modern of Apple s APIs Cocoa All examples will be in Cocoa and we won t be shy about using Cocoa to its fullest benefit to get our job done with the least amount of extra coding We begin by looking at images in Cocoa and considering how to populate and use them with OpenGL Cocoa Image NSImage A fundamental way of interacting with 2D images in Cocoa is the class NSImage An NSImage is an object representing an image and is a funda mental data type used in interacting with a variety of Cocoa classes that perform image manipulation We ll look at how images are represented in the NSTmage class and provide example m
74. hardware Both can be clever but there is no real magic here If your application must make a million calls into OpenGL with every frame it s going to be slower than if it makes a thou sand calls with every frame while submitting the same amount of data This may seem to go without saying but because it is such a common problem with applications we thought it worth mentioning explicitly Let s move on to those golden rules we keep talking about Minimize State Changes The OpenGL ARB works hard to reduce the number of state dependencies in the specification especially when it comes to error handling The engineers build ing the Mac OS OpenGL implementation work hard to reduce the overhead of state changes in the system Despite all of these efforts the system is very large and there is always a cost associated with thrashing the state OpenGL is a state machine In code speak this means the implementation has many data structures and branches that keep track of a lot of information Each time your application makes a state change such as changing the current color turning lighting off or binding a new texture that change needs to be reflected in all of those state data structures Besides the obvious cost of reading and writing to those data structures these state changes effectively cool down your caches because whenever you touch different pieces of memory in the system it has potential to evict cache lines both instruction and
75. in initWithFrame include OpenGL gl h include lt GLUT glut h gt include lt math h gt import MyOpenGLView h implementation MyOpenGLView id initWithFrame NSRect frame time 0 angle 0 GLuint attributes NSOpenGLPFAWindow choose among pixelformats capable of rendering to windows NSOpenGLPFAAccelerated require hardware accelerated pixelformat NSOpenGLPFADoubleBuffer require double buffered pixelformat NSOpenGLPFAColorSize 24 require 24 bits for color channels NSOpenGLPFAAlphaSize 8 require an 8 bit alpha channel NSOpenGLPFADepthSize 24 require a 24 bit depth buffer NSOpenGLPFAMinimumPolicy select a pixelformat which meets or exceeds these requirements 0 288 Appendix C The Cocoa API for OpenGL Configuration in Leopard NSOpenGLPixelFormat pixelformat NSOpenGLPixelFormat alloc initWithAttributes NSOpenGLPixelFormatAttribute attributes if pixelformat nil NSLog No valid OpenGL pixel format NSLog matches the attributes specified at this point we d want to try different sets of pixelformat attributes until we got a match or decide we couldn t create a proper graphics environment for our application and exit appropriately H now init ourself using NSOpenGLViews initWithFrame pixelFormat message return self super initWithFrame frame pixelFormat pixelformat autorelease But wa
76. in one cur rent version of the OpenGL library on one of our development machines the symbol corresponding to the API entry g1CompileShaderARB is named glCompileShaderARB The string you d pass to the dlsym call would not be this mangled name but rather the human readable function name The dlsym call would then mangle and resolve the name appropriately Now let s see the code that uses the dlopen dlsym dlclose API from start to finish First in Example 13 5 we extend our class definition to provide storage for the symbols We allocate space for each of the symbols we use in our pre pareOpenGL method as seen in Example 13 8 Looking at this code segment we see that we have the same preproccessor checks as before but add one more runtime check to see if we ve successfully bound the symbols we require to pro ceed If we pass the extension check we call resolveShaderSymbols as seen in Example 13 7 to resolve and cache the function entry symbols and finally we invoke our shader code The code in Example 13 7 simply calls the method we constructed earlier resolveSymbol to check whether each named symbol is available There s a lot of code here but it really does three simple things in a general form that you can follow for your own extension wrangling 1 Resolve symbols for each extension API entry 2 Validate that all symbols exist together for complete definition and usage of that extension 3 Store extension functio
77. in the computing industry were once large amounts to have on complete computing 30 Chapter 3 Mac Hardware Architecture systems let alone subsystems like graphics Even so these large buffers are used for lots of tasks including not just display of resultant images but also storage of various graphics data from textures to geometry to the framebuffer itself We ll explore some of the issues you should consider about VRAM from a hardware perspective in this section Why does Mac OS 10 2 also known as Jaguar have a minimum VRAM re quirement while Mac OS 10 1 does not With the introduction of OS X and Quartz 2D Apple moved from a simple planar windowing environment to a composited 3D window system Today everything you see windows icons the dock and so on is floating in 3D space on the Mac desktop What once were simple pixel maps now have representation as textures in VRAM This means that the OS is capable of a unique and rich user experience albeit at a cost Quartz 2D the main system 2D graphics rendering engine is also an OpenGL application and competes with your application for some of the same graphics system resources Leopard continued to push forward with OpenGL usage introducing Quartz 2D Extreme which fully accelerated the Quartz layer in OpenGL This feature of the OS has pushed VRAM requirements into another echelon previously un known to personal computer operating systems Quartz 2D Extreme is more or le
78. include include include lt stdio h gt lt mach mach_interface h gt lt mach mach_init h gt lt IOKit pwr_mgt IOPMLib h gt IOKit IOMessage h io connect t root port void callback void x io service t y natural t messageType void messageArgument float z float x printf z 6 2fXn z switch messageType case kIOMessageSystemWillSleep printf SystemWillSleep n Here can either cancel or allow EL IOCancelPowerChange root port long messageArgument IOAllowPowerChange root port long messageArgument break case kIOMessageCanSystemSleep printf CanSystemSleep n Here can either cancel or allow IOCancelPowerChange root port long messageArgument Le IOAllowPowerChange root port long messageArgument break case kIOMessageServicelIsTerminated printf ServiceIsTerminated n break case klIOMessageServicelsSuspended printf ServiceIsSuspended Wn break case klIOMessageServiceIsResumed printf ServiceIsResumed n break Power Management 35 case kIOMessageServiceIsRequestingClose printf ServiceIsRequestingClose n break case kIOMessageServiceIsAttemptingOpen printf ServiceIsAttemptingOpen n break case kIOMessageServiceWasClosed printf ServiceWasClosedWin break case kIOMessageServiceBusyStateChange printf ServiceBusyStateChange n break case kIOMessageServicePropertyChange printf
79. increase only for any major or minor release of the Mac OS Further as the Tiger portion of the table shows version compliance for the software renderer can vary in apparent relationship with the hardware renderer shipped for the system This apparent relationship is a false one however It merely reflects software improvements that accompanied hardware that had shipped later in the prod uct cycle In the software renderer case its version will generally be consistent across all hardware configurations as is shown in the Leopard portion of the table Notice that the table references two different software renderers the Apple Generic Renderer and the Apple Float Renderer The Apple Float Renderer is simply a newer and much improved version of the Apple Generic Renderer Both are referred to as the software renderer The software renderer was vastly improved in both performance and capabilities moving from Panther to Tiger and again moving from Tiger to Leopard About OpenGL 13 As you can see in Table 2 2 no particular version of OpenGL is standard across all hardware in a particular release of Mac OS Care must be taken when writing an OpenGL application to always ensure that your baseline OpenGL implemen tation version requirements are met independently of the Mac OS version Note that only the last minor release version of each major release of OS X is shown in Table 2 2 Minor releases in OS X are free downloads so this table
80. ineffi cient and cumbersome to use GLEXTframebufferobject on the other hand is both simpler to use and more efficient than GLARBrendertexture The GLEXTframebuffer object API is contained wholly within the GL API and has no non portable window system components Under GLEXTframebufferobject it is not necessary to create a second GL context when rendering to a texture image whose format differs from that of the window Finally unlike the pbuffers of Alternative Rendering Destinations 313 GLARBrendertexture by changing color attachments a single framebuffer object can facilitate rendering to an unlimited number of texture objects We believe that this extension is the best way to render to texture and authori tatively settles the question of what to use when performing a render to texture operation Without further ado let s walk through how to use FBOs for inter mediate rendering and look at code to do so as well The overall algorithm for using FBOs is straightforward 1 Build and initialize the target object to be used with this FBO This object is typically a texture 2 Build and initialize the FBO by attaching the target objects 3 Bind the FBO and render the FBO contents 4 Unbind the FBO and render the final scene using the target object We ll begin by revisiting our old standby Cocoa example and extending it to configure and render to an FBO We will then use those results on our final re
81. ing creating a pixel format and creating a subclassed version of drawRect We ll also mimic some of the infrastructure automatically provided in NSOpenGLView so you can see how it does its work This time around we ll present all the code in the final versions of both the header file Example 8 3 and the source file Example 8 4 first and then walk you through each Example 8 3 MyView h Final Header import lt Cocoa Cocoa h gt interface MyView NSView private NSOpenGLContext _context NSOpenGLPixelFormat _pixelformat NSOpenGLContext openGLContext void prepareOpenGL end We begin by looking at the MyView h header We ve inserted both a few member variables and a few methods We ve also created member variables to store pointers to our context and to our pixel format we ll create code to initialize these variables in the source file We also declare two methods openGLContext and prepareOpenGL named to emulate the behavior of the Cocoa supplied NSOpenGLView openGLContext will be used to return the current context or to create one if none exists prepareOpenGL will be used as our first call to our OpenGL context to initialize the basic OpenGL functionality as we did before for our MyNSOpenGLVi ew class That s all there is to do in the header so let s look at the source see which other methods we ve overloaded from NSView and see how the code behind these signatures works Example 8 4 My
82. is defined in terms of CGL commands Pretty clear so far this seems like a simple layering with AGL atop CGL But if you actually look at the CGL headers there is no exposed way for you to perform windowed rendering in CGL If you re doing only full screen or off screen rendering you can work exclusively with CGL commands The point here is that there is more to these APIs than meets the eye and that the exposed API doesn t necessarily allow you the same functionality that the internal APIs can themselves access We ll go into more detail about the relation ships among these APIs in Chapter 5 OpenGL Application GLUT Appkit AGL CGL OpenGL Figure 2 2 AGL CGL and AppKit Layered with OpenGL 16 Chapter 2 OpenGL Architecture on OS X The Mac OS OpenGL Plug In Architecture One important thing that the engineers at Apple responsible for the OpenGL im plementation realized early in development was that the computing landscape is constantly under change Consider just the six major versions of Mac OS X that have emerged since 2001 Table 2 3 Whether it s market conditions tech nical capabilities costs or other factors the OpenGL implementation on OS X has to adapt to a changing environment Further because the OS depends so heavily on OpenGL the implementation has many eyes on its performance In short the OpenGL implementation needs to be adaptable error free and high performance To adapt to the changi
83. is no way around that There are only two solutions when the limits of the graphics bus are reached First you can send less data using lower fidelity images compressed textures or decimated models Alternatively you can distribute the graphics data trans fers over a longer time span That is you can spread the data you re down loading among multiple frames of rendering You sometimes see the results of a technique like this as a progressive improvement in image fidelity over sev eral frames rendered as more and higher fidelity models and textures are trans ferred and rendered A third bus also has relevance for graphics programmers the bus bandwidth available on the actual graphics card on which you re rendering Most modern graphics hardware have much faster busses than either the graphics or mem ory busses described thus far Typically these are approximately an order of magnitude faster than their counterparts farther upstream Current GPUs have memory bandwidths in the 10s of gigabytes per second In most applications you probably won t be bound by this bus but as always it s possible to get bottlenecked here as well Never say never It s vastly more common to see an application have difficulties managing data computation copies and transfer to the graphics card Video Memory VRAM Video memory on graphics hardware is a complex and opaque topic Modern graphics cards have lots of video memory amounts that for old timers
84. it frequently We ll do the same thing here In our NSImage example we created an image and downloaded it once In our current code we re obviously looking at a stream of images so we ll need to continuously download images There s no real way around this download step and we ll look at that in a bit more detail after ex ploring Example 10 10 Example 10 10 Draw Rectangle Method Applying Movie Frames void drawRect NSRect rect glClearColor 0 5 8 1 glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT QuickTime 187 flip texture glMatrixMode GL TEXTURE glLoadIdentity glScalef 1 1 1 grab the next frame from the movie and download it as a texture if movie nil movie play self downloadImageAsTexture movie currentFrameImage configure the view matrix and draw a textured quad glMatrixMode GL_MODELVIEW glLoadIdentity glRotatef angle 0 0 1 giTranslatef 0 0 1 glCcolor3f 0 1 0 glBegin GL QUADS float ww 9 float hh 9 glTexCoord2f 0 0 glVertex3f ww hh 0 glTexCoord2f 1 0 glVertex3f ww hh 0 glTexCoord2f 1 1 glVertex3 ww hh 0 glTexCoord2f 0 1 glVertex3f ww hh 0 glEnd glFlush self openGLContext flushBuffer What do we see here It s the same draw method that we used in earlier exam ples with one entry point to QTMovie the currentFrame method The
85. over the version 2 x series boasts a greatly improved interface and reliable attach to functionality for running applications OpenGL Profiler Main Window For our tour of this application let s start with the main start up window We ve expanded the Launch Settings arrow for Figure 11 2 You will probably find the Launch Settings drop down menu of greatest in terest This menu provides an incredibly powerful feature the ability to test the behavior of your application against graphics devices other than the one installed in your system In addition this menu allows for a quick easy com parison of the behavior of your application with the Apple Software Renderer This is a great thing to check out if you suspect there is a bug in the OpenGL software itself If the output is different it probably indicates the presence of a bug you should report to Apple Also notice the Use custom pixel format check box This option allows you to build a custom pixel format so that you can do a quick comparison of your application with a different pixel format configuration There are two modes of operation for profiling launching the application from Profiler and attaching to a running application When an application is launched from Profiler it retains the history of the application and its arguments for use in the future It s a simple session mechanism but is often overlooked in other ap plications even though it is i
86. per image pixel int bytesPerPlane Number of bytes in each image plane R G B A etc int bytesPerRow Number of bytes in an image pixel row unsigned char bitmapData Pointer to contiguous buffer containing all pixel data Example 10 4 Extracting a Bitmap from an NSImage NSBitmapImageRep bitmap NSBitmapImageRep alloc initWithData image TIFFRepresentation This function takes our existing image and requests that a TIFF representation be generated From that result we create using the familiar Cocoa alloc init paradigm anew NSBitmapImageRep As you can see the conversion process is fairly heavyweight first converting to a TIFFRepresentation and then creating a new NSBitmapImageRep from that data A few copies later and we re there Done Our next and final step is to put all these pieces together in a code example Downloading an NSImage as a Texture In prior sections we ve performed individual pieces of NS1 mage manipulation first creating them then discussing and performing resizing options and finally converting the NSImage into an NSImageBitmapRep so that bitmap data can be fed into OpenGL Let s review our prepareOpenGL code from a few sec tions back and add a conversion and a method that downloads an image to the hardware We begin by creating an NSImage Example 10 5 Example 10 5 Initialization and Creation of an NSImage
87. portion of a data element AltiVec units have a set of burly registers that are 128 bits in size For the math adept among us that s four single precision floating point values that can be processed per pass AltiVec instructions work best on big chunks of data AltiVec units can issue instructions that operate on as small a chunk of data as a byte There are only a very few bit level operations Not only are AltiVec enabled functions fast at processing streaming data or big data elements and fun to write hee hee they are also faster at loading and storing memory The AltiVec instruction set is very well specified but takes some skill to master In particular clever methods for economically loading the same value into multiple data elements byte half word word double of an AltiVec register are out there if you look for them Apple s Developer website is a great place to start 12 The engineers at Apple bust out the AltiVec and SSE big guns whenever seri ous performance and maximum efficiency needs to happen You can too if you have data that will fit that operational model as the performance benefits of a vectorized algorithm can be significant Just keep in mind that if your applica tion is expected to run on a G3 system you ll need to code an alternative to your AltiVec logic In Chapter 11 we ll investigate a tool that can help you generate optimized code for AltiVec and SSE which is introduced in the next section Any M
88. portion of the screen Figure 11 11 You can select a multiplier to vary the degree of magnification Pixie is a great tool for inspect ing individual pixels of your graphics application window 236 Chapter 11 Performance t H I u an a a ij E B Es 293 uu Figure 11 11 Pixie Putting It All Together In this section the rubber meets the road We re going to guide you through a performance tuning example that incorporates many of the tuning techniques introduced in this chapter The example is called please tune me and you will find it in the examples folder that accompanies this book In this folder are six source files ptm1 c through ptm6 c They feature an increasing level of optimization with ptm1 c being the baseline and performing poorly and ptm6 c performing very well Each stage of optimization is a response to many of the most common performance tuning questions and problems discussed on the Mac OS X OpenGL list It s quite worthwhile to follow this example incrementally through every stage We encourage you to use Apple s stellar Filemerge tool to compare successive versions in this series of examples This will make the changing code easy to follow About Please Tune Me Please Tune Me may beg the question Why so complex The answer be cause it s a more comprehensive approach to looking at performance tuning By taking a naive implementation of an application that does more than draw a
89. render those data in another form Second textures are chunks of data that are intimately bound to OpenGL contexts and we ll need to know how to share data among contexts if we want to use textures rendered in one context in another context Essentially this section is a segue into sharing contexts which is the topic we explore next Context Sharing A key concept in many aspects of OpenGL rendering on the Mac or otherwise is what lives in an OpenGL context and how to efficiently use that data for multiple purposes Essentially a context contains all OpenGL state data associated with rendering such as the viewport dimensions active color and rendering modes A context also includes much heavier weight items such as texture objects and vertex objects Large objects consume nontrivial amounts of memory on a graphics card so the designers of OpenGL anticipated the need to avoid duplicating resources among multiple rendering areas This anti redundancy capability is exposed at the window system level as a feature called context sharing This capability is typically requested when a new OpenGL context is created after the first rendering context has been created and used The context with items you wish to access is passed into some form of initialization for your new context usually along with a pixel format For two contexts to be compatible their pixel formats must be compatible which is why you see these two things specified together
90. renderer supports full screen rendering kCGLRPRendererID The renderer ID being described by CGLDescribeRenderer kCGLRPAccelerated Boolean indicating whether the renderer is hardware accelerated kCGLRPRobust In the event that your current renderer is a hardware renderer kCGLRobust indicates whether it can fall back to software in the event that one of the limits of the renderer is exceeded kCGLRPRobust is a renderer selection attribute That is if kKCGLRobust is set to true at pixel format selection time only renderers that cannot fall back to software will be returned in the match list The vast majority of applications should ignore this attribute It has historical relevance for situations where two hardware devices each with an attached display were installed in the system If the less capable of these devices had one of its limits exceeded GL MAX TEXTURE SIZE for instance and kCGLRobust was set to true the more capable device would be used as a fallback renderer If kCGLRobust was set to false the less capable device would fall back to the software renderer to handle the situation where its limits were exceeded kCGLRPBackingStore Boolean indicating whether the renderer can provide a back buffer for color information that is the size of the drawable object associated with the con text using the renderer If set to true KCGLRPBackingStore guarantees that the contents of this back buffer are valid aft
91. scale the view within the window to suite your tastes Finally in the Inspector window name your class something sensible like MyOpenGLView Your results should look similar to Figure C 3 So what did we just do We told Interface Builder that we wanted to create a Custom View arrange it in the window and name it We re trying to get a custom OpenGL view specifically the NSOpenGLView class It provides the integration between OpenGL and Cocoa By subclassing it we become able to customize many aspects of its behavior including pixel format selection and context shar ing But we re getting ahead of ourselves First we ve got to get MyOpenGLView into a form where we can write some code We ll now use Interface Builder to instantiate a default object when the NIB file is loaded bind it to our CustomView and create some sample code First let s create an instance of our class Return to the Library window and find the blue cube icon This stands for an arbitrary object to be instantiated on NSOpenGLView 285 File s Owner First Responder Applicaton MaeMeny NEUE Provides you with an instance of a view subclass that is not available in interface Builder You can use the Custom View to create your own views CB a roe Figure C 3 Selection Layout and Specialization of a CustomView in Interface Builder our behalf Drag that out and into the MainMenu window Select
92. self NSOpenGLContext openGLContext t if context nil only if uninitialized if this is our first time to initialize _context NSOpenGLContext alloc initWithFormat _pixelformat shareContext SharedContext instance context Additional Topics 147 if context nil NSLog No valid OpenGL context can be created with that pixelformat we can fail a few ways 1 bogus parameters nil pixelformat invalid Sharecontext etc 2 share context uses a different Renderer than the specified pixelformat recovery techniques 1 choose a different pixelformat 2 proceed without a shared context id return _context As you can see in Example 8 7 the only changes we made from our origi nal custom view example are to use the SharedContext instance pixelFormat accessor to create a pixel format for this view and then sim ilarly to use the SharedContext instance context accessor when constructing our context We should always of course confirm that all pixel formats and contexts are successfully created for our production code as well So add code like this to your existing code and then make one last change specifically change the clear color in one of your custom View drawRect methods If everything works as planned your application should produce results like these shown in Figure 8 15 ooo Window Figure 8 15 Context Sharing Two Windows D
93. state dependencies involved with any kind of query to OpenGL that returns information such as a g1Get If the OpenGL implementation has buffered 10 drawing commands and the eleventh command is a g1Get the implementation is forced to process and validate the previous 10 drawing commands immediately with no further buffering allowed because one of those prior 10 OpenGL commands could change the value of the state being requested in the eleventh command Implementers of OpenGL have to decide how much drawing command data is buffered If that decision was say 500 and an appli cation forces that command buffer to be flushed every 10 commands the overall throughput will be terrible Optimally performing applications keep track of their own rendering state This behavior allows them to avoid using OpenGL as a ledger that they query when they need to determine what the current state is In essence it avoids g1Get calls gd1PopAttrib calls or any other OpenGL commands that return state data to the implementation Related to state retrieval in that all prior commands need to be completed glReadPixels or any of the glCopy operations that source a frame buffer may also flush the command stream to some extent because those prior commands may modify the framebuffer that is being sourced Use Shaders Where Possible Programmable hardware offers a myriad of possibilities for increasing the frame rate Many visual effects that were for
94. the CPU such as a 2 5GHz processor using a 1 25GHz bus A very common scenario where the memory bus affects applications is as a re sult of implicit data copies By implicit we mean that within the framework the OpenGL runtime engine and graphics drivers make copies of your data dur ing the processing of that data for rendering You don t explicitly do anything in your application except use a data type that has to be transformed into a card native format Several additional copies of your data may be created causing both valuable memory and valuable memory bus bandwidth to be used Consider the architecture of a theoretical system containing two processors one CPU and one GPU and two banks of memory RAM and VRAM The memory for graphics data is initially allocated by the application itself and passed to one of the OpenGL functions When the OpenGL function is called the OpenGL runtime engine may make a copy of the data the graphics driver may make a copy of the data and a copy of the data may be created in VRAM With so many data copies taking place the memory bus becomes very busy For more information on controlling when and where data is copied in the Mac OS OpenGL implementation see the texture range extension and vertex data copy information in Chapter 11 Graphics The latest graphics bus available on the Mac platform as of this writing is PCI Express Prior to PCI Express modern Macs used the AGP Advanced Graphic
95. there is to it if you re a Mac only developer life is pretty easy What about other platforms What about a standard way of resolving sym bols across a variety of platforms It turns out there are a variety of ways to look up symbols at runtime on the Mac The technique we need here is a query of our loaded address space for a symbol matching the one that we want to use In our series of examples we re interested in building shaders so we ll look for the symbol for g1CompileShaderARB prior to using it We ll focus on only the most modern techniques for symbol resolution in this chapter as we re making this discussion as forward looking as possible If you need to target version 10 3 or earlier there are well documented techniques for querying and binding sym bols 5 In version 10 4 and beyond Apple has integrated the dlopen dlsym standard Unix like technique for symbol loading and binding It s pretty easy to do so let s take a look how it works The two functions dlopen and dlsym constitute a standard external symbol addition and resolution package integrated natively in 10 4 and found as part of an external dlcompat library in 10 3 The nice thing about this API is that you can find it on many other platforms including Linux and most versions of Unix The two functions have detailed manual pages which you can read for exhaustive detail on how they operate The overview of their function is simple though The first function dlo
96. this kind of advanced usage is beyond the scope of this book We refer you to the OpenGL framebuffer object extension for complete details Before we leave the topic of FBOs we d like to point out a few more reasons why FBOs are superior to other forms of off screen rendering First FBOs con sist of memory allocated on the graphics card itself that is directly usable in its target form for example as a texture As a consequence you avoid any off card copies to and from the host You can even avoid on card copies in good implementations of the extension Second FBOs present a consistent platform agnostic interface There just isn t a simpler interface to intermediate render ing than FBO largely due to the evolutionary process by which OpenGL is developed A variety of intermediate target rendering APIs and implementa tions were explored over the years culminating in the design and implemen tation that exists today FBOs are the best choice for modern rendering on the Mac Third FBOs avoid expensive context switching that can cost you a great deal of performance Copy to Texture In this section we describe a very common and widely available technique known as render to texture Render to texture is as simple as it sounds 158 Chapter 8 The Cocoa API for OpenGL Configuration You simply render your intermediate scene copy it to a texture and then use that texture in your final render Elegant simple and concise There are o
97. to implement programmability by the different graphics vendors Fortunately the industry has since found good footing with GLSL R300 and NV30 class hardware and better generally produce the same performance results for pro grams encoding what used to be a fixed function state in shader programs Programmability is here to stay and it seems likely that performance efforts for shaders will at least keep pace with what had been traditionally known as fixed function state Aside from the performance comparisons of shaders versus fixed function state all of the standard rules apply when you are dealing with shaders In general you should avoid state changes whenever possible With the introduction of GLSL and its stages of specifying compiling linking and using shader pro grams the need to minimize state changes in this area should be obvious Tools Apple as a company is committed to a great platform experience As a user this means an intuitive interface consistency between applications good aes thetic choices and so forth As a developer platform experience is about great tools that offer all of these same merits OS X has really hit its stride as a great development and tuning platform and the proof is in the development tools provided for it 226 Chapter 11 Performance System Tools Shark Shark formerly known as Shakiri is a system performance characterization tool Shark allows numerous types of statistical sampli
98. unpacking of your pixel data If your pointer address is aligned on a 16 byte boundary and you specify a GL UNPACK SKIP PIXELS value of 3 then your base address is effectively on a 12 byte boundary when you are using 4 byte pixels Another performance problem can result if you have specified a GL UNPACK ROW LENGTH that is greater than the image size In this case if you have a base address in the image somewhere in this big buffer that is 16 byte aligned and the image dimension is for example 9 RGB unsigned byte pixels wide then the right end of each scanline of the image is 27 bytes past the beginning Because the buffer is not tightly packed in memory using the big row length 224 Chapter 11 Performance this non aligned ragged 27 byte aligned right side of each scanline of the im age will require special in not so politically correct terms slow handling Textures More than 5400 valid combinations of texture formats types and internal for mats can be specified via g1TexImage calls of OpenGL on the Mac OS A great deal of engineering has been done to increase the effective texture upload performance on the Mac If however you don t choose wisely on your internal format and external format type your texture upload performance may fall victim to the same pitfalls described for the pixel format type transformations discussed in the previous section Certainly any pixel pipeline state that would cause glDrawPixels
99. wavy regardless of the method of cranial impact In this case our intermediate scene would be the original street scene rendering We would then take that image and run it through our Blunt Trauma frag shader Our example code will render scenes of similar complexity or at least a teapot to demonstrate this process but the idea remains the same The basic path for performing this render is as follows 1 Render to an alternative destination 2 Configure those results for use in the final scene render 3 Render the final scene 312 Appendix C The Cocoa API for OpenGL Configuration in Leopard The following sections describe the various techniques available on the Mac for alternative destination rendering and subsequent reuse of those data We ll pri oritize these strategies in terms of their modernity encouraging you to use the most modern of these framebuffer objects whenever possible For a variety of reasons not least of which are simplicity and performance framebuffer objects are the best choice when your hardware supports them However as always with more advanced OpenGL features the most modern features are not al ways supported on the hardware your customers have so choosing fallbacks for those cases may require you to implement some of the other techniques We cover the basics of each below Dive in Framebuffer Objects In this section we describe a modern and widely available technique for in termediate rend
100. we can directly check for the GLEW analog extensions we described before namely those corresponding to our OpenGL extensions This method either succeeds or fails based on the existence of these extensions Back in prepareOpenGL we use these extensions if the method is successful Example 13 11 Query for Shader Extensions Using GLEW BOOL hasShaderExtensions BOOL has_shading FALSE float versionfloat self openGLVersionNumber if versionfloat gt 1 21 BOOL has vs GL TRUE GLEW ARB vertex shader BOOL has fs GL TRUE GLEW ARB fragment shader BOOL has so GL TRUE GLEW ARB shader objects BOOL has lang GL TRUE GLEW ARB shading language 100 has shading has vs amp amp has fs amp amp has so H return has shading That s all there is to do as far as determining whether an extension exists and us ing it with GLEW goes It s simple it s compact and it s comprehensive It s also highly recommended if you have to take the plunge into the depths of OpenGL extensions GLUT Another approach to extension testing and management is to use the GLUT API GLUT performs many features in a cross platform fashion but one of these which is not directly related to window management is extension resolution and binding GLUT provides two entry points that allow quick and easy testing of named extension existence and function binding e glutExtensionSupported EXT strin
101. 1 Performance Again this doubling up strategy increases the asynchronicity between the CPU modifying vertex data and the GPU drawing it We ve prepared an extensive example that you can use to experiment with some of the different modalities of updating and drawing with VBOs in our source examples folder Unlike most of the examples included with this book the vertex submission example contains a relatively large application to cover the various possibilities in submitting vertices efficiently It allows you to switch between a single large VBO for double buffering or two small ones When using a single large VBO you may also turn on the APPLE flush buffer range extension The vertex submission example allows you to increase the complexity of the model to load your system differently as well NSS1ider widgets permit you to modify the width and height of the model which as you can see in the logic will increase the demand of the CPU to compute updated color vertices You may also increase the depth value of the cube This parameter essentially controls how many planes of GL QUADS are drawn By increasing the depth parameter you force the GPU to fill more polygons thereby shifting the perfor mance bottleneck away from the CPU and toward the GPU You should have fun playing with and modifying the vertex submission ex ample and watching the CPU history on OS X s Activity Monitor applica tion which is found in the Applications Util
102. 11 The extension may or may not continue to exist in versions beyond OpenGL X Y Of course not all steps in this process are required nor do all extensions wend their way through this entire process Many never make it past the stage of a vendor defining and implementing a vendor specific extension Only if an ex tension is really useful to a wide variety of developers does it survive to become part of the OpenGL specification One further note Even if you find an extension useful but it s not yet an OpenGL Architecture Review Board extension you may still use it with hope Extension Design and API Integration 255 for its future Even when an extension grows up moving from an EXT to an ARB sometimes from vendor straight to ARB and finally into the specification itself the older ways of identifying it will still exist Specifically the OpenGL specification says this on extension promotion ARB extensions can be promoted to required core features in later revisions of OpenGL When this occurs the extension specifications are merged into the core specification Functions and enumerants that are part of such promoted extensions will have the ARB affix removed GL implementations of such later revisions should continue to export the name strings of promoted extensions in the EXTENSIONS string and continue to sup port the ARB affixed versions of functions and enumerants as a transition aid Now that we ve seen the process that an e
103. 2D glGenTextures GLsizei 1 amp textureID glBindTexture GL TEXTURE 2D textureID const unsigned int texdim 64 const unsigned int nbytes 3 char data texdim texdim nbytes memset data Oxff texdim texdim nbytes unsigned int ii for ii 0 ii texdim texdim ii data ii nbytes 0 Oxff gluBuild2DMipmaps GL_TEXTURE_2D 0 GL_RGB texdim texdim 0 GL_RGB GL_UNSIGNED_BYTE data glTexEnvi GL TEXTURE ENV GL TEXTURE ENV MODE GL REPLACE generate amp bind our framebuffer object to our texture object glGenFramebuffersEXT 1 amp fboID Alternative Rendering Destinations 155 glBindFramebufferEXT GL FRAMEBUFFER EXT fboID glFramebufferTexture2DEXT GL FRAMEBUFFER EXT GL COLOR ATTACHMENTO EXT GL TEXTURE 2D textureID O0 glTexEnvi GL TEXTURE ENV GL TEXTURE ENV MODE GL DECAL glBindFramebufferEXT GL FRAMEBUFFER EXT 0 unbind fbo add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES The OpenGL designers did a pretty good job of keeping the design clean and consistent with that of other objects in the OpenGL system Specifically note the parallels in the setup and configuration of FBOs and texture objects In essence you simply bind the FBO do some rendering and unbind the FBO At that point the textur
104. 4 Window and NIB Ready to be Edited in Leopard Interface Buildet vero t e pe rer RHET Rex eaei 285 Selection Layout and Specialization of a CustomView in Interface Builder 4 isaceeccoesi ete osse temer e ete ns 286 Create and Bind an Instance of our CustomView 287 Custom View Derivation and Project Files in XCode 3 0 287 Teapot Rendered with NSOpenGLView with Subclass 294 Two Views Contexts Shared 0 0 c cece eee eee e ees 303 Final Two Window XCode Contents 00 000005 304 Visible at Launch Enabled sssssesesesesess 304 Context Sharing Two Windows Demonstrating Common Shared Data and Unshared Clear Color Context Data ent eene p Ne ru UR ETE Re Ri ER pk 308 Results of Rendering to an FBO and Texturing a Quad with That Result 0 cc cc cece cence ence e nee 317 Figures xvii This page intentionally left blank Table 2 1 Table 2 2 Table 2 3 Table 3 1 Table 4 1 Table 5 1 Table 6 1 Table 7 1 Table 7 2 Table 7 3 Table 7 4 Table 8 1 Table 8 2 Table 8 3 Table 9 1 Table 9 2 Table 9 3 Table 10 1 Table 11 1 Table 12 1 Table 13 1 Table C 1 Table C 2 Table C 3 Tables Versions of OpenGL in Which Extensions Were Promoted t0 Core OpeBnGE usse apran a E E hd dederit 9 Mac OS Hardware Renderer Support for Versions of OpenGL 12 Timeline of Mac OS X Releases Drawing APIs and Windowing APIs sess 17 Processor Type and Gr
105. 42 63 All Contexts 3 A Figure 11 5 OpenGL Profiler Trace View 232 Chapter 11 Performance Resources View The Resources view allows inspection of textures and vertex or fragment pro grams that have been submitted to the GL API Figure 11 6 The ability to in spect these resources can be immensely valuable in debugging If for instance a texture image has been procedurally generated and has never been viewed prior to being applied as a texture you can evaluate the data in its raw form before its application as a texture to geometry and any transformations it may have undergone in the process This can assist you in deciding whether render ing anomalies are a result of the texture generation loading process or rather are part of the rasterization process 000 Resources b Name Textures Programs Shaders FBOs Renderbuff VBOs VAOs 0 GL TEXTURE 2D Target GL TEXTURE 2D Internal Format GL RGBAB8 Source Format GL RGBA Source Type GL UNSIGNED INT 8 8 8 8 Texture Dimensions 2048x2048 Display Refresh Texture Mipmap Level 0 ZUOm Level E h V e i rmm E RR Source Blend Mode SRC ALPHA B Destination Blend Mode ONE_MINUS_SRC_ALPHA He Background Color amp Opacity gae L Flip Texture 7A Figure 11 6 OpenGL Profiler Resources View Graphics Tools 233 0600 Pixel Format Context Parameter Value Y GL Context ID 0x01815400 GL R
106. 8 The Cocoa API for OpenGL Configuration as we ve written code similar to it earlier in this book The only caveat when writing context sharing code of your own is to keep in mind that any context that is meant to be shared must be compatible with the other contexts Compat ibility implies many things but chiefly that the destination pixel depth color depth and other factors are similar We work around that problem in this ex ample by first exposing a common pixel format through the pixelFormat method and then using that method to construct our pixel format and context for each window s view Let s revisit the code we used for our custom OpenGL view example for initial ization and setup This code with one minor twist does everything we need and is presented in Example C 7 Example 8 7 Initialization of an OpenGL View with a Shared Context implementation MyView id initWithFrame NSRect frameRect NSLog MyView initWithFrame if self super initWithFrame frameRect nil _pixelformat SharedContext instance pixelFormat if _pixelformat nil NSLog No valid OpenGL pixel format matching attributes specified at this point we d want to try different sets of pixelformat attributes until we got a match or decided we couldn t create a proper working environment for our application init the context for later construction _context nil return
107. A444Bit 0x00000080 16 argb bit pixel A 15 12 R 11 8 G 7 4 B 3 0 kCGLRGB444A8Bit 0x00000100 8 16 argb bit pixel A 7 0 R 11 8 G 7 4 B 3 0 T kKCGLRGB555Bit 0x00000200 16 rgb bit pixel R 14 10 G 9 5 B 4 0 kCGLARGB1555Bit 0x00000400 16 argb bit pixel A 15 R 14 10 G 9 5 B 4 0 kCGLRGB555A8Bit 0x00000800 8 16 argb bit pixel A 7 0 R 14 10 G 9 5 B 4 0 y kCGLRGB565Bit 0x00001000 16 rgb bit pixel R 15 11 G 10 5 B 4 0 kCGLRGB565A8Bit 0x00002000 8 16 argb bit pixel A 7 0 R 15 11 G 10 5 B 4 0 kCGLRGB888Bit 0x00004000 32 rgb bit pixel R 23 16 G 15 8 B 7 0 kCGLARGB8888Bit 0x00008000 32 argb bit pixel A 31 24 R 23 16 G 15 8 B 7 0 y kCGLRGB888A8Bit 0x00010000 8 32 argb bit pixel A 7 0 R 23 16 G 15 8 B 7 0 y kCGLRGB101010Bit 0x00020000 32 rgb bit pixel R 29 20 G 19 10 B 9 0 Ey kCGLARGB2101010Bit 0x00040000 32 argb bit pixel A 31 30 R 29 20 G 19 10 B 9 0 kCGLRGB101010 A8Bit 0x00080000 8 32 argb bit pixel A 7 0 R 29 20 G 19 10 B 9 0 kCGLRGB121212Bit 0x00100000 48 rgb bit pixel R 35 24 G 23 12 B 11 0 x4 74 Chapter 6 The CGL API for OpenGL Configuration kCGLARGB12121212Bit 0x00200000 48 argb bit pixel A 47 36 R 35 24 G 23 12 B 11 0 kCGLRGB161616Bit 0x00400000 64 rgb bit pixel R 63 48 G 47 32 B 31 16 kCGLRGBA16161616Bit 0x00800000 64 argb bit pixel R 63 48 G 47 32 B 31 16 A 15 0 kCGLRGBFlo
108. APPLE totalBytes vertexData glFlushVertexArrayRangeAPPLE totalBytes vertexData Create drawing fence glGenFencesAPPLE 1 amp drawingFence Update routine for animating vertices in buffer 218 Chapter 11 Performance void UpdateBuffer GLuint fence GLint first GLint length GLfloat currentVertexBuffer int i Insure that we re through drawing with the memory holding the vertices we re about to update glFinishFenceAPPLE fence for i 0 i lt length i Modify contents of currentVertexBuffer here Mark our updated region as modified so OpenGL knows how to establish coherency for drawing glFlushVertexArrayRangeAPPLE length currentVertexBuffer first 3 Typical draw routine for setting up double buffering VAR void Draw static unsigned int currentBuffer 0 if currentBuffer glDrawArrays GL_QUADS 0 VERTICES 2 glSetFenceAPPLE drawingFencel The first half of the buffer is now drawing so update the second half UpdateBuffer drawingFence2 VERTICES 2 VERTICES 2 vertexData else glDrawArrays GL QUADS VERTICES 2 VERTICES 2 glSetFenceAPPLE drawingFence2 The second half of the buffer is now drawing so update the first half UpdateBuffer drawingFencel 0 VERTICES 2 vertexData currentBuffer currentBuffer Typical clean up state reset routine for a VAR implementation void Clean
109. Buffers 1 amp bufID glBindBuffer GL ARRAY BUFFER bufID Supply data to the VBO 212 Chapter 11 Performance glBufferData GL ARRAY BUFFER VERTEX CT vertexBuffer GL STATIC DRAW glEnableClientState GL VERTEX ARRAY glVertexPointer 3 GL FLOAT 0 char NULL Now the VBO is initialized when we re ready to draw Bind the VBO for drawing glBindBuffer GL ARRAY BUFFER bufID Draw triangle strip using n vertices from the VBO starting at index 0 glDrawArrays GL TRIANGLE STRIP 0 n glFlush Notice that the g1BufferData call specifies GL STATIC DRAW to charac terize the usage of the VBO in Example 11 6 Notice too that the vertex array nomenclature is used to characterize the memory layout of the VBO in the same manner that it was used for vertex arrays In this case however glVertexPointer is used not to specify the vertex data but rather to specify an offset into the VBO data For VBO usage in this example we re simply specifying a zero offset and relying on the offsets implicit in the glDrawArrays call to access and draw the data of interest Modifying data in a VBO it s VBOs biggest advantage over display lists is done using one of three methods glMap UnmapBuffer glBufferData or glBufferSubData In the case of glMap UnmapBuffer when the buffer is mapped it may be modified by the OpenGL application without concern for the state of drawing on that
110. CGL Core Graphics Figure 5 1 OpenGL Configuration API Dependencies Even these calls may be unnecessary because Carbon and AppKit provide an abstraction for all of the window server integration your API will likely need Exceptions to this rule may arise when you are controlling the event stream directly or when you are requesting or setting windowing system wide parame ters such as obtaining the ID of the main display setting the display pixel depth or resolution or modifying display gamma values The dependency layering gets more interesting when you consider that AGL and AppKit both rely on the CGL interface to OpenGL itself To summarize AppKit AGL and CGL depend on CoreGraphics and AppKit and AGL depend on CGL This means the dependency relationship isn t a simple layering It looks more like the hierarchy shown in Figure 5 1 Note that Figure 5 1 doesn t reveal anything about the layout of the directory structure of the frameworks within the System Library Frameworks di rectory of OS X AGL and AppKit are easy to understand They have their own frameworks and reside in the System Library Frameworks directory CGL is part of OpenGL and therefore is contained in the System Library Frameworks OpenGL framework directory Core Graphics is perhaps the most difficult to find Ruining the surprise you can find this framework in the System Library Frameworks ApplicationServices framework frameworks directory You
111. Context contextObj Now that we have a context populate the rendererInfoObj instance step 3 CGLQueryRendererInfo displayMask amp rendererInfoObj amp rendererCount Iterate over all of the renderers contained in the rendererInfoObj instance step 4 for i 0 i rendererCount i CGLDescribeRenderer rendererInfoObj i kCGLRPRendererID amp rendererID CGLDescribeRenderer rendererInfoObj i kCGLRPVideoMemory amp vram CGLDescribeRenderer rendererInfoObj i kCGLRPTextureMemory amp texMem printf Renderer ID 0x lx n t 1l6s 1d b 0 2 MB n t 1l6s ld b 0 2f MB n n rendererID Video Memory vram vram 1024 0f 1024 0f Texture Memory texMem texMem 1024 0f 1024 0f return 0 Example 6 2 shows the simplest and most commonly used form of each of the steps Now let s look at some of the options and details where the four steps could vary Context Management 69 Step 1 Obtaining Display IDs The first step is to obtain the display ID associated with the renderer you re interested in inspecting The Quartz Services API provides several routines for obtaining display IDs CGMainDisplayID CGGetOnlineDisplayList CGGetDisplaysWithPoint e e e CGGetActiveDisplayList e e CGGetDisplaysWithRect CGMainDisplayID is the simplest of these calls Its prototype is CGDirectDisplayID CGMainDisplayID void In a sense a c
112. CreatePBuf fer function In addition to the context association CGLSet PBuf fer configures the current face and level settings for pbuffers with targets of the respective types The virtualScreen argument to CGLSetPBuffer requires the most care when setting it Recall that there is one renderer per virtual screen This argu ment serves to establish the renderer to be used when rendering to this pbuffer Often you ll wish to use the same renderer that is associated with your CGL context to render to your pbuffer This can be done inline with a simple call to CGLGetVirtualScreen CGLGetVirtualScreen CGLContextObj ctx long screen Using the same renderer as your main rendering context is essential for best performance when texturing from your pbuffer If the renderer used for your context and pbuffer differs it will likely result in a copy of the texture level data from the local storage of one renderer to the other Pbuffers hold a lot of data so this copy may well cause considerable performance and memory problems for your applications Once a pbuffer has been associated with a CGL context for rendering you can call CGLError CGLGetPBuffer CGLContextObj ctx CGLPBufferObj pbuffer unsigned long face long mipmapLevel long screen to retrieve information about the pbuffer associated with ctx If the target of the pbuffer is GL TEXTURE CUBE MAP face will be set to the cube map face of the pbuffer Otherwise face will
113. E Select pixel formats with supersample buffers Type n a n a Default n a Policy Hint prefer 98 Chapter 7 The AGL API for OpenGL Configuration Token Description AGL_SAMPLE_ALPHA Request alpha filtering Type n a n a Default n a Policy n a AGL_RENDERER_ID Choose renderer by a specific ID Type Unsigned integer One of AGL RENDERER ID tokens Default n a Policy Exact AGL SINGLE RENDERER Choose a single renderer for all screens Type Boolean GL_TRUE Default n a Policy n a AGL NO RECOVI csl K Disable all failure recovery systems The OpenGL driver layer will fall back to other renderers if a drawable or surface cannot be attached typically due to insufficient graphics memory resources AGL would in this failure case usually switch to another renderer however specifying GL TRUE to this option will prevent a failover to a software renderer from occurring in this instance Type Boolean GL_TRUE Disable failure modes GL_FALSE Fail to alternate renderers Default n a Policy Exact AGL_ACCELERATED Choose a hardware accelerated renderer Note that in a multiscreen system configuration it s possible that you may not get windows that span because a spanning window usually causes OpenGL to choose the software renderer Type Boolean GL
114. ENDERER ATI Radeon X1600 OpenGL Engine GL VENDOR ATI Technologies Inc GL_VERSION 2 0 ATI 1 4 42 kCGLPFAAccelerated GL TRUE kCGLPFAAccumSize 0 kCGLPFAAIIRenderers GL_FALSE kCGLPFAAIphaSize 8 kCGLPFAAuxBuffers 0 kCGLPFAAuxDepthStencil GL_FALSE kCGLPFABackingStore GL_FALSE kCGLPFAClosestPolicy GL_FALSE kCGLPFAColorFloat GL_FALSE kCGLPFAColorSize 32 kCGLPFACompliant GL_TRUE kCGLPFADepthSize 16 kCGLPFADisplayMask 0x00000001 1 kCGLPFADoubleBuffer GL_TRUE kCGLPFAFullScreen GL_FALSE kCGLPFAMPSafe GL_TRUE kCGLPFAMaximum Policy GL_FALSE 2 kCGLPFAMinimumPolicy GL FALSE I l7 71 DE ARM MFC unnm Cc Tniic Figure 11 7 OpenGL Pixel Format View Pixel Format View The Pixel Format view is a nice time saver It shows a comprehensive list of pixel format attributes for each context of the currently attached or launched application Figure 11 7 Buffer View The Buffer view allows inspection of the various planes that constitute a GL framebuffer Figure 11 8 At present these include the back buffer the alpha buffer the depth buffer and the stencil buffer It will be interesting to see how this view changes with the use of framebuffer objects and stereo rendering Scripts View The Scripts view allows composition and saving of scripts Figure 11 9 These are attached to and executed before or after breakpoints 234 Chapter 11 Performance 008 Back Buffer c All Contexts Save Image Context ID Figure 11 8
115. EXTURE 2D textureID glCopyTexSubImage2D GL TEXTURE 2D 0 0 0 0 0 64 64 void draw t glClearColor 0 0 0 5 0 8 1 0 glClear GL COLOR BUFFER BIT glMatrixMode GL MODELVIEW glLoadIdentity glRotatef 5 0 0 0 0 0 1 0 glBindTexture GL TEXTURE 2D textureID giColor4d 0 0 1 0 0 0 1 0 giRectd 0 1 0 1 0 9 0 9 J7 aglSwapBuffers context We ll spend a bit more time discussing this technique its strengths its weak nesses and its applicability in Chapter 8 but for now a few words on what s happening should suffice The initialization code performs two steps 1 as seen in our prior examples setup of the projection matrix and 2 a simple texture generation all white and load of that texture That s all we do to prepare a tex ture for usage later The drawTexture function performs our rendering into our texture and it s as simple as it always has been a clear to yellow tran sition The last step in this function is the workhorse of this technique and simply copies the contents of the active framebuffer read target set through glReadBuf fer to the texture specified We use the g1TexSubImage2D fla vor of texture copy because it s the most efficient way to replace some or all of a texture with updated image pixels Finally we see in Example 7 10 the draw code which does the same draw as in our earlier AGL examples This time however it binds this texture before
116. FAMinimumPolicy NULL CGLPixelFormatObj pixelFormatObj long numPixelFormats CGLError cglError cglError CGLChoosePixelFormat attribs amp pixelFormatObj amp numPixelFormats if cglError kCGLNoError printf Unable to create pixel format Error is 0x 0x n cglError Notice that the pixel format attribute constants are prefaced with kCGLPFA The k specifies that the value is a global constant CGL well that just means CGL PFA stands for pixel format attribute Pixel format attributes are scalars that may be integer quantities or Boolean val ues In our example KCGLPFADoubleBuf fer and kCGLPFAMinimumPolicy are Boolean values There s a certain asymmetry in specifying Boolean versus non Boolean values but you can t argue that it doesn t save on typing Rather 58 Chapter 6 The CGL API for OpenGL Configuration than having a value of true or false explicitly listed for Boolean attributes they are simply specified when true and not specified when false The design of Apple s pixel format API is subtractive in nature That is you can think of your attribute array as a set of constraints for the list of possible pixel formats that will match rather than trying to build up a pixel format containing only these features typedef enum _CGLPixelFormatAttribute kCGLPFAAllRenderers L kCGLPFAOffScreen 53 kCGLPFAFullScreen 54 kCGLPFAAuxDep
117. Figures 619 9k t RR RESP APR UU PEU HR Reed bred rea xv List ot Tables awe scores vse iad eo egt veg i ohod woe es sto Revie eae p Ud UE xix List of Examples ysis ebur Ne hers eR S RECS aus dracon ENNQPHEUER SERE EENEI xxi Preface dos dise one tates ORs ceed Man datadeeadaadasadaeaes PT XXV Acknowledgr nts ec cetrere E eae unceaad atta ne RE han limehanet DEN xxix About the Authors ca is ie e efe ere moo AR Mahan DOE REETORIAQN NR Xxxi Chapter 1 Mac OpenGL Introduction 1 Why the Mac eean ders ace ee hase eee ae eee NNUS 2 Whiy OpenGL xi none ibas e dc dc e c hibreiarmd ee fere E dd 3 The Book 12 en tr RR b Re UR P beqa d REESE MUN EDS PeWd 4 Chapter 2 OpenGL Architecture on OS X 7 ONVerVIeW reado abenia bebe x te dbide be b e RewRebU4ewRe idee rien 7 About OpenGL RERBA ns seg adaseegeensee neds 7 Mac OS X Implementation of the OpenGL Specification 11 OpenGL Feature Support 0 cece e eee EEA 14 nudum E 15 The Mac OS OpenGL Plug In Architecture 0004 17 Eendeters2 6 ub TR eoe eer ue vet ed ee es 18 lic EM 21 SUMMATY ERE 21 Chapter 3 Mac Hardware Architecture 23 Overview eesi daten iue ub deb d Rede Rice IA IEEE IT RT 23 Data Flow and Limitations sese 24 Problem Donialns v3 e 9E ee RR RESI Mae IPODPeROPIES 27 Know Thine OS Requirements 0 cece eee eee eee 27 CPU and Clock Rat 1 22192 meg bie REPRISE RISIRRIIDRRS PUR 28 vii Chapter 4 C
118. Format pixelFormat aglSetCurrentContext context window creation CreateNewWindow kDocumentWindowClass kWindowStandardDocumentAttributes kWindowStandardHandlerAttribute amp windowRect amp window Alternative Rendering Destinations 111 SetWindowTitleWithCFString window CFSTR AGL PBuffer Texture ActivateWindow window true ShowWindow window bind context to window aglSetDrawable context GetWindowPort window aglUpdateContext context initialize window context amp draw window GLuint texid init context pbuffer amp texid drawWindow context texid stub event loop sleep 4 0 cleanup and exit aglSetCurrentContext NULL aglDestroyContext context aglDestroyContext pbContext aglDestroyPBuffer pbuffer return 0 At some point in the future when you re ready to use this result as data ref erence the contents as the image portion of a texture ag1TexlImageP Buffer Example 7 9 shows this process happening for our main OpenGL windowed AGL context This method shows the key step in pbuffer usage CGL or AGL documented fully in Chapter 6 when generating a new texture ID Example 7 9 OpenGL Context Initialization Referencing a Pbuffer as the Texture void init AGLContext context AGLPbuffer pbuffer GLuint textureID Initialize the projection matrix glMatrixMode GL PROJECTION glOrtho 1 Ly 1 Deve
119. GL PBuffer Texture Figure 7 4 AGL Pbuffer Example Results Alternative Rendering Destinations 113 Render to Copy to Texture In this section we describe a very common and widely available technique known as render to texture Render to texture is as simple as it sounds You simply render your intermediate scene copy it to a texture and then later use that texture in your final render The method is simple and concise with the only downside being the copy of pixels phase Of course you must deal with some details concerning how you target the texture into which you want to render and in some cases how you move pixels around the sys tem and into your final texture Nevertheless on the whole this process is largely as simple as described This technique is interesting because it is widely available and offers relatively high performance It has some problems too It s not as clean as the most modern OpenGL technique of framebuffer objects and there may be extra data copies Overall though it works pretty well Perfor mance is pretty good too albeit not as consistently good as using framebuffer objects Sometimes you may run into problems on different cards from differ ent vendors where this technique is actually moderately expensive However if you can t use framebuffer objects this method is a good option We ll now explore the details of this technique and look at some example code and results Because we re only g
120. GL RENDERER ID 99t AGL_RGBA 95t AGL ROBUST 100t AGL SAMPLE ALPHA 99t AGL SAMPLE BUFFERS ARB 98t AGL SAMPLES ARB 98t AGL SINGLE RENDERER 99t AGL STENCIL SIZE 96t AGL STEREO 95t AGL SUPERSAMPLE 98t AGL VIRTUAL SCREEN 100t AGL_WINDOW 100t aglChoosePixelFormat 93 94 95t 101t aglCreatePBuffer 110t agIDescribePBuffer 110t aglDestroyPBuffer 110t aglGetPBuffer 110t aglSetPBuffer 110t aglTexImagePBuffer 110t AGP see Advanced Graphics Port alignment pixel data 224 25 texture 225 26 alternative rendering destinations 109 13 312 22 AltiVec engines 28 42 43 API layers 15 16 16f APIs and surfaces 15 16 cross platform 48 49 integration with 254 55 Mac only 46 49 X11 277 79 325 AppkKit 16 16f 20 122 33 123f 124f 125f 126f Apple Fence 216 17 Apple Float Renderer 13 Apple Generic Renderer 13 Apple OpenGL 16 16f 47 alternative rendering destinations in 109 13 context sharing in 107 9 framebuffer objects in 117 19 full screen application in 91 101 pbuffers in 110 13 110t 113f 208t renderers in 104 7 107t software layering in 90 91 91f 91t windowed application in 101 4 Apple Texture Range 205 7 Apple Vertex Array Range 205 7 APPLE flush_buffer_range 220 21 APPLE_vertex_array_range 217 19 ARB see Architecture Review Board ARB Architecture Review Board ARB and extensions 8 9 creation of 8 asynchronous calls 204 7 B best practice axioms 196 201 BG
121. GL REPLACE lBindTexture GL TEXTURE 2D 0 unbind texture Q generate amp bind our framebuffer object to our texture object lGenFramebuffersEXT 1 amp fboID IBindFramebufferEXT GL FRAMEBUFFER EXT fboID IFramebufferTexture2DEXT GL FRAMEBUFFER EXT GL COLOR ATTACHMENTO EXT GL TEXTURE 2D textureID 0 glBindFramebufferEXT GL FRAMEBUFFER EXT 0 unbind fbo Q Qu void drawFBO glBindFramebufferEXT GL FRAMEBUFFER EXT fboID bind fbo glClearColor 1 0 1 0 0 0 1 0 glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT glBindFramebufferEXT GL FRAMEBUFFER EXT 0 unbind fbo void draw IClearColor 0 0 0 5 0 8 1 0 IClear GL COLOR BUFFER BIT IMatrixMode GL MODELVIEW LLoadIdentity IRotatef 5 0 0 0 0 0 1 0 Q Q Q QQ IBindTexture GL TEXTURE 2D textureID IColor4d 0 0 1 0 0 0 1 0 IRectd 0 1 0 1 0 9 0 9 Q Q Q aglSwapBuffers context 118 Chapter 7 The AGL API for OpenGL Configuration 000 AGL Window Figure 7 6 Results of Rendering to a Framebuffer Object and Texturing a Quad with That Result in AGL Before we leave the topic of framebuffer objects we d like to point out a few reasons why they are superior to other forms of indirect rendering First framebuffer objects consist of memory allocated on the graphics card itself that is directly usable in its target form for example as a texture T
122. GL and AGL head ers as in Example 7 1 Example 7 1 Headers for OpenGL and AGL include lt OpenGL OpenGL h gt include AGL agl h We ll also configure a pair of standard methods we ll use in a variety of exam ples to initialize our OpenGL state once we ve got a context and to draw in our main loop With one minor exception these methods look like other initializa tion and draw methods you ve seen other places Example 7 2 shows these two routines and their resultant bodies Example 7 2 AGL OpenGL Initialization and Draw Functions void initGLstate glMatrixMode GL PROJECTION gdlOrtho 0 0 1 0 0 0 1 0 1 0 1 0 glClearColor 0 0 0 5 0 8 1 0 void draw void glClear GL COLOR BUFFER BIT glMatrixMode GL MODELVIEW glLoadIdentity glRotatef 5 0 0 0 0 0 1 0 glColor4d 0 0 1 0 0 0 1 0 giRectd 0 1 0 1 0 9 0 9 aglSwapBuffers context The difference between this code and code you ve seen before and will see again later is the method used to swap the implicitly double buffered pixel format we re using The call aglSwapBuffers takes one argument the AGL context to be swapped which for our purposes is declared in a globally accessible variable outside this routine We also have an externally declared 92 Chapter 7 The AGL API for OpenGL Configuration pixel format that we use elsewhere too That s all there is to our initialization and draw methods t
123. HELM I Selecting a Renderer i ecesse se rk ee E EE RR PRESE RERBEEES viii Contents 33 33 33 34 34 38 39 41 42 42 43 45 46 46 48 49 49 51 53 Chapter 7 Chapter 8 Context Management 0 ce cece cece eee ene 63 Renderer Information m erta cease tt e Re secs meena PEERS ENSE 68 Sharing OpenGL Objects Across CGL Contexts 005 76 Drtawabl sus 2 chose bexodetia ene EE UR ARR ROREM REATO 77 Pixel Butlerssc0 ctcacitagchenei eee hed lends cscestie REND RREID REY 78 Off Screen Drawables icc re tren RR pr RE naked se 82 Full Screen Drawables cece cece eee ence eee eens 82 Virtual Screen Management cesses 83 Global CGL State Functions 0 00 e cece eee ees 84 Using CG LAMacrosiscs oc ujus tenia x E E A abana Ee gies 86 SUMMANI do docecsdar dade de siege aidan RR RR D RO RUD CR naan 86 The AGL API for OpenGL Configuration 89 wg RIT 89 Software Layerlg nere EID Dr REUUPER ERECTA Eid gne 90 Pixel Format and Context 0 cece e eee e eee ene eee 91 Full Screen Application 0 0 c cece eee eee e 92 Windowed Application 4 sc0 c c50eeeenes bee bee RR e EET 101 DUMMALY orrenda esne Messrs winsdas RUE REP eR ERNLRREC RU PP 104 Additional Topics 1 24 2 03 x debi us s Shee ee os a Sate Pe Sas 104 Rendefergsc cene kea a eE ems Reset REC p Reb es 104 Context Shafipeicisbkber Bee a a EPRRPASS 107 Alte
124. IRageProID kCGLRendererATIRadeon85001ID kCGLRendererATIRadeon97001D kCGLRendererGeForce2MXID Pixel Format Selection 61 kCGLRendererGeForce3ID kCGLRendererGeForceFXID kCGLRendererVTBladeXP2ID kCGLRendererIntel900ID kCGLRendererMesa3DFXID The star of this show is the Apple software renderer which was released as part of Tiger If you wish to use or test certain functionality that your hard ware doesn t support you can use this renderer The new software renderer is specified using kCGLRendererGenericFloatID You may hear this ren derer described as the float renderer because of its support for floating point framebuffers and pixel formats This software renderer is highly tuned for the Mac platform It uses a great deal of hand tuned and hand scheduled PowerPC and Intel assembly The performance of this renderer though not comparable to that of a dedicated hardware renderer is quite astonishing The software renderer is a great tool to use when you are debugging your appli cation If for instance you believe your OpenGL logic is correct yet the render ing doesn t appear correct try changing your renderer to the software renderer The software renderer allows you to cross check the vendor specific renderers to determine whether your application has a bug that is specific to a certain graphics card If you see correct results in the software renderer but not in the vendor specific renderer or vice versa it s time to file
125. If you re not initially a member of our target audience for this book we d sug gest that you give the Mac a try developing a modern application from start to finish and see if you don t agree Why OpenGL If you re reading this book chances are that you already know why you are us ing OpenGL But if you re reading this book and trying to make some decisions about which 3D API to use we ll say a few words on why you should consider OpenGL The reasons are very similar to those as to why you d choose the Mac platform To reiterate ease of development ease of use and solid stylish tools make the Mac development process easy OpenGL is no exception OpenGL has a long history like the Mac Although the history of OpenGL is covered in more detail later in the book here s an abbreviated version OpenGL was developed from the experience and foundation of IrisGL an API for 3D graphics first developed by SGI OpenGL was developed to bring a fresh set of eyes to the task of creating a clean modern and portable graphics API The designers of OpenGL did an excellent job with an API that is nicely orthogonal in function high performance in execution and extensible in design It should be mentioned too that OpenGL is the only graphics API that exists on virtually every hardware platform you might want to develop from cell phone to supercomputer OpenGL exists on operating systems from Symbian to Mac OS X and many others No other graphic
126. Image 123 D calls Let s provide an overview of this process and then translate it into code 1 Create and configure a texture glGenTextures glBindTexture glTexImage2D glTexEnv glTexParameter 2 Bind that texture g1BindTexture 3 Draw using that texture g1lBegin glTexCoord2f glEng This book isn t meant to teach you fundamental OpenGL rendering techniques but the preceding sequence is essential to understand for two key reasons First texturing is the primary means by which you ll access the data you render to off screen surfaces and the primary way by which you ll re render those data in another form Second textures are chunks of data that are intimately bound to OpenGL contexts and we ll need to know how to share data among contexts if we want to use textures rendered in one context in another context Essentially this section is a segue into sharing contexts which is the topic we explore next Context Sharing A key concept in many aspects of OpenGL rendering on the Mac or otherwise is what lives in an OpenGL context and how to efficiently use that data for multiple purposes Essentially a context contains all OpenGL state data associated with rendering such as the viewport dimensions active color and rendering modes A context also includes much heavier weight items such as texture objects and vertex objects Large objects consume nontrivial amounts of memory on a graphics card so the desig
127. Jaguar Jaguar was released in August 2002 and proved to be a really solid fast and finally almost complete version of Mac OS X In the span of a little more than a year and a half Mac OS X had improved from a fast but new operating system to a stable fast and widely supported operating system Its performance had improved dramatically too Among the performance features added was an en hancement to its graphics layer Quartz known as Quartz Extreme Quartz Ex treme promised and mostly delivered a great performance boost by offloading numerous UI elements to the graphics hardware This was the first step Apple would publicly take that yielded insight into how the UI and window manager would evolve in the future 10 3 Panther Panther was released in October 2003 Apple continued to release numerous performance and feature enhancements but among the most notable for graph ics developers was the acceleration of UI elements through hardware GPU rendering Version 10 3 added a few other features for OpenGL developers in cluding the ability to share a full screen context with a windowed context on the Mac As we ve described earlier context sharing means that resources in one context such as textures and VBOs can be used by another context with out incurring extra memory overhead Version 10 3 s ability to share full and windowed contexts meant a resource optimization for applications that needed both modes to be supported Anot
128. Jase eeend P qUbp EHE RADAR 207 THOUGH PUL 2e eor Eee DEEP RI CDU Parse cata sie 209 Efficient Data Management Using Mac OpenGL 209 Efficient Handling of Vertex Data llle 210 A Brief History of the Evolution of Submitting Vertices uBncl m 210 Which Methods Should You Use to Submit Vertices lor DrawIng hzicerseeeuee Ee ra roei E CREER debe VERE HE 213 Apple s Methods of Vertex Submission Past and Present 214 Efficient Handling of Texture Data esses 221 Pormats and Lypess sa zeescet ee e a ea EE EE S 221 Pixel Pipeline and Imaging Subset State 00 223 Alignment Considerations eee 224 dio EMT 225 Compressed Textlres 0 20 06 52 os ee e f Der der sdededa Pr p us 225 Alignment Considerations esee 225 DNAd iic tb epe e RI PRRRERIPe Rege D eipxe t Pe bpepb Ie RES 226 TOO Snee ITEM 226 System Todlsisis ici cneeis serat De rE ETEA IE bade TE TEP 227 Graphics TONS s usce sarees oria Gute dicate Dated eon n edle etn 228 OpenGL Profilet nsare rarae nanne P Xl EE a ae E e beni 228 OpenGL Driver Monitor 20 lt iqsecnuseeueehsekebauneeneeaseee sd 235 PII So roasebobU epu e cem bees ae ast reU ere pec Eee 236 Putting It All Togethers seek eue Se E ERE ERR 237 About Please Tune Me 0 20 cee cece eee eee 237 Please Tune Me Tari iemm REG RR RPXEEREAG N ined URBIUM E ES 238 Please Tune ME 2 er ema mem sins ace EIS RII digs EEES 240 Please Tune Me 3
129. LVersionNumber if versionfloat gt 1 21 NSDictionary extdict createExtensionDictionary BOOL has vs extdict objectForKey Q GL ARB vertex shader nil BOOL has fs extdict objectForKey Q GL ARB fragment shader nil BOOL has so extdict objectForKey Q GL ARB shader objects nil BOOL has lang extdict objectForKey Q GL ARB shading language 100 nil has shading has vs amp amp has fs amp amp has so H return has shading Example 13 4 Creating a Dictionary of All Extensions NSDictionary createExtensionDictionary t NSString extstring NSString stringWithUTF8String char glGetString GL EXTENSIONS NSArray extensions extstring componentsSeparatedByString NSDictionary extdict NSDictionary dictionaryWithObjects extensions forKeys extensions return extdict 264 Chapter 13 OpenGL Extensions One final note about extensions that export API entries What happens at run time We ve seen how we check for the validity of a particular extension at com pile link and runtimes but where are the symbols defined on the platform on which we re now running What guarantees do we have about symbol defini tions being valid On the Mac there s an implicit guarantee that if you have the extension defined and are linked with the OpenGL library you ll have proper symbol resolution for all symbols exported by that extension That s all
130. OVeFVieWu sois xdi tipp 99 901m 334199 iP ai eTi 3 NSOpenGhView srs 2d volete Saeed INNSWMIeWis e ie Dee muss oun Lt eee manna DLE E xii Contents 253 253 254 256 257 257 262 269 270 273 275 277 277 278 279 281 Additional Topics s 0tss neces yaveees de EXT RE E EE eC E teas 300 Manipulating Images and Pixels in OpenGL 300 Context Sharing ist cad opis 3e IU a e PRISE ME dieses 301 PulbScreen Surfaces essence E eR disnei o RAN RA S ED 308 Display Capture lm E BREL REIHE Bl pe SC T RAD C REDPEEAS 309 byent HandliBg sescenti ro pec nar wee REREREU HESS 310 Alternative Rendering Destinations lesse esee 312 Prameba tter Objects icce sirare e RR dae Rr x REER S E EE SER 313 Clopystos Texture ioco nt anette as thee aia tease E E 318 Pbuffer Off Screen and Other Intermediate Targets 321 SUMIMATY sive leisrzacre Re l3 RA EROR Rei ca EEEE ia Peden dh 322 Appendix D Bibliography 323 ll c PUTAS 325 Contents xiii This page intentionally left blank Figure 2 1 Figure 2 2 Figure 2 3 Figure 3 1 Figure 4 1 Figure 5 1 Figure 5 2 Figure 6 1 Figure 7 1 Figure 7 2 Figure 7 3 Figure 7 4 Figure 7 5 Figure 7 6 Figure 8 1 Figure 8 2 Figure 8 3 Figure 8 4 Figure 8 5 Figure 8 6 Figure 8 7 Figure 8 8 Figure 8 9 Figure 8 10 Figure 8 11 Figure 8 12 Figures OpenGL Version History Timeline 000 e eee eee 9 AGL CGL
131. OpenGL Programming on Mac OS X Robert P Kuehne s J D Sullivan OpenGL Programming on Mac OS X This page intentionally left blank OpenGL Programming on Mac OS X Architecture Performance and Integration Robert P Kuehne J D Sullivan vv Addison d Upper Saddle Rive iy P no e In da nape a dat Fra New York e Toronto ie Lon Paris e Madrid ich e Capetown e Sydney e s ie e Sing un Mon City Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks Where those designations appear in this book and the publisher was aware of a trademark claim the designations have been printed with initial capital letters or in all capitals The authors and publisher have taken care in the preparation of this book but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein The publisher offers excellent discounts on this book when ordered in quantity for bulk purchases or special sales which may include electronic versions and or custom covers and content particular to your business training goals marketing focus and branding interests For more information please contact U S Corporate and Government Sales 800 382 3419 corpsales pearsontechgroup com For sales outsi
132. OpenGL Version 2 1 OpenGL Shading Language Second Edition Randi Rost 0 321 33489 2 OpenGL Shading Language Second Edition is the experi enced application programmer s guide to writing shaders Part reference part tutorial this book explains the shift from fixed functionality graphics hardware to the new era of programmable graphics hardware and the additions to the OpenGL API that support it OpenGL Library Fourth Edition 0 321 51432 7 This special boxed set contains both OpenGL Programming Guide Sixth Edition and OpenGL Shading Language Second Edition Richard S Wright Jr Benjamin Lipchak Nicholas Haemel OpenGL Distilled Paul Martz lBpencr Programming on Mac OS X Architecture Performance and Integration Robert P Kuehne amp J D Sullivan OpenGL SuperBible Fourth Edition Comprehensive Tutorial and Reference Richard S Wright Jr Benjamin Lipchak and Nicholas Haemel 0 321 49882 8 OpenGL SuperBible Fourth Edition offers compre hensive coverage of applying and using OpenGL in your day to day work It covers topics such as OpenGL ES programming for handhelds and OpenGL implementations on multiple platforms including Windows Mac OS X and Linux UNIX OpenGL Distilled Paul Martz 0 321 33679 8 OpenGL Distilled provides the fundamental information you need to start programming 3D graphics from set ting up an OpenGL development environment to creating re
133. PACK ALIGNMENT 1 unsigned char bmdata bitmap bitmapData NSLog bmd d d n imageArea size width imageArea size height glReadPixels 0 0 imageArea size width imageArea size height GL_RGB GL_UNSIGNED_BYTE bmdata self writeBitmapImageRep bitmap toFile tmp test_bitmap png return self convertBitmapImageRepToImage bitmap The most complex call here is the one made to initialize our NSBitmapImageRep In initWithBitmapDataPlanes we set the image width height bits per component components per pixel interleaved data and image representation but we don t fill in the data contents The call in this for mat with the data component set to NULL makes the representation allocate space but not fill it in To fill in the data we use the traditional formulation of glReadPixels We call this method with the same parameters size com ponents bits per pixel with which we configured our NSBitmapImageRep allowing us to read directly into the bitmap data store pointed to by bitmap bitmapData Next we convert our bitmap into an NSImage us ing another function we ll present in Example 10 8 Example 10 8 Converting a Bitmap to an NSImage NSImage convertBitmapImageRepToImage NSBitmapImageRep bitmap Create a new Image and draw the bitmap into it NSSize size bitmap size NSImage newlmage NSImage alloc initWithSize size newImag
134. RA pixel format 10t bitmap to NSImage 183 84 blend squaring 10t blending logical operations 9t Breakpoints view 229 31 230f buffer flush 205 7 220 21 buffer sizing 59 60 Buffer view 234 235f bugs in OS 39 41 bus bandwidth 30 graphics 29 30 30t memory 29 C C programming language 2 89 90 C 89 90 cache in CPU 25 CAD limitations 27 CAE limitations 27 central processing unit CPU and Activity Monitor 227 and clock rate 28 cache 25 326 Index idle time minimization 204 7 northbridge of 23 24 24f southbridge of 24 24f transistors in 23 CGL see Core OpenGL CGL CGLChoosePixelFormat 58 59 CGLFlushDrawable 230 231 32 CGLRendererInfoObj 72 Cheetah see also OS X release of 17t clock rate 28 Cocoa API in Leopard 283 322 Cocoa Image 174 84 178f 179t Cocoa OpenGL 47 48 color models X11 279 context enables 64 65 context management in CGL 63 68 context parameters 64 65 context sharing in AGL 107 9 in OpenGL 141 49 143f 144f in OpenGL Leopard 301 8 copy to texture 114 17 158 61 318 21 Core Graphics 16 49 Core OpenGL CGL 16 16f 18 47 53 54 54f 55 87 buffer sizing 59 60 ChoosePixelFormat 58 59 context management in 63 68 error handling in 57 global state functions in 84 86 macros in 86 pbuffer selection mode 208t pixel format selection in 57 63 read only parameters 68 read write parameters in 66 67 virtual screen management in 83 84 Core
135. RB shader objects amp amp defined GL ARB shading language 100 amp amp defined GL ARB vertex shader amp amp defined GL ARB fragment shader vertexShader glCreateShaderObjectARB GL VERTEX SHADER ARB fragmentShader glCreateShaderObjectARB GL FRAGMENT SHADER ARB glShaderSourceARB vertexShader 1 amp vertsource c NULL glShaderSourceARB fragmentShader 1 amp fragsource c NULL glCompileShaderARB vertexShader glCompileShaderARB fragmentShader programObject glCreateProgramObjectARB glAttachObjectARB programObject vertexShader glAttachObjectARB programObject fragmentShader glLinkProgramARB programObject glUseProgramObjectARB programObject else error No shading extension information in headers error NO shading will be available Only fallback error rendering provided in this binary endif add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES 272 Chapter 13 OpenGL Extensions The method hasShaderExtensions doesn t really do anything conceptually different from the action of our prior example but the methodology is slightly different We first check our version number but we don t create an extension dictionary GLEW has already done that for us and we can directly use the code it provides Thus
136. S glVertex2i 0 0 glVertex2i 2 0 glVertex2i 1 1 More batches of three vertices to follow for each triangle drawn giEnd glFlush Taking this example apart we can see its limitations First there is not only an entire OpenGL function call to delimit the batch of triangles drawn but also a function call for every vertex of those triangles Furthermore if this batch of triangles represents a triangle mesh all shared vertices are specified twice This immediate mode pattern typically is used for small batches of triangles 210 Chapter 11 Performance such that the cost of handling the begin end tokens in the OpenGL command stream is relatively high when compared to the few triangles drawn to amortize that cost A simple improvement in efficiency for this example is to replace the primi tive type GL_TRIANGLES with the type GL_TRIANGLE_STRIP This eliminates a great deal of the submission of redundant shared vertices Even with triangle strips there is a great deal of headroom for improvement To absorb the enormous function call overhead associated with the code in Exam ple 11 5 batch submission of vertices was added to the OpenGL interface This batching which is known as vertex arrays is shown in Example 11 5 Example 11 5 Immediate Mode Vertex Submission Vertex Arrays OpenGL context setup Preprocess vertex data as triangle strips into vertex buffer glEnableClientState GL
137. SCM Project Symbols gt Bmain cpp 4 25 No selec unn aise spud il include lt iostream gt Figure 9 3 Adding a Framework to This Project eoo le main cpp glut c B glut i amp Dev i E3 m NT A A A Q String Matchir Active Target Active Build Style Action Build Build and Run Build and Debug Tasks Clean All Clean Search Groups amp Files Ilr A A Code O A A glut B glut Ba P 9 GLUT framework 3 glut i gt 3 Source K GLUT framework gt 7 Documentation Bb main cop 4k 4 gt 2 Products v 9 Targets v 7g glut gt E Compile Sources 1 gt E Link Binary With Libra gt I Copy Files 1 gt J Executables gt 9 Errors and Warnings yq Find Results E gt Lf Bookmarks d gt SCM N gt B main cpp 4 25 lt No selected symbol NL 1 include lt iostream gt B e Project Symbols 2 using namespace std F n Implementation Files 3 n NIB Files 4 if defined __APPLE__ 5 include GLUT glut hz 6 else 7 include GL glut hz B endif 9 10 void prepareOpenGL n 12 B 14 15 int main int argc char const argv 16 17 18 glut exited normally Succeeded z Figure 9 4 Resultant GLUT Project Showing Framework and Sample Code 166 Chapter 9 The GLUT API for OpenGL Configuration live in the GL directory so some wrangling is necessary to ensure that your compiler can find the header file The code in Exampl
138. String Matching Groups amp Files v BS cocoa_openg E 7 w 2 Classes MyOpenGLView m 4 gt hMyOpenGLViewh 6 1 M interface MyOpenGLView import lt Cocoa Cocoa h gt gt Other Sources gt 2 Resources interface MyOpenGLView NSOpenGLView gt 2 Frameworks B Products gt 8 Targets gt J Executables gt Errors and Warnings vQ Find Results gt Lf Bookmarks gt SCM Project Symbols gt 3l Implementation Files gt i NIB Files Figure C 5 Custom View Derivation and Project Files in XCode 3 0 NSOpenGLView 287 generic NSView which allows us a bit more flexibility For now switch back to XCode and we ll dig into the code In XCode open the file MyOpenGLView m We ll now begin adding methods to handle key elements of the OpenGL render cycle We start by adding a method to select pixel formats This code performs pixel format selection in three steps T 2 A structure is created containing a list of pixel format configuration parameters That structure is passed to an NSOpenGLPixelFormat constructor to create a new pixel format object That pixel format object is passed on to the base NSOpenGLVi ew method for finishing the initialization of this view Either add the code yourself to your project or grab it from the sample code provided in Example C 1 Compile and run the code and you should have a window Example C 1 Configuration of an OpenGL View
139. Up glVertexArrayRangeAPPLE 0 NULL glDisableClientState GL VERTEX ARRAY RANGE APPLE free vertexData Efficient Handling of Vertex Data 219 This example shows a natural usage of the VAR extension We ve written pseu docode for this example because like many of the other snippets it describes the way things used to be done on OS X With the introduction of VBOs and the APPLE flush buffer range extension this same strategy can be employed using the more modern and OpenGL standard VBO interface Using VBOs on OS X As stated earlier VBOs are the way to go for modern OpenGL applications They have been designed with all the flexibility and all of the performance ben efits associated with previous methods of vertex submission in OpenGL We will not go into details on using VBOs these points are well covered in the OpenGL specification and supporting documentation We will highlight a few things about them here however Aside from the characterization of usage for VBOs when you initialize them you may notice that some of the relatively complex methods employed to obtain top notch performance on OS X become quite simple using VBOs For instance the vertex double buffering scheme described earlier is nearly free of charge You simply use two VBOs each of which holds a copy of the same data You update the first copy of the data in the first VBO with g1BufferData and then draw with it You do the same thing with the
140. VERTEX ARRAY glVertexPointer 3 GL FLOAT 0 vertex buffer Draw triangle strip using n vertices of vertex Buffer starting at index 0 glDrawArrays GL TRIANGLE STRIP 0 n glFlush In both of the immediate mode examples to draw the same data over again as with a static model you must continually and redundantly send vertex data over the bus or wire to the graphics device Display lists were added to OpenGL to allow reuse of data that was already submitted to a GPU and stored in VRAM Once the list has been specified you can simply refer to the list by ID to redraw it rather than resubmitting all of its often voluminous con tents Display lists were the earliest form of retained mode rendering Here s an example OpenGL context setup listID glGenLists 1 glNewList GL COMPILE listID glBegin GL TRIANGLE STRIP glVertex2i 0 0 glVertex2i 2 0 glVertex2i 1 1 More batches of two vertices to follow for each triangle drawn Efficient Handling of Vertex Data 211 glEnd glEndList Now as often as you wish draw the list glCallList listID glFlush For static models display lists yield an enormous performance gain because they effectively eliminate the transfer of data between the host CPU and the GPU They also eliminate all of the internal copies and data management re quired for immediate mode vertex submission Their drawbacks include the space required to store the d
141. Video 192 CoreFoundation 37 38 CPU see central processing unit CPU D Darwin 33 data copy minimization 201 2 data flow across contexts 51 53 76 77 and hardware 24 32 unidirectional 199 200 data management 209 10 data parallel computation 42 debugging OpenGL 39 41 dependency layering 50 50f depth textures 10t development history of Mac 2 3 display capture 149 51 309 10 display IDs 70 71 display masks 20 71 display release 150 displays 26 27 dl calls 265 66 dlopen 265 66 dlsym 265 66 double buffered drawables 77 78 downloadImageAsTexture 188 89 drawables 77 86 drawRect 132 33 Driver Monitor 235 36 235f 236f driver plug ins 17 18 drivers and renderers 21 E encapsulation 197 error handling in CGL 57 event handling 151 52 310 12 EXT extensions 8 9 extensions and ARB 8 9 creation of new 8 design of 254 55 EXT 8 9 identification 257 62 management libraries 269 75 overview of 253 54 parallel 8 promotion of to Core OpenGL 9t 11t query 257 62 range 205 7 selection 257 62 styles 256 tokens and 259 60 260t types 256 usage 257 62 utilization and binding 262 69 F FBOs see framebuffer objects feature support 14 15 fences 207 216 17 filesystem 38 fill 26 floating point framebuffers 23 Flush Buffer Range extension 205 7 220 21 fragment shaders 200 201 243 frame rate metrics 207 8 frame rate quantization 26 27
142. View in initWithFrame 127 Cocoa drawRect Rendering Method with Sample OpenGL Content sisi kit ker a snes parities eases 132 MyView h Final Header 0 cece ccc neces 136 MyView m Final Code 0 ccc cece cence ees 136 Singleton Class Declaration for Managing a Shared Context iiie e ada sr rave de eave RARE 144 Singleton Class Implementation for Managing a Shared Context i ussiieseded de aa pede rp E RR 144 Initialization of an OpenGL View with a Shared Context 147 Capturing and Releasing the Display sss 150 xxi Example 8 9 Example 8 10 Example 8 11 Example 8 12 Example 8 13 Example 8 14 Example 8 15 Example 8 16 Example 9 1 Example 9 2 Example 9 3 Example 10 1 Example 10 2 Example 10 3 Example 10 4 Example 10 5 Example 10 6 Example 10 7 Example 10 8 Example 10 9 Example 10 10 Example 11 1 Example 11 2 Example 11 3 Example 11 4 Example 11 5 Example 11 6 Example 11 7 Example 11 8 Example 11 9 Example 11 10 Example 11 11 xxii Examples Custom Controller Event Handling Loop ina Full Screen Context needs ces eee sag iodnan daa et cate Custom View Header for FBO Example Code OpenGL Setup for FBO Rendering Cocoa drawRect Routine for FBOs Cocoa Draw Methods for Contents of the FBO and the Eital Render dre idee enero t Ebr Custom View Header for Copy to Texture Example Code couette sed deta tee ee enu en OpenGL Setup for Copy to Texture Rendering
143. Without VAR the vertex array is treated atomically with regard to flushing the data to the GPU leading to a great deal of unnecessary bus traffic It s somewhat ironic that this extension s name does not generally denote its most powerful feature Along with the ability to modify and flush subregions of a vertex array the VAR extension allows you to characterize the usage of vertex data much as VBOs do allowing the OpenGL driver to avoid making unnecessary copies of your vertex array data For instance if the data in a vertex array is static it s best to cache it in VRAM and eliminate any other copies the driver may otherwise need to maintain Example 11 9 demonstrates how we might draw static vertex array data Efficient Handling of Vertex Data 215 Example 11 9 Using Vertex Array Range Standard vertex array setup glEnableClientState GL VERTEX ARRAY glVertexPointer 3 GL FLOAT stride vertexBuffer Tell OpenGL data is mostly static so hang on to it in VRAM glVertexArrayParameteriAPPLE GL VERTEX ARRAY STORAGE HINT APPLE GL STORAGE CACHED APPLE Set up the VAR glVertexArrayRangeApple arrayLength vertexBuffer Tell OpenGL the data has changed so it knows it needs to upload it to the card glFlushVertexArrayRangeAPPLE arrayLength vertexBuffer Notice that gIVertexArrayParameteriAPPLE is the key to characterizing the vertex array memory and avoids unnecessary data transfers and copies
144. X11 is launched using the Applications Utilities X11 app application In the Application menu you ll find the fa miliar xterm application Xterm will set up the X11 execution environment for you and makes it easy to launch your X11 applications If you need more information on configuring your X11 environment see Apple s comprehensive guide on its website 9 Like most X11 distributions the X11 install comes with the Athena and Xt wid get sets If your application uses another widget set most commercial applica tions do you ll have to do a bit more installation work to configure your Mac One of these widget sets Motif is quite popular in the commercial X software world Motif is a layer above raw X11 that provides a variety of higher level object oriented though not C rendering widgets Many large scale applica tions use Motif in the Unix world and a compatible version of Motif for Mac OS X called OpenMotif can be downloaded from the OpenMotif website 20 This version of OpenMotif requires a complete compile process however so you may prefer to use a precompiled version IST makes a variety of pack aged versions of OpenMotif for many platforms including an installer dmg for OS X Despite this not being an official Open Group version of OpenMotif installing from the disk image is considerably easier than building Motif from scratch IST s version of this packaged OpenMotif can be downloaded from the company s websi
145. _ARB_shader_objects L_ARB_vertex_shader L ARB fragment shader QoQvao Multiple render targets GL ARB draw buffers Non power of two textures L ARB texture non power of two G Point sprites GL ARB point sprite Separate stencil GL ATI separate stencil 2 1 Programmable shading Updated shading language to 1 20 Pixel buffer objects GL_ARB_pixel_buffer_object sRGB textures GL_EXT_texture_SRGB Mac OS X Implementation of the OpenGL Specification Once an extension or a version of the specification has been completed and rati fied by the required organization the company or organization that will sup port the extension must then implement it Naturally there is some amount of delay between the publishing of a specification and a vendor s implemen tation of that published specification We ll explore extensions in detail in Chapter 13 About OpenGL 11 Table 2 2 Mac OS Hardware Renderer Support for Versions of OpenGL Mac OS Version OpenGL Version Renderer 10 2 8 Jaguar 1 3 Radeon 9600 9700 9800 Radeon 9000 9200 Radeon 8500 Radeon 7000 7200 7500 Geforce FX Geforce 4 Ti Geforce 3 1 1 Apple Generic Renderer Geforce 2 MX 4 MX Rage 128 10 3 9 Panther 1 5 Geforce 6800 Geforce FX Radeon X800 Radeon 9600 9700 9800 1 3 Radeon 9200 Radeon 9000 Radeon 8500 Radeon 7000 7200 7500 Geforce 4 Ti Geforce 3 1 1 Ap
146. _TRUE Specify that only hardware renderers are searched Default GL_FALSE Policy Exact Continued Pixel Format and Context 99 Table 7 2 Pixel Format Specifiers for Use with aglChoosePixelFormat Continued Token Description AGL_ROBUST Choose a renderer that doesn t have a hardware failure mode due to lack of graphics resources Type Boolean GL_TRUE Search renderers with no hardware failure modes as described Default GL_FALSE Policy Exact Specify that only renderers with a back buffer that accommodates the full size of the drawable surface object should be searched Ensure that the back buffer is copy swapped to the front buffer meaning that the contents are usable after a swap buffers command Type Boolean GL_TRUE Consider only renderers with this capability Default n a Policy Exact AGL_WINDOW Can be used to render to a window Type n a n a Default n a Policy n a A single window can span multiple screens Type n a n a Default n a Policy n a Specify a virtual screen number on which to search for pixel formats Type Integer n a Default n a Policy Exact AGL_PBUFFER Choose a renderer that can be used to render to a pbuffer Type Boolean GL_TRUE Choose a pbuffer pixel format Default n a Policy Exact AGL BACKING STORI B AGL MULTISCRI t E Z
147. a tions on Mac OS X We target two categories of OpenGL programmers those XXV who are new to OpenGL on the Mac and those who want to explore the specific benefits of writing OpenGL programs on the Mac For those who are new to OpenGL on the Mac either existing Mac developers or those coming from other platforms we provide advice on cross platform issues portable interfaces and ideas about choosing native interfaces for the Mac Existing Mac developers will find a single source reference guide to all OpenGL interfaces on the Mac For developers wishing to explore the power and richness of the Mac we provide complete details on Mac specific OpenGL extensions and ways of integrating other Mac APIs such as QuickTime and Core Image into applications Organization This text is intended to be useful as both a programming guide and a reference manual The text contains several chapters focused on OpenGL on the Mac and other chapters that cover related graphics information A few appendices are in cluded to cover supplemental information in detail The chapters are organized as follows Architecture Chapters 1 through 4 describe the hardware and software archi tectures of the Mac This part of the book also presents an introduction to performance considerations as they relate to architecture Configuration and Integration Chapter 5 explores the interfaces to OpenGL on the Mac in detail Those new to OpenGL on the Mac should begin her
148. a baseline of OpenGL 1 5 and use features only natively defined therein no extensions If you can stick to that criterion you re in really good shape because a simple combination of compile time and runtime checks will get you access to all the features you require In a real world application you ll likely want to use some newer OpenGL fea tures in subsequent revisions to your application so you may have access to Identification Selection Query and Usage 257 these features on only some platforms and in extension form In this case we recommend you choose extensions based on the OpenGL Architecture Review Board extension evolution process By this we mean that the OpenGL ARB extension process defines the evolution of an extension from concept to core OpenGL To be explicit in a cross platform or even a cross Mac application the most compatible ways of choosing which features and extensions to use are in order 1 Features satisfied by the core OpenGL version 2 Features satisfied by an ARB extension 3 Features satisfied by an EXT extension 4 Features satisfied by a vendor extension e g ATI nV sGI In essence there are three steps to choosing which extensions your appli cation will use First choose which fundamental features your application needs and which combinations of core OpenGL versions and extensions satisfy those needs Decide which of those combinations will be the pre ferred path the alternative pat
149. a basis for you to get started If you need more detail we provide a more comprehensive example on our website www macopenglbook com Alternative Rendering Destinations In the following sections we ll explore what it takes to render an intermediate image for use later in your application You ll probably already know if this is something you re interested in If not let s discuss a case or two in which you might need to render intermediate results One example in which intermediate rendering results are useful is for render ing of reflections Suppose you ve got a scene with some watery bits and some shiny bits in it Picture a rainy street scene with puddles and a car The puddles would reflect the buildings across the street and those shiny rims would re flect the buildings behind the viewer To reflect something on those wheels and puddles we have two options One is to use a fake scene to create the reflec tions and the other is to use the real scene Obviously the real scene is the better option so we ll need to generate a view of the scene that contains the images to be reflected This would be the image that we d render in our intermediate buffer In another example we might want to render the same view of the street scene but perhaps after the viewer hit his or her head on something a painful simula tion to be sure Perhaps your character was jogging and ran into a signpost We want to render the scene slightly blurred and
150. a breakpoint before CGLFlushDrawable clearing the Trace and Statistics views and then clicking Continue to resume execution you will get precisely one frame s worth of GL function calls as a trace and as a collection of statistics This often simplifies the debugging and performance process such that it yields the essential information only without any duplicate state changes In addition to collecting the trace and the statistics the Breakpoints view pro vides state change information since the last breakpoint was encountered If you click the State tab on the rightmost pane of the Breakpoints view window all GL state settings that have changed since the last breakpoint was encoun tered will appear in a red typeface All unchanged states remain in the normal black typeface This distinction allows you to quickly review state changes for a 230 Chapter 11 Performance frame You may be surprised at how often you see state changes that you hadn t anticipated Now we leave the raw utility class of operations in the Breakpoints view and get to the it s just plain cool functionality Specifically the Breakpoints view allows you to execute a script before or after each invocation of a specified GL function Generally speaking there s no way to upload new data to GL in the same way an application can with memory buffers but you can make any GL function calls that modify the GL state machine Let s consider an example Suppose you h
151. ac tually shows the version potential if you will for each of these major releases To obtain OpenGL version information for other minor releases you must first choose a pixel format with the hardware or software renderer in which you are interested Once you have created a context with the pixel format of interest you can retrieve the OpenGL version of the selected renderer as follows char opengl_version_str strdup const char glGetString GL VERSION The OpenGL version number is the first space delimited token in the string opengl version str strtok opengl version str if strcmp opengl version str 2 1 OpenGL 2 1 Specific Application Configuration else if strcmp opengl version str 2 0 OpenGL 2 0 Specific Application Configuration Configuration for other versions of OpenGL free opengl version str OpenGL Feature Support Every graphics card has different capabilities with regard to support of OpenGL features Naturally the more advanced and modern the graphics card the more support it has for OpenGL features natively on its graphics processing unit GPU Perhaps a bit surprisingly the software renderer often has the most full featured support of OpenGL of the possible devices As a result and so as to maintain compliance with the OpenGL specification the software renderer is often called upon by Mac OS OpenGL to handle rendering tasks that the GPU insta
152. ac with a G4 or later is AltiVec or SSE capable Thus if you re writing new code targeting newer Macs consider these SIMD instruction sets for inten sive CPU processing A detailed discussion of SIMD programming is beyond the scope of this book so for now we ll simply provide you with a code sam ple at http www macopengl com that can help you determine whether your CPU has SIMD capabilities Intel Streaming SIMD Extensions or SSE were introduced in 1999 by Intel Numerous versions of SSE exist e g SSE SSE2 SSE3 but the basic idea is the same as with AltiVec coding Vectorize your algorithm and implement it as a chunk of SSE assembly in your code As with AltiVec this is obviously not a graphics function per se but may be related to your OpenGL development For example if your application does compression or decompression of video audio or other streaming data and then displays this information on screen you might want to investigate SSE as a way of accelerating your codecs Data Parallel Computation SIMD 43 Apple provides two good references if you re interested in learning the details behind SSE First the performance analysis tool Shark as described in Chapter 11 is a good way to see what s going on in your code and find hints about what might be candidates for vectorization Shark also contains a very nice SSE reference containing all of the commands their arguments and results Apple s second reference to
153. access DMA performance The other key aspect of Apple Texture Range Apple Vertex Array Range and Apple Flush Buffer Range is the ability to update a subset within a block of data and to flush only the modified data across the bus to the graphics device This partial update mechanism saves a tremendous amount of bus traffic Without these interfaces updates to a portion of a texture a vertex array or in the case of Apple Flush Buffer Range a vertex buffer object would set a flag indicating that the entire contents of the object were stale The GPU would then be forced to transfer all of the data for the object over the bus The introduction of buffer objects to OpenGL combined with the introduction of Apple s Flush Buffer Range extension has effectively replaced the Apple Tex ture Range and Apple Vertex Array Range Extensions Buffer objects for both vertices and pixels and the Apple Flush Buffer Range extension provide a con sistent mechanism to perform partial updates and flushes between the two Buffer objects are easier to use have better cross platform compatibility and have a brighter future than the older mechanisms OpenGL for Mac OS X Rules of Thumb for Performance 205 Here s an example of using Apple Flush Buffer Range to do partial flushing on a buffer object In Example 11 3 we arbitrarily chose to work with pixel buffer objects Vertex buffer objects work in exactly the same manner albeit with some simple substi
154. agement Using Mac OpenGL 209 The answer to each of these questions is It depends But the important com mon thread is that a copy of the data is made In many cases if it makes sense multiple copies of the data are made There may be a copy in the OpenGL frame work one in the driver and one in VRAM All told that s four potential copies of large data buffers The moral to this story can be summarized as follows Efficient data handling on the Mac means efficient use of memory by providing a clear usage model of the memory to OpenGL using the available interfaces of both OpenGL and Apple extensions Efficient Handling of Vertex Data A Brief History of the Evolution of Submitting Vertices in OpenGL The number of different ways to submit vertex information provided via the OpenGL API through version 2 1 of the specification is staggering From a per formance perspective most of these methods are outdated From a convenience perspective things are a bit more debatable Regardless of the outcome of the debate the OpenGL ARB is convinced that fewer performance nooses need to be present in the API Over time older idioms will be purged from the API leaving only the best practices intact Let s start with the most primitive form of submitting vertex data in OpenGL use of immediate mode as illustrated in Example 11 4 Example 11 4 Immediate Mode Vertex Submission Begin End OpenGL context setup glBegin GL TRIANGLE
155. alistic textures and shadows Written in an engaging easy to follow style you ll quickly learn the essential and most often used features of OpenGL along with the best coding practices and troubleshooting tips OpenGL Programming on Mac OS X Architecture Performance and Integration Robert P Kuehne and J D Sullivan 0 321 35652 7 Apple s highly efficient modern OpenGL implementation makes Mac OS X one of today s best platforms for OpenGL development OpenGL Programming on Mac OS X is the first comprehensive resource for every graphics program mer who wants to create port or optimize OpenGL applications for this high volume platform A Available wherever technical books are sold For more information including free VW W sample chapters go to www awprofessional com
156. all to CGMainDisplayID in the context of obtaining renderer information is redundant and slow If it is just the main display ID you wish to use the constant kCGDirectMainDisplay is defined for this purpose Displays on a Mac system employ a global coordinate system to describe positional information independent of a specific device and display pairing The main display is defined as the display in this global coordinate space with its screen location at 0 0 Mac systems can perform display mirroring to display the same information on two monitors Alternatively the display preferences pane allows you to configure multiple monitors in an extended desktop mode As a point of ref erence in extended desktop mode the display with the menu bar is the main display of the system All other display retrieval functions aside from CGMainDisplayID in the Quartz Services API return a list of displays To obtain a list of displays that can be rendered to use CGDisplayErr CGGetActiveDisplayList CGDisplayCount activeDisplayArraySize CGDirectDisplayID activeDisplayArray CGDisplayCount activeDisplay ReturnCount This function uses the common data retrieval entry point parameters of an array the allocation size of the array and a pointer for the return count of matching items For a broader list of all displays connected to a system call CGDisplayErr CGGetOnlineDisplayList CGDisplayCount onlineDisplayArraySize CGDirectDisplayID
157. amebuffer Objects In this section we describe a modern and widely available technique for in termediate renders using framebuffer objects FBOs Rendering to FBOs is a technique born out of frustrations with the complexity of many of the other intermediate rendering techniques FBOs were designed to provide a simple enable disable mechanism that is familiar in usage to textures and yet provide a great deal of flexibility in terms of what can be rendered and how to use it later FBOs are an evolution from earlier extensions namely GL_ARB_render_texture However they are a vast improvement over the older techniques as you ll hear shortly FBOs are really the only choice for new applications as they offer high performance are flexible and are easy to use That s our perspective on the matter but for reference you should defer to the extension specification as the authority The specification declares Alternative Rendering Destinations 153 We believe that this extension is the best way to render to texture and authori tatively settles the question of what to use when performing a render to texture operation Without further ado let s walk through how to use FBOs for inter Previous extensions that enabled rendering to a texture have been much more complicated One example is the combination of GL_ARB_pbuffer and GL_ARB_render_texture both of which are window system extensions This combination requires calling glxMakeCurrent a
158. ank Example 4 1 Example 6 1 Example 6 2 Example 6 3 Example 7 1 Example 7 2 Example 7 3 Example 7 4 Example 7 5 Example 7 6 Example 7 7 Example 7 8 Example 7 9 Example 7 10 Example 7 11 Example 7 12 Example 8 1 Example 8 2 Example 8 3 Example 8 4 Example 8 5 Example 8 6 Example 8 7 Example 8 8 Examples Power Management on OS X 06 6 cece cence ences 35 CGLChoosePixelFormat Usage ccc eee eee ee 58 Creating and Inspecting Renderer Info Objects 68 Testing for Full Screen Rendering Support 82 Headers for OpenGL and AGL 0 c eee eee 92 AGL OpenGL Initialization and Draw Functions 92 AGL Full Screen Application main Method 93 AGL Windowed main Example ssssssse 101 AGI Renderer Query Example eric eer eer 105 Sharing One Context with Another in AGL 108 Copying the Context State Between Two Contexts WAG beean ee eicere teet Ratan Rats 109 Pbuffer and Windowed Context Creation in AGL 111 OpenGL Context Initialization Referencing a Pbuffer asthe Texture 152i etuscwdininP tte dened baiting lee Heb RUE habs 112 AGL OpenGL Initialization and Draw Functions for Copy Texture Rendering i c cce vere eee 114 AGL Copy Texture Render Call Sequence 116 AGL Initialization and Draw for a Framebuffer Object and Main Duet ucseta cea ditas tcn ee Ue 117 Configuration of an OpenGL
159. aphics Bus Pairing 5 30 Mac OS X Versions and Code Names sssuuusuuususus 34 API and Framework Locations 000ce cece eee e ence ene 50 CGL Pbuff r F ncti ns oce Ie eR ERN AE EE d EY ed das 79 Locations of AGL Headers and Frameworks 91 Pixel Format Specifiers for Use with aglChoosePrixelFormat u ERE LERENEE LIEN EER 95 Tokens for Use with aglDescribeRenderer 107 AGL Pbuffer Functions 0 00 c cc cece cece cence n 110 AppKit Cocoa Headers Frameworks and Overview 122 Selection Policies and Behaviors 0 00 cece ee eee eee 127 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat cece ccc eee cece eee nee eens 129 GLUT Headers Frameworks and Overview 164 glutInitDisplayMode Bit Field Tokens 169 glutInitDisplayString Policy and Capability Strings 170 NSBitmapImageRep Accessors for OpenGL Texture Data 179 Pixel Format Buffer Selection Mode 0 0 cece eeee 208 giGetstring lokens oup EDbkeEEpe AE R Eb RA 249 Preprocessor Tokens for Extension Usage suus 260 AppKit Cocoa Headers Frameworks and Overview 284 Selection Policies and Behaviors 0 000 eee eee eeee 289 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFOrMat ccc cece eee eene eens 290 xix This page intentionally left bl
160. aphics chipsets Since SGI J D has worked on the Mac as his primary development platform He has been an OpenGL driver engineer for more than five years and serves on the OpenGL Architecture Review board xxxii About the Authors Chapter 1 Mac OpenGL Introduction Welcome to OpenGL on Mac OS X This book is designed to be your one stop resource for all things OpenGL on the Mac We wrote this book for Mac OpenGL developers such as you We wrote it for ourselves too let us explain We have always cherished having a comprehensive programming guide in hand that provides the continuity and context of programming environments We also ap preciate the concise bulleted information found in most reference guides The analog learning experience of sitting back in a comfortable chair with a clear mind and a cup of your beverage of choice is a great way to deeply understand the intention and usage of an API or programming environment We invite you to sit back and enjoy learning what the exceptional pairing of the Mac OS and OpenGL have to offer This book will serve both existing Mac developers and those new to the plat form We are living proof of the former case We ve referenced it ourselves dur ing the writing of the book itself We ve consolidated a lot of information from a variety of sources and our own experience into one complete guide Developers who are new to the Mac platform should appreciate both the comprehensive na ture o
161. apter 12 Mac Platform Compatibility its overall runtime goodness for inquiring as to whether a particular object or class responds to a particular method These respondsToSelector and instancesRespondToSelector methods are thoroughly documented within Apple s developer documentation Summary In this chapter we saw some of the differences between the various versions of Mac OS X and we learned how to identify both the running Mac version and the OpenGL platform With the combination of these identifying markers you re well positioned to build features for specific combinations of Mac platform and OpenGL platform to work around bugs and to enable and disable features as appropriate In Chapter 13 we ll dig into the details of customizing OpenGL rendering for particular versions of OpenGL Taken in combination these two chapters will show you how to exercise complete control over which features run on which platforms for OpenGL and the Mac OS Summary 251 This page intentionally left blank Chapter 13 OpenGL Extensions Overview In this chapter we ll discuss a design feature of OpenGL known as OpenGL extensions We ll describe how these extensions work how to discover which ones are available and how to determine exactly how extensions operate We ll also describe a few libraries for working with extensions that make your life as a developer easier But first what are extensions and why do they exist Extensions are
162. as Leopard We know Leopard will fully support PowerPC and Intel Macs Likely it will be faster better and more feature complete in its OpenGL implementation At least OpenGL 2 1 will be supported Even more computa tion may be offloaded to the GPU so that graphics developers need to be all the more conscientious about their place in the universe Your application may not be the only one expecting to use the GPU and in fact may always be operating in conjunction with other GPU intensive applications specifically those within the Mac OS itself However if applications are well written and aren t resource gluttons they should continue to perform well OpenGL Platform Identification We ve just talked a bit about the various changes evident among the versions of Mac OS X through the last few years but let s not talk about how you can manage that change right now In Chapter 13 we ll see a key way of managing change between OpenGL versions and ways of evolving your OpenGL func tionality gracefully But what do you do if something graceless is happening for example with a particular platform For that matter what is the definition of the OpenGL platform We ll look at these questions and even provide an swers to them in this section Earlier in this book we discussed the ways in which OpenGL is integrated with various window systems and APIs on the Mac We looked at AGL CGL GLUT and Cocoa yet underpinning all of these systems was th
163. as WGL for Windows and GLX for X Windows systems Our focus on using GLEW here will be on the OpenGL extension management aspects of the library GLEW builds and maintains a list of current OpenGL extension tokens and extension API entry points upon initialization of the library The to ken list GLEW builds can be used to directly query whether a particular extension exists if you prefer you can also perform functional queries to test for groups of functionality GLEW names tokens for extensions by defining a companion token to the extension of interest in which the GLEW prefix re places the GL prefix For instance as per our earlier shader example GLEW de fines GLEW_ARB_fragment_shader to correspond to the GL_ARB_fragment_ shader extension If this token exists a user is able to use all the functionality that this extension provides GLEW also provides all the basic compile time definitions needed for an application for example the tokens defined by a particular extension At run time when the library is initialized GLEW resolves the symbols for each of the functions defined by a particular extension It does so by exploiting the same Core foundation methods that we used to do this task ourselves earlier How ever GLEW does this for each and every extension known in the universe or at least known to GLEW as of the version you re using In summary GLEW defines all aspects of the extensions known to it at the time th
164. at bootstrapping the rest of the way to a functional chunk of code is required to fully explain and demonstrate how to use preprocessor and runtime checks We re in a bit of chicken or egg bind so we will simply show the code for shading setup without further ado We re going to look at Example 13 1 We ll gloss over a few runtime details here and focus on the preprocessing elements for now We ll circle around to the runtime checks momentarily First let s look at an overview of this example The code does three things two of which we ve seen before The shading section begins by checking the method hasShaderExtensions to see if our platform has shader extension support We won t dig into the hasShaderExtensions check now as we re just look ing at compile time checks in this section What do we see within this block Essentially we validate that our compiler and header support at least OpenGL 1 3 and the required shader extensions Within that block the API and to ken definitions for baseline OpenGL 1 3 and all the shader extensions are de fined Things get more complex when we try to intermingle various versions of OpenGL support With OpenGL and shading in particular some of the API entry points change which is why we re not looking at that issue here Within the block then we do the things necessary to load compile link and bind our shaders These are all fairly commonplace shader operations and the interested reader can fin
165. at64Bit 0x01000000 64 rgb bit pixel half float R kCGLRGBAFloat64Bit 0x02000000 64 argb bit pixel half float ay kCGLRGBFloat128Bit 0x04000000 128 rgb bit pixel ieee float kCGLRGBAFloat128Bit 0x08000000 128 argb bit pixel ieee float Ry kCGLRGBFloat256Bit 0x10000000 256 rgb bit pixel ieee double kCGLRGBAFloat256Bit 0x20000000 256 argb bit pixel ieee double 4 For all of the preceding constants the color components occupy some multiple of 16 bits In most the pixel size is simply the sum of the component widths In some such as kCGLRGBA444Bit the pixel occupies more than the required 12 bits but is always stored in the low order bits of the nearest 16 bit boundary in this case 16 bits The relevant information in these constants is the component sizes themselves These sizes provide information on the level of quantization of the pixel data you should expect to see when using a framebuffer configured in this format There is no programmatic interface through OpenGL or CGL to retrieve the data with the bit positions as they are described here remaining intact from the framebuffer The layout of these pixels as they are retrieved from the frame buffer is controlled by tokens in OpenGL kCGLRPDepthModes and kCGLRPStencilModes Both kCGLRPDepthModes and kCGLRPStencilModes are bitwise ORs speci fying the number of respective bits that are supported by the renderer The range of possible
166. ate often this is because the application wasn t strictly adhering to the OpenGL specification That said it s entirely possible a regression was introduced with the software update again Apple is eager to hear about such a problem A closely related cousin to this type of filing is the bug that is filed with the rationale that It works on this other platform therefore it must be broken on OS X This may be the case It may also be the case that the other platform is more lax in its compliance with the specification and is allowing behavior that it probably shouldn t In any case this is a great data point for a bug filing but isn t the proverbial nail in the coffin for identifying the source of the bug Suppose you ve done some due diligence and now you re ready to file a bug Here are some tips to get satisfaction for your efforts First realize there are a few layers of Apple engineers involved when it comes to bug processing When a bug report is filed it is screened by the developer program to see if it can resolve the problem If not the report will be sent to the appropriate engineer ing group within Apple That group will also have a screener The engineering group screener knows what everyone is working on within the group and will dispatch the bug to the appropriate engineer By now I hope you can see where I m going with this Given the many people and many schedules involved it can take quite a while to validate and assi
167. ate a proper graphics environment for our application and exit appropriately H now init ourself using NSOpenGLViews initWithFrame pixelFormat message return self super initWithFrame frame pixelFormat pixelformat autorelease We ll finish this Cocoa example by adding a few more useful methods to our code These will allow two more key tasks namely context setup that is things you might do in an OpenGL application such as glEnable certain states and bind textures and drawing 128 Chapter 8 The Cocoa API for OpenGL Configuration Table 8 3 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat Token Description NSOpenGLPFAAllRenderers Look in entire set of renderers to find a match Type Boolean YES Search entire set of available renderers including those that are potentially non OpenGL compliant Default YES Policy Any NSOpenGLPFADoubleBuffer Double buffer requirements Type Boolean YES Search only for a double buffered pixel format NO Require a single buffered pixel format Default NO Policy Any NSOpenGLPFAStereo Stereo requirements Type Boolean YES Require a stereo pixel format NO Require a monoscopic pixel format Default NO Policy Any NSOpenGLPFAAuxBuffers Auxiliary buffer requirements Type Unsigned integer Number of auxiliary buffers required by this pixel format Default NA Policy Smallest NSOpenGLPFAColorSize Color bits requir
168. ate all devices similarly to the way aglChoosePixelFormat operates If we were particu larly interested in a specific device we could customize this call to just query that device or a sublist of AGLDevices This code then ensures that the result isn t NULL which indicates the last of our AGLRendererInfo structures and walks through the list invoking ag1DescribeRenderer on a few properties The output from this example looks like the following for the author s Intel based iMac 0 id 137473 hardware 1 vram Mb 128 tram Mb 128 renderer 1 id 132096 hardware 0 Mb 0 tram Mb 0 renderer vram An AGL renderer query of this type for video and texture memory isn t the most useful as these results indicate hardware limits all of that memory may not necessarily be available to a running application but it s an easy way to demonstrate the concept Furthermore we derive certain satisfaction from pro grammatically validating that the hardware actually has the capabilities listed on the marketing literature From these results we can see the renderer ID de termine whether it has hardware acceleration and learn about its video and tex ture memory limits This method provides an easy way of querying supported renderers on a particular platform A complete and current list of tokens can always be found in the AGL ag1 h header file and we ve also documented a useful set of tokens in Table 7 3 For the most part q
169. ate can benefit greatly from these interfaces and the methods to use them At a higher level asynchronous operations put more control in the hands of your application and bring a bit more peril The peril lies in the fact that 204 Chapter 11 Performance asynchronous programming is a bit more difficult because data doesn t move in the system without you telling it to do so The pattern is this modify some data do some other stuff check whether the data is ready for use and then use the data The flipside of this peril is that this additional control allows your application to apply smarts about how its data are to be handled Picking up the asyn chronous pen and putting down the synchronous club is essential in obtaining peak overall system bandwidth Here s a list of the asynchronous extensions and features of the Mac OS X OpenGL API Multithreaded OpenGL Engine e Apple Texture Range e Apple Vertex Array Range e Apple Flush Buffer Range e Apple Fence The ultimate expression of asynchronicity of OpenGL on Mac OS X is the Multi threaded OpenGL Engine Let s move on to the Range extensions The Range Extensions The Apple Texture Range and the Apple Vertex Array Range extensions are both aggregation methods They allow you to specify large chunks of memory in which all of your texture or vertex data are aggregated so as to more efficiently map the memory This more efficient mapping improves direct memory
170. ath altogether Please Admire Me ptm6 reaches frame rates in excess of 100 frames per second We ve left one exercise for the reader For ptm6 c what could be done to im prove the efficiency of the mesh rendering We ll give you a hint There s a more efficient way to draw quadrilaterals in OpenGL without using the GL_QUADS token to glBegin Summary Many of the steps required to build a high performance OpenGL application on OS X are shared with other platforms Measures such as minimizing state Summary 243 changes using retained mode rendering and including other OpenGL best practices are platform agnostic To these known axioms the Mac OS X OpenGL implementation is an industry leader with its plethora of asynchronous data submission interfaces and multithreaded OpenGL engine Adding these capa bilities to the great OpenGL diagnostic performance and debugging tools on OS X makes the platform first in its class for producing an optimally performing OpenGL application 244 Chapter 11 Performance Chapter 12 Mac Platform Compatibility Mac OS Versions Mac OS X has evolved significantly over its life span but OS X has featured OpenGL as a key piece of its foundation since day 1 As Mac OS X evolved the operating system itself has assumed increasingly more heavy usage of the OpenGL layer and the performance features and quality of the graphics sub system have continually improved In this chapter we
171. ation requires power of two data several options are available to you e You can resize the image data to be a power of two per side e You can create the next power of two size texture larger than the data subload the data and use appropriate texture coordinates when texturing e You can check for and use the GL_LARB_non_power_of_two extension to load non power of two data By far the most flexible of these solutions especially with respect to preserv ing your data s original quality and integrity and minimizing the impact on your hardware resources by minimizing the texture size downloaded to the hardware is using the GL ARB non power of two extension This extension isn t available on all graphics hardware on all Mac computers or on all ren derers so a cautious approach is necessary Be sure to query for the extension before you attempt to use it Aside from ensuring its existence however us ing GL ARB non power of two is as simple as downloading your data into a texture The second most effective technique with respect to preserving your data s in tegrity is to create a larger texture and subload your full image data into it This technique does waste precious texture resources because you re creating an im age that contains empty or unused pixels which nevertheless require space in the texture cache Your image will be represented at full fidelity however and there may be applications for which this requirem
172. ation about an AGL pixel buffer CGLGet PBuffer Queries a context for the pixel buffer attached to it CGLSet PBuffer Sets the pixel buffer to be the target for the specified context CGLTexImagePBuffer Binds a pixel buffer as a texture analogous to glTexImage2D internalFormat may be either of the two basic internal OpenGL texture for mats GL RGBA or GL RGB These two parameters give good insight into why pbuffers exist in the CGL interface They were specifically designed for render ing to textures so much so that there isn t a simplified interface for creating them that is texturing agnostic Continuing with the texturing theme the width and height parameters must be powers of 2 when using either a GL TEXTURE 2D or GL TEXTURE CUBE MAP target Also width must equal height for GL TEXTURE CUBE MAP targets because they must be square The last parameter constraint also a texturing consideration deals with mipmaps The maxLevel parameter must be commensurate with the number of possible mipmap levels when using the provided width and height parameters If the number of mipmap levels is less than the value specified in maxLevel or if any of the aforementioned constraints is violated CGLCreatePBuffer will return kCGLBadValue Freeing a pbuffer and its resources entails a simple call to CGLError CGLDestroyPBuffer CGLPBufferObj pbuffer Given that it has only one argument only one thi
173. ation that allows configuration of shaders in a tools window with some parameter sliders to adjust the shader Suppose you want to render a sphere with the shader applied on the more capable renderer yet maintain the tools window itself ona less capable virtual screen In this example the sphere would be updated infrequently and the size of the buffer being copied would be rela tively small thus mitigating any performance dropoff You can retrieve the current virtual screen of a context as follows CGLError CGLGetVirtualScreen CGLContextObj ctx long virtualScreen Global CGL State Functions CGL allows for setting and retrieving global state parameters Unlike all other CGL API entry points the global state functions are context independent These values can be set at any time and affect any subsequent CGL operations 84 Chapter 6 The CGL API for OpenGL Configuration CGLSet Option is used to set a global CGL option Its function prototype is CGLError CGLSetOption CGLGlobalOption globalOption long break optionValue For retrieving global options use CGLError CGLGetOption CGLGlobalOption globalOption long optionValue The global options for CGL are as follows typedef enum CGLGlobalOption kCGLGOFormatCacheSize 501 kCGLGOClearFormatCache 502 kCGLGORetainRenderers 503 kCGLGOResetLibrary 504 kCGLGOUseErrorHandler 505 CGLGlobalOption kCGLGOFormatCacheSize corresponds to the number of pixel
174. atively support Apple s flagship API set Cocoa QuickTime 7 continues to support the fundamental Movie Toolbox for accessing time based content but also introduced the Cocoa QTKit which will be our focus in this portion of the book QuickTime has evolved much since its early days but it retains the good design that set the foundation for the API that lies at the heart of Apple s multimedia engines 184 Chapter 10 API Interoperability QuickTime to OpenGL As with other interoperability topics we ll try to focus on the most modern tech niques and the highest level languages available to developers in our present discussion In this case we ll focus on Cocoa but because of QuickTime s his tory we ll make a brief diversion to explore how the legacy QuickTime routines behave too This section will unfold similarly to earlier sections demonstrat ing interoperability by showing examples of how to get QuickTime content into your OpenGL application through code and offering an examination of how that code works and how you can tweak it As mentioned earlier QuickTime 7 introduced a native Cocoa interface for accessing QuickTime content through the OTKit framework This framework modernized and simplified the API for use with Cocoa and is a logical suc cessor to the Movie Toolbox API provided in all prior and current versions of QuickTime It s also the logical successor to the existing wrappers provided in Cocoa NSMovie and NSMovieVie
175. ave a rendering logic problem be tween a call to g1Translated anda call to g1LineWwidth You could at tach a script to be executed after the call to g1Translated to set the current color to green You could then attach a script to be executed before the call to glLineWidth to set the current color to white After attaching these scripts and continuing execution you would know that all geometry rendered in green was subject to the logic problem and all geometry rendered in white was not Aside from GL function and GL error breakpoints the Breakpoints view allows breaking on thread conflicts and vertex array range errors Thread conflicts oc cur when multiple threads concurrently modify the same GL state This often arises with multithreading and the use of NSOpenGLVi ews that internally must modify GL state These implicit state modifications are often not anticipated by users of this Cocoa class Statistics View The Statistics view accumulates and displays statistics on a per GL function basis Figure 11 4 This view is useful in characterizing your application s usage patterns related to the OpenGL API Often having this information yields sur prises and allows for reworking the application to achieve better performance For each OpenGL function called both the execution time and the percentage of time spent inside the implementation to execute the call are shown Generally speaking if the percentage of time spent inside OpenGL i
176. ave access to both features 253 and a compatibility path with older code Thanks to a lot of really good up front design in the OpenGL specification OpenGL doesn t cause a major compatibil ity headache for the developer with each version and in fact it handles growth and change in a very elegant and evolutionary fashion The OpenGL mecha nism for adding new features and evolving the API is known as the OpenGL process and is the focus of this chapter We ll see how extensions are incorpo rated into OpenGL from a graphics vendor s perspective which in turn yields insight into our second key goal in this chapter how to use OpenGL extensions effectively Extension Design and API Integration OpenGL extensions exist for a few key reasons e To allow OpenGL to evolve as fast as hardware developers push it e To keep the core OpenGL API stable e To give developers a consistent mechanism for accessing new features and capabilities e To support feature API and usage compatibility across a wide variety of API versions and vendor hardware These design parameters mean that if you work on the Mac and on Linux using whichever vendor s graphics hardware you always use a very similar mecha nism to access specific features of that hardware Another implication is that if you are working on a platform that supports OpenGL 1 4 but the graphics hardware in that box has features that are not yet found in OpenGL 14 the vendor will provide
177. blished in the GLX specification Applications are responsible for synchro nizing the state of objects between contexts This implies that multithreaded applications with shared context establish mutex locks between the threads use glFlush to flush pending commands that modify object state and call g1Bind to realize changes to shared objects in other contexts These may seem like a lot of steps but they are usually worth the resulting resource conservation and performance gains In this section we ve seen how to configure context sharing in Cocoa how to use it with a custom OpenGL view and under which circumstances you d want to share contexts We ve provided examples of how this sharing mechanism works in Cocoa and we ll revisit this topic for AGL and CGL later Context sharing is a key principle we ll use for a variety of on or off screen rendering techniques so you ll likely revisit this section from time to time for hints when performing full screen and off screen rendering Full Screen Surfaces Every now and again you might want to put your Cocoa OpenGL application into full screen mode There are lots of reasons why you might want to do this and Apple often uses this approach for many of its applications Apple software 308 Appendix C The Cocoa API for OpenGL Configuration in Leopard examples include QuickTime full screen movie presentation iPhoto Finder slideshows DVD playback and FrontRow set top display The most
178. bon h header file and link against the Carbon framework Example 12 1 Unpack the OS X Version Number long macOSXVersion unsigned int major unsigned int minor long version 0 Gestalt gestaltSystemVersion amp version minor version amp 0xf major version amp 0xf0 gt gt 4 return version A quick point of interest for the curious Which versions of Mac OS X have existed and been released Apple maintains a complete list including version numbers and build numbers in Article Number 106176 3 Apple also main tains a really nice list of releases of hardware and software together in Article Number 25517 11 These pieces of information may prove useful when you are developing code that targets particular pieces of hardware and when your customers and clients need to debug your application When should you use this kind of query If you re writing an application that must run on multiple versions of Mac OS X and you re using some feature that you think might be available only on a particular version of the operating system then this is what you d do There aren t a lot of reasons why you might search out version information but working around a bug is one of them Using undocumented API calls is another but that wouldn t be a good idea in general Finally you expressly don t want to use this functionality to check for features with Cocoa applications Cocoa has a well defined mechanism part of 250 Ch
179. brary We do that as seen in Figure 9 3 with the result shown in Figure 9 4 This specifies that we will use the GLUT framework to resolve include files and link libraries The only other Mac specific element is the way in which we include the headers as seen in Figure 9 3 On other plat forms the GLUT headers may live in different directories in fact they usually 008 Assistant id New Project PyObjC Document based Application a PyObjC Mixed Application Y Bundle Carbon Bundle CFPiugin Bundle 0 Cocoa Bundle Y Command Line Utility CoreFoundation Tool CoreServices Tool Foundation Tool Standard Tool Y Dynamic Library b BSD Dynamic Library M This project builds a command line tool that links against the stdc library Cancel Previous Next Figure 9 2 New Project Creation for GLUT Application Configuration and Setup 165 eoo SB glut iz Dev H v le main cpp glut is Active Target Active Build Style Action Build Build and Run Build and Dv Groups amp Files wi New File gt 7 Docu Open With Finder New Group gt Prod AL ns New Target v 9 Targets Reveal in Finder New Custom Executable gt 4 Executables gt gt Errors and Warnings vq Find Results Get Info Preferences New Build Phase gt Existing Files Existing Frameworks Add Existing Frameworks to glut ee gt Q Bookmarks gt
180. caveats to this technique Example 8 16 Cocoa drawRect Routine for Copy to Texture Rendering void drawRect NSRect rect setup and render the scene self drawIntermediateContents copy it to a texture glBindTexture GL TEXTURE 2D textureID glCopyTexSubImage2D GL TEXTURE 2D O0 0 0 OF Q0 64 64 render final scene self drawFinalContents complete rendering amp swap glFlush 160 Chapter 8 The Cocoa API for OpenGL Configuration self openGLContext flushBuffer Notice two things in Example 8 16 First our draw routines are the same as the FBO example so we won t present them again The first method draws the stuff to be used as a texture and the second draws the scene using the texture gen erated from the first method Second there is no binding or other redirection of where this routine renders Instead we do all of the rendering in the back buffer and then copy it to a texture This approach has one important implication This technique really works only for double buffered visuals Another consequence of the way this technique works is that we re actually copying the contents of the back buffer to a texture so performance may be less than that in the FBO case Specifically we perform this copy between each of the self draw methods Thus performance is likely to be slower than in the FBO case but there s a lot of bandwidth available in modern graphics hard war
181. ces when configuring your application Summary 21 This page intentionally left blank Chapter 3 Mac Hardware Architecture Overview We ll now step back from the software side of things and look at hardware Most modern personal computers have at least two large processors in them a central processing unit CPU and a graphics processing unit GPU a term coined in the late 1990s In 2001 the number of transistors in GPUs caught up with and surpassed the number within CPUs Although this feat is in large part a result of parallel logic in the GPUs it still speaks loudly to the fact that more and more processing in today s computers is happening on the GPU These are exciting times to be a graphics developer Now that there are more transistors on the GPU than on the CPU graphics developers have been looking at many different ways to push computation to the GPU This trend toward more processing on the GPU was greatly catalyzed by the introduction of programmable shaders in the late 1990s Shading and high level shading languages opened the door to performing more generalized computing tasks on the GPU A necessary complement to complex shading was a place to store those high precision results That need gave rise to the develop ment of floating point framebuffers The lack of precision storage was a signifi cant barrier to generalized computing on the GPU but is no longer an obstacle Furthermore recent GPUs have been chipping a
182. ch has performance consequences Another way of look ing at this same problem is to state that your application should play nicely with the graphics hardware as it will compete for resources with the window system To do so use best software practices draw only when you need to download data when only absolutely necessary and so on Not only will your application performance benefit from judicious use of graphics resources but so will the rest of the user experience Beginning with version 10 4 4 Apple began officially supporting and shipping Intel based Macs This shift in the underlying processor marked the beginning of the latest processor transition for the Mac Apple and Mac developers have weathered numerous processor transitions over the years including switches from Motorola 680X0 processors to Motorola PowerPC 60X series processors to IBM Motorola G3 G4 G5 processors and now to Intel processors Why did Apple make this change Theories abound but a quote from Caroline Schoeder sums up one point of view Some people change when they see the light oth ers when they feel the heat Said differently the G5 was one hot processor literally Where there s heat there s power being consumed which has meant problems for laptop processors The PowerBook platform upon which I m typ ing this very sentence had relatively little performance gain for more than 2 years Obviously something had to change to keep portables in the game
183. coa Classes are deemed Windowing Layer calls Beneath this layer and getting closer to the metal is the Renderer Layer A renderer is the primary term used to describe the software object or structure that graphics applications will interface with to perform rendering on OS X Each renderer represents a set of capabilities in terms of being able to process and execute OpenGL commands Renderers may or may not be associated with a hardware device They are configured created maintained and destroyed in CGL 18 Chapter 2 OpenGL Architecture on OS X Earlier we discussed the very capable software renderer a purely software path for rendering OpenGL commands Hardware renderers are associated with specific hardware devices and accordingly have the graphics process ing capabilities of those devices One of the more notable capabilities of to day s graphics cards is their ability to drive multiple physical displays Accord ingly the renderers associated with these devices support multiple displays as well In OS X each physical display has an associated software virtual screen Renderers are always associated with exactly one virtual screen Macs config ured with more than one graphics card will always have more than one virtual screen Note that the Mac OS provides a mechanism to configure a virtualized desktop from more than one graphics device This virtual desktop allows users to drag applications across the boundaries of t
184. compatible with the other contexts Compatibility implies many things but chiefly that the destination pixel depth color depth and other factors are similar We work around that problem in this example by first exposing a common pixel format through the pixelFormat method and then using that method to construct our pixel format and context for each window s view Let s revisit the code we used for our custom OpenGL view example for initial ization and setup This code with one minor twist does everything we need and is presented in Example C Example C 7 Initialization of an OpenGL View with a Shared Context implementation MyView id initWithFrame NSRect frameRect NSLog MyView initWithFrame if self super initWithFrame frameRect nil _pixelformat SharedContext instance pixelFormat if _pixelformat nil 306 Appendix C The Cocoa API for OpenGL Configuration in Leopard NSLog No valid OpenGL pixel format matching attributes specified at this point we d want to try different sets of pixelformat attributes until we got a match or decided we couldn t create a proper working environment for our application init the context for later construction _context nil return self NSOpenGLContext openGLContext t if context nil only if uninitialized if this is our first time to initialize _context NSOpenGLCo
185. cs chipsets you know that these numbers are quite staggering Typically these numbers are an order of magnitude greater than the graphics bus bandwidth that feeds the chips Correspondingly it s not unusual to see a 10 times perfor mance gain when moving an application from immediate mode rendering to retained mode rendering In short specify your data up front with one of the retained mode mechanisms and reference it later while drawing to reap grand performance rewards Unidirectional Data Flow Once you have your rendering modes established your objective should be to stream data e g vertices indices textures pixels from the host system to the Axioms for Designing High Performance OpenGL Applications 199 graphics device as close to the theoretical bandwidth as is achievable To keep this stream of data flowing and going in one direction it is important not to issue any unnecessary queries or reads from the OpenGL implementation The rule of thumb here is that any OpenGL call that has a return value will likely stall the rendering pipeline You may be wondering why said stalls would occur To optimize throughput nearly any command or packet processing system OpenGL included will buffer the information into batches and submit the batches simultaneously This strategy allows the best amortization of protocol overhead by having a rela tively large amount of data per quantum of protocol information Now further consider the
186. ct separate contexts with separate states except for sharable items For reference the following items can be shared among contexts e Display lists e Buffer objects vertex buffer objects fixer buffer objects Texture objects Vertex and fragment programs and shaders Framebuffer objects Like most windowing system interfaces to OpenGL AGL exposes the ability to duplicate context contents Specifically in Example 7 6 we took pains to demonstrate that each context was different by setting a unique g1C1earColor for each However if we d like the rest of the state to be the same between these two contexts we d use the AGL method aglCopyContext to specify a copy from one context to another This routine takes arguments for the 108 Chapter 7 The AGL API for OpenGL Configuration source context the destination context and the attribute mask describing which pieces of state to copy Specifically the mask and constants are the same ones that the g1PushAttrib call uses For our example we d write code as in Example 7 7 Example 7 7 Copying the Context State Between Two Contexts in AGL aglCopyContext context otherContext GL ALL ATTRIB BITS One last note on shared contexts which applies to the general concept of con text sharing not to any particular implementation When you are using con text sharing and you reach the point in your application where you need to destroy the second sharer context make sure that you
187. cular that defines the Mac style You prob ably thought that we d say simplicity or consistency but neither is as core to the Mac as style You d be right however in assuming that both simplicity and consistency are two key aspects of what makes developing for and using the Mac such an exceptional experience And it s true that both consistency and simplicity are aspects of the overarching style that is the Mac Nevertheless we d be doing a disservice to the Mac to suggest that there isn t substance be hind that style because there is From its solid BSD underpinning through years of evolution in software APIs the Mac has remained a robust platform From a user perspective the Mac has always been at its core a smooth fun and stylish user experience And now with OS X the Mac is also one of the best development platforms available From the developer side of the equation things have not always been so elegant of course The Mac OS of the pre OS X days was a much more interesting development experience Beginning from their roots in Pascal and through their evolution into the C language the OS 9 and its brethren from earlier days were a lot more challenging Partly in response to these difficulties NextStep a start up outgrowth of Apple in the early 1990s worked hard to simplify the modern development experience and the results of its work are now available in Mac OS X For us to describe the entire development histor
188. d a much more detailed discussion of how those pieces work in a companion book in this series 21 260 Chapter 13 OpenGL Extensions Finally an else clause performs our preprocessing checks We took this tack because if we fail to compile this code no shader code will ever be executed even on platforms that support it Our preprocessing checks really just validate that we know how to build our application so that it can move on to the next step runtime checking for these extensions which we look at in the next section Example 13 1 Querying for Extensions in a Valid OpenGL Context void prepareOpenGL setup projection glMatrixMode GL_PROJECTION glLoadIdentity glOrtho 1 1 1 1 1 100 do we have shading extensions NSLog Has OpenGL Shader d n self hasShaderExtensions if TRUE self hasShaderExtensions ii NSBundle res NSBundle mainBundle NSString fragsource NSString stringWithContentsOfFile res pathForResource test ofType frag NSString vertsource NSString stringWithContentsOfFile res pathForResource test ofType G vert const char fragsource c fragsource UTF8String const char vertsource c vertsource UTF8String if defined GL VERSION 1 3 amp amp defined GL ARB shader objects amp amp defined GL ARB shading language 100 amp amp defined GL ARB vertex shader amp amp defined GL ARB fragme
189. d efficiently It also provides a fair degree of specificity for window management You can use the glut InitDisplayMode as shown in Example 9 2 to specify a variety of flags to set the visual that is used For example you can use any combination of the bit flags as described in Table 9 2 to customize which visual you use These bit fields are described in complete detail in the glut InitDisplayMode manual page and we present only a few in Table 9 2 A simplified version of the use of this visual specification was presented in Example 9 2 This function along with its bit field settings allows you a coarse degree of control in the visual qualities of your application As we ve seen in other chapters selecting a visual can be a very detailed process and one Table 9 2 gluti that your application needs to specify fully GLUT provides nitDisplayMode Bit Field Tokens Token Description GLUT RGBA GLUT RGB Synonymous tokens to select a visual with RGBA pixel formats The default if no other format is specified GLUT SINGLE Single buffered visual token The default if neither GLUT DOUBLE nor GLUT SINGLE is present Q LUT DOUBLE Double buffered visual token Has priority if GLUT_SINGLE is also present GLUT_ACCUM Token for accumulation buffer visuals GLUT_ALPHA Token to choose alpha channel visuals GLUT_DEPTH Token to select a depth buffered visua
190. de of the United States please contact International Sales 317 382 3419 international pearsontechgroup com Visit us on the Web www awprofessional com Library of Congress Cataloging in Publication Data Kuehne Robert P OpenGL programming on Mac OS X architecture performance and integration Robert P Kuehne J D Sullivan p cm Includes bibliographical references and index ISBN 13 978 0 321 35652 9 pbk alk paper ISBN 10 0 321 35652 7 1 Computer graphics 2 OpenGL 3 Mac OS I Sullivan J D II Title T385 K82 2007 006 6 6 dc22 2007011974 Copyright C 2008 Robert P Kuehne and J D Sullivan All rights reserved Printed in the United States of America This publication is protected by copyright and permission must be obtained from the publisher prior to any prohibited reproduction storage in a retrieval system or transmission in any form or by any means electronic mechanical photocopying recording or likewise For information regarding permissions write to Pearson Education Inc Rights and Contracts Department 501 Boylston Street Suite 900 Boston MA 02116 Fax 617 671 3447 ISBN 13 978 0 321 35652 9 ISBN 10 0 321 35652 7 Text printed in the United States on recycled paper at Donnelley in Crawfordsville Indiana First printing December 2007 For my family Bob For my family John In memory of democracy This page intentionally left blank Contents List Of
191. dering on the Mac Windowing systems primarily operate on a data structure known in OS X as a surface Surfaces are a logical construct that includes the memory and metadata required to act as a destination for rendering These surfaces may correspond to visible pixels on the display or they may be invisible or off screen surfaces maintained as a backing store for pixel data On the Mac OS four APIs manage or interact with surfaces API Layers 15 Core Graphics CGL Core OpenGL AGL Apple OpenGL AppKit or Cocoa Of these only Core Graphics is not an OpenGL specific interface Of the OpenGL specific windowing or surface related interfaces CGL is the lowest logical layer It provides the most control when managing the interface between OpenGL and the windowing system GLUT is the highest level and easiest to use of these layers but has limited UI capabilities This is followed by the App Kit Cocoa classes which provide the highest level fully functional windowing interface to OpenGL on OS X AGL lies somewhere in between these two ex tremes and is used primarily by legacy applications or applications that draw their own user interface rather than using the Quartz window system compo nents defined in AppKit Figure 2 2 is a basic diagram that shows the interaction of these software layers There are some simple relationships between the layers in Figure 2 2 and some not so simple relationships For instance AGL depends on and
192. ding a pixel format and ultimately choosing a drawable or surface on which to render Depending on whether you re using CGL AGL or Cocoa you ll specify a particular token indicating your interest in using a single buffered or a double buffered pixel format as seen in Table 11 1 Typically if you re displaying data on screen the only high quality way to do so is with double buffered pixel formats The primary reason for choosing double buffered drawing is to ensure that the user of your application doesn t see image tearing a visual artifact that stems from the fact that your application drew two partial images to the framebuffer as it was displayed If your application isn t displaying data directly to the user perhaps it is rendering graphics frames in a nonvisible buffer so a single buffered pixel format may be the way to go Double buffered vertical blank synchronized applications can achieve a maxi mum frame rate that matches the refresh rate of the monitor on which the ap plication windows are displayed This is a very important metric to be aware of because it means that even in the best case you ll still get only 60Hz on a mon itor with that refresh rate Another consequence of this limitation when using a double buffered pixel format is that if your application takes one femtosec ond longer than a single frame 16 67 ms frame to draw that frame will not appear until the next swap boundary Thus your application will be waiting
193. do not delete the shared contents within that context If one context cleans up shared objects but another context continues to use those contents it s possible that visual data corruption or even worse a crash of the application could occur The solution to this prob lem is that as with data shared through pointers only one application element should be responsible for both construction and deletion of shared elements Thus when you are sharing data between contexts make sure that shared ob jects are created once used many times and then deleted once only when the last sharer of those contents has completed its usage Alternative Rendering Destinations In AGL as in CGL and Cocoa an increasingly more popular OpenGL render ing technique is to render to a hardware accelerated nonvisible buffer There are numerous reasons for doing so most commonly to create an image to use somewhere else as a texture For example you might create an image to rep resent a reflection image in service of creating nice shiny water A variety of rendering destinations can be used to create this sort of image for reuse or for any other purpose In this section we ll look at techniques to render to modern off screen render destinations as well as some bridge technology techniques such as render to texture used for compatibility with older hardware Off Screen Surfaces Apple refers to off screen buffers as a particular form of alternative render in
194. dow your code here event handler loop stay here until no longer in fullscreen mode upon exit we transition back to windowed mode and release the display CGReleaseAllDisplays return error 150 Chapter 8 The Cocoa API for OpenGL Configuration For simplicity we use the global form of display capture that is the form in which all displays are captured You may have a need or a preference to control which display you capture more precisely For those circumstances Apple pro vides CGDisplayCapture and CGDisplayRelease to specify a particular display And that s really all there is for display capture as it relates to OpenGL except for the event handling part which we ll discuss next Event Handling One key caveat to full screen windows regardless of the amount of OpenGL window system integration relates to event handling Who s handling the events now that your window system and UI elements are hidden Yes Virginia this is another headache of full screen windows but you ve got to do it Otherwise nothing will be handling events making it very difficult to even quit your application So what s an application to do especially in Cocoa As we do a number of times throughout the book we will not go into the details of this operation as numerous Cocoa books deal with this topic Here we simply present Example 8 9 in which code modeled closely on an Apple source exam ple shows what you might
195. dow is updated or resized If your application creates a new thread that is distinct from the main NSApplication thread and starts issuing OpenGL calls on this thread voila A thread contention problem is created To avoid threading issues of this sort Apple added the entry points CGLLockContext and CGLUnlockContext as of OS X Tiger 10 4 If you wish to perform OpenGL rendering or state changes in a thread that you ve created in your Cocoa application that uses an NSOpenGLView you must bracket those calls with calls to CGLLockContext and CGLUnlockContext to avoid contention issues between the main thread and your ancillary thread Data Parallel Computation SIMD This section focuses on the programming paradigm know as Single Instruction Multiple Data SIMD In this model data that has an intrinsic parallelism say a color vertex or normal has a computation applied to each of its elements in parallel Put differently one instruction is applied to multiple data elements simultaneously PowerPC Modern PowerPC processors i e G4 and later have vector processing units dubbed AltiVec units that work as we just described That is AltiVec 42 Chapter 4 Application Programming on OS X instructions are vector instructions that allow the application of the same op eration to multiple data elements in parallel In some cases if the data elements are large enough the instructions may operate on a single data element or even a
196. e Typically kCGLCPReclaimResources is used when the context usage is ex pected to be much simpler after the resources have been freed For instance perhaps your application no longer intends to use vertex buffer objects vertex array objects or display lists but still makes calls to g1DrawPixels In this case it s worth the small amount of setup overhead needed to reestablish the internal draw pixels state given that you ll be freeing a great deal of memory associated with the other object types in the OpenGL driver Context Management 67 Read Only Parameters kCGLCPDispatchTableSize Used internally by OS X and tools for memory allocation kCGLCPSurfaceBackingSize Used to retrieve the amount of memory allocated to support the drawable attached to the current context kCGLCPSurfaceSurfaceVolatile Used internally by OS X for efficient surface management kCGLCPCurrentRendererID Use as an argument to CGLGetParameter to retrieve the ID of the current renderer kCGLCPGPUVertexProcessing Use to determine whether the GPU associated with the renderer will be used for vertex shading kCGLCPGPUFragmentProcessing Use to determine whether the GPU associated with the renderer will be used for fragment shading Renderer Information Obtaining information about the renderers available on a Mac is a four step process Here we ll show a simple example and then elaborate on the four steps needed to complete th
197. e CGL AGL Cocoa GLUT Chapters 6 through 9 explore details behind the in dividual APIs Each API is covered in detail in its own chapter and the APIs are compared and contrasted in each chapter These chapters form the core of this book Interoperability Chapter 10 collects a variety of interesting OpenGL and other Mac API integration ideas This chapter describes how to incorporate video in an application with QuickTime perform image effects on textures or scenes with Core Image and process CoreVideo data in an application Performance Chapters 11 and 12 describe the basics of analyzing performance of OpenGL applications and offer tips about where common problems may surface and how they might be resolved Analysis tools architecture data types and solutions are covered Extensions Chapter 13 presents a guide to detecting integrating and using OpenGL extensions This chapter introduces extension management princi ples and tools and provides details on how to perform such management specifically on the Mac xxvi Preface Additional Resources As both OpenGL and the Mac platform evolve so must developers appli cations At our website www macopenglbook com we provide our example OpenGL code as well as other OpenGL related resources Additionally we track and provide corrections for any errata and typos Although we aspire to Knuth like greatness we are open to the idea that bugs may yet lurk within these pages Should y
198. e so if you can spare it this technique will be pretty efficient But the reason we re explaining this method at all is that the hardware on which you run po tentially might not support a real off screen technique like FBO so a technique like render to texture may be required And that brings us to the final point This technique is window dependent You ll notice that we re copying only a fixed area of pixels from within our drawing surface in our example If we wanted to capture the entire area we d have to monitor the size of the drawable area using the reshape routine and ensure that the width and height of the copy call were updated accordingly Another way of looking at this problem is to consider texture resolution You ll need a window at least as big as the texture size you want to use because you re directly copying pixels from within it Thus if your user wants a win dow smaller than this texture size either you have to fall back to a smaller sized texture or you have to limit the window minimum size At any rate the hairy details of the bookkeeping surrounding pixel sizes are not the most fun part of this technique and constitute another way in which FBOs are a better solution In this section we ve covered how to perform textured renders from the con tents of a texture filled by another render The technique is very portable but carries some overhead concerning texture and window sizes and has some per formance limitations
199. e this is another option for GL function binding Summary Whatever your level of OpenGL programming sooner or later extensions will be part of your future And when you do have to use them there are a number of ways of addressing how to efficiently manage their complexity In this chapter on OpenGL extensions we explored a variety of aspects of extensions on Mac OS X We looked at the particulars of how to find choose and use extensions through native OpenGL mechanisms We also explained how to perform the same process with external extension management tools Finally we covered both approaches with an eye toward Mac specifics but remained grounded in the reality of multiplatform development At this point you should be conversant in extensions and well prepared to use them to make your application faster more well rounded through advanced features or more compatible with a variety of platforms Extensions are a nec essary part of keeping your application up to date on the feature and compati bility curve of OpenGL development on the Mac Summary 275 This page intentionally left blank Appendix A X11 APIs for OpenGL Configuration X11 X Window System Version 11 is a network transparent window system that is widely used on Unix based workstations It is a client server based win dowing environment where a single server services multiple client windows of applications written for X11 The first windowing system on w
200. e 9 1 performs this operation to include the glut h header using a preprocessor check to deter mine whether we re building on the Mac and if so to adjust where we find GLUT to use the framework resolved path Those are really the only two unique elements to using GLUT on the Mac Simple enough Now let s look at fleshing out this code Example 9 1 GLUT Header Inclusion on the Mac dif defined __APPLE_ include lt GLUT glut h gt else include GL glut h endif Pixel Format We ll now look at a complete application from window creation to GL initial ization through swap buffers This code is presented here for your edification but not because we plan to explain it in painstaking detail As we ve said before GLUT is GLUT is GLUT You ll find that the code we write here will function on many platforms and the GLUT examples on the Mac are a great way to learn more about how to use the API In fact Apple ships a complete set of GLUT examples with its developer tools you ll find them in Developer Examples OpenGL GLUT Now lets move on to our code It renders a 000 GLUT Configuration Example p Figure 9 5 GLUT Project Results Showing Visual Selection and Rendered Object Configuration and Setup 167 simple animated shape but doesn t do much else The results of Example 9 2 are seen in Figure 9 5 Example 9 2 Basic GLUT Sample Application void prepareOpenGL myAngle 0 myTime 0 void draw
201. e GL APPLE texture range extension Other extensions are named for the companies that formulated and specified them for example SGI 3DLABS or ATI Often ARB member companies will create parallel extensions that is two ex tensions with essentially the same functional purpose but different interfaces If these companies wish to collaborate on consolidating these similar specifi cations into a single unified proposal they will often create a working group within the ARB so as to select the best aspects of each proposal and merge them into one When an extension is supported by more than one ARB member it is called an EXT extension The GL_EXT_framebuffer_object extension which is defined to do off screen rendering is an example of such an extension If a vendor or an EXT extension gains enough favor with the voting ARB mem bers it can be put to a vote to approve it as an ARB extension With the approval of a two thirds majority of the voting ARB members the extension can gain ARB status Often vendor extensions go through a process of gaining acceptance 8 Chapter 2 OpenGL Architecture on OS X amp r IrisGL Introduced OpenGL 1 1 OpenGL 1 2 OpenGL 1 3 OpenGL 1 4 OpenGL 1 5 OpenGL 2 0 OpenGL 2 1 amp OpenGL 1 0 3 2 1995 1998 2001 200220032004 2007 Figure 2 1 OpenGL Version History Timeline as an EXT extension by other vendors before being promoted to the core specification Each o
202. e OS X revolution of the Mac operating system began in 2001 Darwin the open source core of OS X is derived from Berkeley Systems Division BSD Unix The introduction of a Unix core has had a profound and arguably positive effect on software developers for the platform Along with the time tested and industry standardized architecture of Unix its multiprocessing capa bilities and advanced virtual memory semantics came the diverse and powerful shell programming environment libraries and tools familiar to Unix applica tion developers The addition of scripting environments such as Perl Ruby and Python can further catalyze the development and testing process The X11 window system is also supported on OS X With an industry standard OS kernel windowing system and graphics API graphics applications written on other Unix platforms can be ported to OS X with relative ease Mac OS X Versions Mac OS X has gone through several major iterations and many more minor iterations during its life so far Each minor release number for OS X represents a large chunk of functionality Releases such as 10 1 10 2 and 10 3 represent at least a year of engineering time for Apple Another way to think of it is that each time there s a new cat such as Panther Tiger or Leopard assigned to a designated OS X it represents a substantial software release for the OS In the developer community and sometimes even in the popular press these major rel
203. e a e EEE 173 Cocoa Image NoImage nore rt rrr Rote REDE RER 174 Basie NSEIf ge egwewktet Bee S Ax AT EE s 174 NS Image to OpenGlu elles eErerc TOR RI P RE UR E RR 176 OpenGL to NSXfage u 6 eere nere tudine he iHe QU 182 Quick DID uror errorae xp basn eed dex 184 OVERVIEW cci pte hue ro IEEE tnde tpe ed taedet hades 184 Quick Time to OpenGL 5 2 ut ReRPIR RETE araras RES 185 OpenGL to Quick lime 5 oos ssp parece TIE E ee PEU ENS 191 High Performance QuickTime in OpenGL sesssss 192 SUMIMAT Ys SRM 193 Chapter 11 Performance 195 ug rrari dah aise ba ake ae ok Gk GA Eee ae Dee GR eae 195 Axioms for Designing High Performance OpenGL Applications 60 cece eee eee eee 196 Minimize State Changes silia mede ac etr e RONE KESE 196 Retained Mode versus Immediate Mode Rendering 198 Unidirectional Data Flow 5 oio eet terere 199 Use Shaders Where Possible cece cece eee e eee tenes 200 OpenGL for Mac OS X Rules of Thumb for Performance 201 Minimize Data Copies sessios vendeeee Seder ber ERR new eed 201 x Contents The OpenGL Multithreaded Engine 0 0 00000 202 Minimizing Function Call Overhead 0 0 00085 204 Minimize CPU and GPU Idle Time by Using Asynchronous Calls tnncrsk rates veu E EEE P ES 204 Share Data Across Contexts When Possible sssssuu 207 hub nut E TE 207 Brame Rates wit cscs acwctelse dees
204. e bound to that FBO is ready to be used We ll demonstrate this usage of the FBO next even though we ve really covered it all in the setup It couldn t be much simpler Example 8 12 shows our drawRect routine Example 8 12 Cocoa drawRect Routine for FBOs void drawRect NSRect rect render to offscreen glBindFramebufferEXT GL FRAMEBUFFER EXT fboID self drawIntermediateContents glBindFramebufferEXT GL FRAMEBUFFER EXT 0 render to final self drawFinalContents complete rendering amp swap glFlush self openGLContext flushBuffer Finally for interest we present the code we actually draw with in those routines in Example 8 13 Example 8 13 Cocoa Draw Methods for Contents of the FBO and the Final Render void drawIntermediateContents glClearColor 1 1 0 1 glClear GL_COLOR_BUFFER_BIT GL DEPTH BUFFER BIT glMatrixMode GL MODELVIEW 156 Chapter 8 The Cocoa API for OpenGL Configuration glLoadIdentity giTranslatef 0 0 1 glColor3f 0 1 1 glBegin GL QUADS float ww 9 float hh 9 float zz 0 0 glDisable GL TEXTURE 2D glVertex3f ww hh zz glVertex3f ww hh zz glVertex3f ww hh zz glVertex3f ww hh zz glEnd void drawFinalContents giClearColor 0 5 8 1 IMatrixMode GL MODELVIEW ILoadIdentity IRotatef angle 0 0 1 Q Q Q LTranslatef 0 0 1 IColor3f 0 1 0
205. e fadeaway of g1TexImage2D There s a new rogue at the top of 240 Chapter 11 Performance 000 Statistics E fk Save As Text Clear GL Function of Calls Total Time usec Avg Time usec GLTime App Time glVertex2f 11 168 78 1789294 0 16 55 45 9 03 glTexCoord2f 11 168 641 631585 0 06 19 57 3 19 glReadPixels 34 243652 7166 24 7 55 1 23 glEvalMesh2 1 088 208370 191 52 6 46 1 05 glBegin 70 174182 2488 32 5 40 0 88 glTeximage2D 2 121487 60743 70 3 77 0 61 glTexSublmage2D 34 41432 1218 59 1 28 0 21 CGLFlushDrawable 35 8976 256 46 0 28 0 05 7 Total elapsed GL function time 3226647 37 usec Estimated time in GL 16 29 Show slice lt 25 of 25 gt Context ID All Contexts Figure 11 15 ptm3 OpenGL Statistics our list now glVertex2f accounts for more than 55 percent of the time spent in OpenGL Perhaps we can apply a retained mode technique for the glVertex2f problem as well Please Tune Me 4 Please Tune Me 4 takes a huge stride forward relative to ptm3 By encapsulat ing the huge number of mesh vertices in a display list we ve avoided a tremen dous amount of data copying bus traffic and function call overhead through OpenGL Display lists are a very easy way to get big performance gains when rendering static geometry Making the display list change resulted in about an 1800 percent gain in performance in the vicinity of 36 frames per second Our little application is growing up At this point l
206. e into Window and arrange it as shown in Figure 8 6 The final step in this setup operation is to change the CustomView to be your MyOpenGLView object To do so open the Inspector if it s not open click CustomView PA Figure 8 6 Adding a Custom View to a Window in Interface Builder NSOpenGLView 125 4 Window O O MyOpenGLview Custom Info Custom Class E Class MyOpenGLView NSBox NSBrowser NSButton NSClipView NSColorWell NSComboBox NSControl NSForm NSImageView NSMatrix Figure 8 7 Binding a Custom View to the NSOpenGLVi ew Subclass Object the Tools menu and Show Info item and click on the CustomView you just dragged into place Choose the Custom Class pop up menu entry in the Inspector window and navigate and choose MyOpenGLView from the list You should see results like those shown in Figure 8 7 We could have handled all of this setup configuration and routing programmatically but this book isn t about Cocoa plumbing so we ll stay at this level for now In a later section we ll explore Cocoa configuration of a generic NSView which allows us a bit more flexibility For now switch back to XCode and we ll dig into the code In XCode open the file MyOpenGLView m We ll now begin adding methods to handle key elements of the OpenGL render cycle We start by adding a method to select pixel formats This code performs pixel format s
207. e is preferred NSOpenGLPFAMinimumPolicy YES Change to the selection policy described Selection policy Consider only buffers greater than or equal to each specified size of the color depth and accumulation buffers NSOpenGLPFAMaximumPolicy YES Change to the selection policy described Selection policy For non zero buffer specifications prefer the largest available buffer for each of color depth and accumulation buffers NSOpenGLPFAOffScreen YES Consider only renderers capable of rendering to an off screen memory area that have a buffer depth exactly equal to the specified buffer depth size An implicit change to the selection policy is as described Selection policy NSOpenGLPFAClosestPolicy NSOpenGLPFAFullScreen YES Consider only renderers capable of rendering to a full screen drawable Implicitly defines the NSOpenGLPFASingleRenderer attribute NSOpenGLPFASampleBuffers Unsigned integer The value specified is the number of multisample buffers required 130 Chapter 8 The Cocoa API for OpenGL Configuration Token Description NSOpenGLPFASamples Unsigned integer The value specified is the number of samples for each multisample buffer required NSOpenGLPFAColorFloat YES Consider only renderers capable of using floating point pixels NSOpenGLPFAColorSize should also be set to 64 or 128 for half or full precision floating point pixels
208. e library was created including both extension tokens and extension functional bindings That s a fair bit of complexity but it s nicely wrapped and using the library to query extensions is very straightforward 270 Chapter 13 OpenGL Extensions To use GLEW in an application there are several ways of accomplishing the same tasks We ll look at one approach that s a close analog of the way we pre viously investigated shader support in an earlier example The basic process is this 1 Initialize the library g1ewInit I 2 Query for a particular extension if GL TRUE GL ARB shader objects 3 Use that extension and its API calls g1CreateProgramObjectARB We ll perform those steps in conjunction with using OpenGL Shading Language shaders with our basic example as before We begin with our prior example but change the headers from including the GL extensions to including the GLEW header as shown in Example 13 9 The only caveat with GLEW is that because of the way it manages extensions it must include its header before any other OpenGL header as our example does Next we modify our prepareOpenGL routine to initialize GLEW and then prepare our shaders as before pending success As you look at the code for Example 13 10 you ll notice that the only difference between this version and our last version is that we initialize GLEW We preserve our compile time checks on the off chance that we re building under
209. e on for the pixel format and type you re using is a matter of measuring the performance The large matrix of changing possibilities between what the graphics hardware desires and which paths are tuned within the OpenGL framework is an unbounded problem over time In a macroscopic sense measuring OpenGL performance in general falls in the same category It must be benchmarked The key to high performance drawing with pixel data is to match the most com mon formats and types of the graphics hardware such that a format type trans formation does not take place The tricky part is that the precise formats types that are handled natively are not very well published As a rule the canonical 4 component 8 bits per component types are very well served For any hardware made as recently as 2001 both ATI and NVIDIA graphics hardware natively support GL BGRA GL UNSIGNED INT 8 8 8 8 REV pixels They will also handle GL_RGB and GL RGBA formats with the type GL UNSIGNED BYTE The 2001 cutoff date is somewhat arbitrary of course It s mostly a date chosen to represent reasonably new hardware that gives a great deal of coverage for the Mac computers that are running OS X For 16 bit formats graphics parts from both vendors have an affinity for the GL UNSIGNED SHORT 1 5 5 5 REV type with a type of GL BGRA They also natively support the 16 bit YCBCR format with a gravity toward the GL UNSIGNED SHORT 8 8 REV APPLE type
210. e rendering 152 53 choosing 21 definition of 18 drivers 21 hardware vs software 19 in AGL 104 7 107t incompatibility of 141 42 Index 329 renderers continued obtaining information on 68 76 selection in CGL 56f 61 63 switching between 19 21 rendering retained vs immediate mode 198 200 rendering destinations alternative 152 62 Resources view 233 233f retained mode rendering 198 200 S Scripts view 234 235f secondary color 10t shader instruction limits 201 shader performance 226 shader use 200 201 shadow functions 11t Shark 3 227 Single Instruction Multiple Data SIMD 42 singleton 142 144 146 47 software layering in AGL 90 91 91f 91t software vs hardware renderers 19 southbridge of CPU 24 24f sRGB textures 11t state change minimization 196 98 Statistics view 231 232f stencil wrap 10t stereo rendering 61 subset state 223 24 subtexturing 9t surfaces and windowing systems 15 16 system tools in OS X 226 28 T teardown 150 texture alignment considerations 225 26 and data integrity 176 compressed 225 texture data handling 221 25 texture ID 188 89 texture LOD bias 11t texture objects 10t texture proxying 9t texture range extension 205 7 texture NSIMage as 179 82 texturing with pbuffers 81 threading 41 42 42f 330 Index throughput 209 Tiger see also OS X improvements of 246 48 OTKit in 185 RAM requirements 31 re
211. e same OpenGL code Independently of how the image gets to the screen the way we generate the im age is the same pure sweet light graphics goodness OpenGL The window ing layer above OpenGL is an obviously essential element in using a particular platform Yet OpenGL graphics commands are distinct separate and orthogo nal to windowing systems That is a key piece of what makes the original design OpenGL so powerful Necessarily then we need ways of querying pieces of information about OpenGL itself independently of the window system in which it integrates and this information can be used to define the OpenGL The OpenGL platform as defined by the OpenGL specification is the unique combination of two strings queried through the g1Get String call The OpenGL function g1GetString 248 Chapter 12 Mac Platform Compatibility Table 12 1 glGetString Tokens Token Information GL_VENDOR The company responsible for this OpenGL implementation Technically despite what this string reports frequently ATI or NVIDIA Apple maintains the OpenGL driver and is the key contact for any questions or problems This string can provide a useful hint in determining the underlying hardware used by this context GL_RENDERER A specific name defining the hardware used by this OpenGL context GL_VERSION OpenGL version information Fields are space delimited within this string The first field contains a version nu
212. e setFlipped YES newImage lockFocus create a draw context bitmap drawInRect NSMakeRect 0 0 Size width size height newImage unlockFocus release the draw context return newImage This method simply renders our bitmap into an NSImage and returns this new image As in our prior example transformImage we use Quartz to do the ren dering and use the lockFocus unlockFocus pair to direct Quartz rendering appropriately Also as before we use the setFlipped method to take care to get the orientation of the image in native OpenGL coordinates After those two Cocoa Image NSlmage 183 manipulations we end up with a lovely NSImage that we can use in another part of a Cocoa application that takes an image QuickTime In this section we ll explore another way of integrating native Mac technol ogy with your OpenGL application Specifically we ll look at how to integrate video content using the QuickTime API Although there are lots of image based techniques for performing video rendering using Apple s QuickTime API pro vides a number of benefits Chief among these is the wide variety of codecs available for easy reading and writing of a variety of video formats Quick Time provides a number of other nice features as well including time manage ment audio playback and a full complement of easy video navigation controls Integration of QuickTime with OpenGL is a little tricky but once you get it w
213. e target for the specified context aglTexImagePBuf fer Binds a pixel buffer as a texture analogous to glTexImage2D 110 Chapter 7 The AGL API for OpenGL Configuration Example 7 8 Pbuffer and Windowed Context Creation in AGL int main int argc char argv setup the pixelformat GLint attribs AGL_RGBA AGL_DOUBLEBUFFER AGL_ACCELERATED AGL_NO_RECOVERY AGL_DEPTH_SIZE 16 AGL_NONE Is const int width 451 const int height 123 AGLPixelFormat pixelFormat AGLPbuffer pbuffer AGLContext context pbContext long virtualScreen GDHandle display2 CGDisplayIDToOpenGLDisplayMask CGMainDisplayID GDHandle display GetMainDevice Rect windowRect 100 100 100 width 100 height WindowRef window pbuffer pixelformat and context setup and creation printf Sd n display2 pixelFormat aglChoosePixelFormat display2 1 attribs pbContext aglCreateContext pixelFormat NULL aglDestroyPixelFormat pixelFormat aglCreatePBuffer width height GL TEXTURE 2D GL RGBA 0 amp pbuffer bind pbuffer virtualScreen aglGetVirtualScreen pbContext aglSetCurrentContext pbContext aglSetPBuffer pbContext pbuffer 0 0 virtualScreen draw into pbuffer drawPBuffer window pixelformat and context setup and creation pixelFormat aglChoosePixelFormat amp display 1 attribs context aglCreateContext pixelFormat NULL aglDestroyPixel
214. e two types are syntactically the same GDHandle and AGLDevice Similarly for AGL methods referring to drawables CGra Ptr and AGLDrawable are interchangable In much of the code pre sented in this book and in Apple examples these types are interchanged but it s not explained why directly The reason they are interchangeable is that the AGL types are simply typedefs of their Carbon base types Please note however that QuickDraw is deprecated in Leopard Pixel Format and Context 103 full screen example Window creation the next step is just the standard Car bon window creation and is beyond the scope of this book However the necessity of having our window setup is visible in the final step in this section in which we bind the AGL context to the AGL drawable In our full screen example we did this create and bind operation in a single step through aglSetFullScreen here because we re binding to an already created Window we use aglSetDrawable We use the Carbon adapter GetWindowPort to convert our WindowRef into an AGLDrawable type The piece in this section is to call aglUpdateContext This method is an AGL required method used any time the AGL drawable changes size As we just created and bound our window it s prudent to ensure that the AGL context is informed of the AGL drawable s size at this point The final section of the code in Example 7 4 is also similar to our full screen example The essence of this section is to initiali
215. eProgramObjectARB return myglCreateShaderObjectARB amp amp myglShaderSourceARB amp amp myglCompileShaderARB amp amp myglCreateProgramObjectARB amp amp myglAttachObjectARB amp amp myglLinkProgramARB amp amp myglUseProgramObjectARB const char OL RTLD LAZY RTLD GLOBAL Example 13 8 Our Application s OpenGL Initialization Code void prepareOpenGL setup projection glMatrixMode GL_PROJECTION Utilization and Binding 267 glLoadIdentity glOrtho 1 1 1 1 1 100 do we have shading extensions if TRUE self hasShaderExtensions amp amp TRUE self resolveShaderSymbols load shader from disk bundle NSBundle res NSBundle mainBundle NSString fragfile res pathForResource test ofType frag NSString vertfile res pathForResource test ofType vert J NSString fragsource NSString stringWithContentsOfFile fragfile NSString vertsource NSString stringWithContentsOfFile vertfile fragsource UTF8String vertsource UTF8String const char fragsource c const char vertsource c dif defined GL VERSION 1 3 amp amp defined GL ARB shader objects amp amp defined GL ARB shading language 100 amp amp defined GL ARB vertex shader amp amp defined GL ARB fragment shader vShader fShader myglCreateShaderObjectARB GL VERTEX SHADER ARB myglCreateShad
216. eading packages Threading Manager and Mul tiprocessing Services Both of these threading packages are part of the Core Services framework Multiprocessing services allows pre emptive scheduling of threads Threading Manager will schedule threads cooperatively sharing the available resources among the threads Cocoa applications can and should leverage the NSThread class for pre emptively scheduled threads This is part of the Foundation framework Threading Manager Multiprocessing Services and NSThread are all built on top of the POSIX threading interface in OS X This in turn is built on top of the Mach threading interface Figure 4 1 Threading 41 NSThreads Carbon Thread mgr Mach Threads Figure 4 1 Threading Layer Cake Thread Packages on Top of POSIX on Top of Mach Threads For OpenGL applications on OS X only a single thread may generate OpenGL commands for a given OpenGL context at one time This with some consider ation is somewhat self evident Consider the rendering output you would get if you interleaved rendering commands and OpenGL state changes from two different threads at one time One of the more insidious threading problems for OpenGL applications on OS X arises with the use of the Cocoa NSOpenGLVi ew class This class does some im plicit CGL and OpenGL calls and will modify the OpenGL context accordingly These implicit calls most frequently occur when your application win
217. ease versions are interchangeably referred to by their code names Because we have been working on Mac OS X for years these names are an in nate part of our lexicon but we want to make sure we re not confusing you 33 Table 4 1 Mac OS X Versions and Code Names Version Number Code Name 10 0 Cheetah 10 1 Puma 10 2 Jaguar 10 3 Panther 10 4 Tiger 10 5 Leopard 10 6 Ocelot Manx Margay Serval dear reader So for your viewing edification and entertainment we present in Table 4 1 a list of the Mac OS version numbers and release names current as of this publishing For fun we ve added some speculative suggestions for future versions too System Configuration You can determine which GPU core your machine has by using the Apple System Profiler Go under the Apple menu and select About this Mac Click the More Info button Under the hardware list you will see a category for PCI AGP cards An AII part will have a label such as ATY Radeon X1600 We ll discuss in detail both how this information can be programmatically queried and how these tools work later in this book Specifi cally programmatic inquiry of hardware capabilities is discussed in Chapter 13 and tools for inspecting and analyzing your OpenGL code and environment are explored in Chapter 11 Power Management The Mac OS can be configured so as to conserve power by putting the CPU the display and the hard dr
218. eated managed and destroyed To allocate configure and size them their attributes must be described The set of attributes that describe a framebuffer is collectively known as the framebuffer s pixel format Pixel format is the termi nology most commonly used to describe this idea on the Mac OS because that is how it is referred to in the CGL interface Given that X11 also runs on the Mac OS the term visual is used to describe the layout of a framebuffer We ll stick with pixel format for our discussion however 54 Chapter 5 OpenGL Configuration and Integration Chapter 6 The CGL API for OpenGL Configuration Overview Since the transition from IrisGL to OpenGL this graphics API has been indepen dent of the windowing system of the operating system on which it runs This aspect of the API was the primary redesign requirement of IrisGL to make it an open standard and multiplatform rather than running on just the Iris worksta tions on which it originated When windowing functionality was first written out of the IrisGL API it needed anew home This home is GLX the interface between OpenGL and X11 Shortly after this transition WGL was created as an interface between OpenGL and Windows On OS X the original interface developed between the Quartz windowing system and OpenGL was called CGL short for Core OpenGL The AGL Apple GL interface for Carbon applications was written later and is layered on top of CGL
219. ect is typically a texture Build and initialize the FBO by attaching the target objects Bind the FBO and render the FBO contents Unbind the FBO and render the final scene using the target object where we ll store our texture object and FBO IDs Example 8 10 Custom View Header for FBO Example Code import lt Cocoa Cocoa h gt import lt OpenGL OpenGL h gt interface MyOpenGLView NSOpenGLView 154 Chapter 8 The Cocoa API for OpenGL Configuration GLuint fboID GLuint textureID float time float angle void angleUpdate NSTimer tt void reshape end We next look at the code in our prepareOpenGL method As before this is the place where we create and initialize things that we need to set up once per context We look at the entire prepareOpenGL method in Example 8 11 so es sentially we see the first two phases of our outlined FBO usage build and ini tialization for both our target texture and our FBO We begin by creating and initializing a texture object which we ll both bind to our FBO and use in our final rendering We then create an FBO and bind it to that texture for color ren dering Finally after configuration we unbind our current FBO by binding the FBO ID of 0 Example 8 11 OpenGL Setup for FBO Rendering void prepareOpenGL glMatrixMode GL_PROJECTION glLoadIdentity glortho 1 1 1 1 1 100 enable generate and bind our texture objects glEnable GL TEXTURE
220. ects were designed to closely resemble texture objects provide a simple en able disable mechanism that is similar in usage to textures and yet offer a lot of flexibility in terms of what can be rendered and how to use it later Framebuffer objects are also similar to pbuffers in terms of their usage We have a more de tailed discussion of these objects in the Cocoa chapter Chapter 8 so for now we ll simply say a few quick things First framebuffer objects are the best thing since sliced bread and really your best consideration for new applications They re too easy too familiar to texture object users and too widely supported to not use them In fact framebuffer ob jects are an easy port from pbuffers if your application already supports those but they will clean up some code and remove some worrying restrictions So without further ado let s look at our original AGL windowed example but ex tend it to use framebuffer objects In Example 7 12 we see code covering the main steps involved in config uring and setting up a framebuffer object You ll notice that this example is virtually the same as the prior texture copy example from Example 7 11 The main differences occur after texture creation and initialization The pieces given here are the essential elements of how to create a framebuffer object You ll notice the parallels to texture creation specifically that we generate a unique framebuffer object ID bind it construct a
221. ed Context import Cocoa Cocoa h interface SharedContext NSObject NSOpenGLPixelFormat _pixelformat NSOpenGLContext _context NSOpenGLPixelFormat pixelFormat NSOpenGLContext context SharedContext instance end Example 8 6 Singleton Class Implementation for Managing a Shared Context import lt AppKit NSOpenGL h gt import lt OpenGL gl h gt import SharedContext h SharedContext _sharedContext nil 144 Chapter 8 The Cocoa API for OpenGL Configuration NSWindow Inspector attributes B Window Title Window Auto Save Name Title bar controls v Close M Minimize v Zoom and resize Window backing O Nonretained O Retained 9 Buffered F Release when closed 7 Hide on deactivate v Visible at launch time v Deferred v One shot _ Utility window panel only Non activating panel panel only 3 Has texture v Has shadow F Display tooltips when app is inactive C Unified title toolbar look Auto recalculate key view loop PA Figure 8 14 Context Sharing Set Visible on Launch for Second Window implementation SharedContext id init if self super init _pixelformat nil _context nil GLuint attributes NSOpenGLPFAWindow NSOpenGLPFAAccelerated NSOpenGLPFADoub1leBuf fer NSOpenGLPFAColorSize 24 NSOpenGLPFAAlphaSize 8 NSOpenGLPFADepthSize 24 hil wi
222. ed in this chapter you should have a solid foundation from which to begin building your own Carbon and AGL OpenGL applications 120 Chapter 7 The AGL API for OpenGL Configuration Chapter 8 The Cocoa API for OpenGL Configuration Cocoa also known as AppKit is the Objective C API for writing modern Mac OS X applications Cocoa provides a high level object oriented set of classes and interfaces for the OpenGL subsystem and for user interface interaction Cocoa is the modern successor to the NextStep API from NeXT Computer the company s initials explain the NS prefix on all of the class definitions and data types Cocoa provides a more object oriented API than any other option on the Mac which is useful for building Uls handling events and functioning as an interface to OpenGL We presume you re reading this chapter with a fundamental understanding of the Objective C language and basic Cocoa so we won t spend any time review ing core Cocoa concepts like the Objective C language views actions outlets Interface Builder and so on We also assume you ve already read one of the many good books on these key background elements of Cocoa If not we ve got a reference or two for you in Appendix D In the following sections we ll ex plore two ways of creating a Cocoa based application one that relies heavily on Interface Builder and one that requires more code but yields a bit more flexibil ity and capability We ll also tackle some
223. ed on the graphics card associated with the renderer Often this number will be some number less than video memory where the difference is accounted for in allocations for framebuffer memory For software renderers where host memory is used for texture memory 0 is reported as this attribute s value Sharing OpenGL Objects Across CGL Contexts Sharing data across contexts is done by specifying a share context at CGLCreateContext time CGLCreateContext is defined in CGL h CGLError CGLCreateContext CGLPixelFormatObj pix CGLContextObj shareCtx CGLContextObj newCtx 76 Chapter 6 The CGL API for OpenGL Configuration CGLCreateContext also has an external definition in OpenGL h of the OpenGL framework To successfully share data across contexts the contexts must share the same renderer Another way of expressing this requirement is to say that the contexts must have the same virtual screen list A virtual screen is defined as the pairing of one renderer and its associated set of physical displays Given that there is only one renderer per virtual screen having the same virtual screen list means having the same renderer To determine the virtual screen list from a context use CGLError CGLGetVirtualScreen CGLContextObj ctx long screen To determine the renderer ID from this virtual screen use CGLError CGLDescribePixelFormat CGLPixelFormatObj pix long pix_num CGLPixelFormatAttribute attrib long value If the renderer
224. election in three steps 1 A structure is created containing a list of pixel format configuration parameters 2 That structure is passed to an NSOpenGLPixelFormat constructor to create a new pixel format object 3 That pixel format object is passed on to the base NSOpenGLView method for finishing the initialization of this view Either add the code yourself to your project or grab it from the sample code provided in Example 8 1 Compile and run the code and you should have a window 126 Chapter 8 The Cocoa API for OpenGL Configuration Table 8 2 Selection Policies and Behaviors Policy Description Match Choose only from the set of pixel formats that match exactly Closest Choose a match closest to the size specified but not necessarily an exact match Minimum Require a match of at least this size Can choose larger sizes Maximum Require a match of at most this size Prefers larger sizes But wait you say what about the rest of the key OpenGL configu ration pieces the context and the drawable or surface By subclassing NSOpenGLView you re getting the last two pieces configured for you you lucky dog no extra work required The base NSOpenGLView class creates a context from the pixel format you passed in and it creates a drawable such that it can be visualized in the window we created with our CustomView back in Interface Builder Later however we ll go through the process of spec
225. ely the one in which you d like your subsequent OpenGL commands to be executed NSView 299 Put more succinctly you want your context to be active In context parlance this is known as making your context current lockFocus is the place in the Cocoa framework where your view is made current and where you can then make your context current If we now look at our code we can see that we need to overload this method to do the usual lockFocus work when we call our superclasses lockFocus We then do work to get our OpenGL context and make it current And that as they say is that We ve got a context it s current and we re ready to finish this exercise with two methods that we ve seen before The last two methods we implement are identical to those we ve used before The prepareOpenGL and drawRect methods contain the same code as in the prior example As before they perform two tasks in your context OpenGL initialization and rendering respectively With their completion you re ready to build and run the application You should see the same teapot against a blue background as in Figure C 6 Additional Topics So far we ve explored ways to render directly to the screen using Cocoa Now we ll dig into how to render somewhere off screen There are many reasons why you might want to do this for example to create a cube map for reflection to create shadow maps or to create another form of dynamic texture For off screen rend
226. ements Type Unsigned integer Number of color buffer bits required by all color components together Default If this token is not specified a ColorSize that matches the screen is implied Policy Closest NSOpenGLPFAAlphaSize Unsigned integer The value specified is the number of alpha buffer bits required Default If no value is specified pixel formats discovered may or may not have an alpha buffer Selection policy Pixel formats that most closely match this size are preferred Continued NSOpenGLView 129 Table 8 3 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat Continued Token Description NSOpenGLPFADepthSize Unsigned integer The value specified is the number of depth buffer bits required Default If no value is specified pixel formats discovered may or may not have a depth buffer Selection policy Pixel formats that most closely match this size are preferred NSOpenGLPFAStencilSize Unsigned integer The value specified is the number of stencil planes required Selection policy The smallest stencil buffer of at least the specified size is preferred NSOpenGLPFAAccumSize Unsigned integer The value specified is the number of accumulation buffer bits required Selection policy An accumulation buffer that most closely matches the specified siz
227. emonstrating Common Shared Data and Unshared Clear Color Context Data 148 Chapter 8 The Cocoa API for OpenGL Configuration Remember that the OS X OpenGL implementation follows the conventions es tablished in the GLX specification Applications are responsible for synchroniz ing the state of objects between contexts This implies that multithreaded ap plications with shared context establish mutex locks between the threads use g1F lush to flush pending commands that modify object state and call g1Bind to realize changes to shared objects in other contexts These may seem like a lot of steps but they are usually worth the resulting resource conservation and per formance gains In this section we ve seen how to configure context sharing in Cocoa how to use it with a custom OpenGL view and under which circumstances you d want to share contexts We ve provided examples of how this sharing mechanism works in Cocoa and we ll revisit this topic for AGL and CGL later Context sharing is a key principle we ll use for a variety of on or off screen rendering techniques so you ll likely revisit this section from time to time for hints when performing full screen and off screen rendering Full Screen Surfaces Every now and again you might want to put your Cocoa OpenGL application into full screen mode There are lots of reasons why you might want to do this and Apple often uses this approach for many of its applications Apple software
228. enGL context of your application and that of the new renderer Filesystem There are a few surprises in store for Unix users who move to the Mac OS for the first time From a user or an application developer perspective the biggest difference is case insensitivity in the most common filesystem HFS and HFS The problem to be aware of here is that HFS is case preserving but not case sensi tive Thus to the filesystem you can create and save a file named Foo but later access that file by opening foo That makes for some tricky errors if you re not aware of that distinction The Mac also supports a number of other filesystems natively including a few that are both case sensitive and case preserving Again when accessing files on the Mac it s imperative to ensure that the file you asked for is really the file you received From an administrative perspective the tools used to manage and configure the filesystem on the Mac OS are likely to be considerably different from the tools available on other Unix workstations you may have used simply due to the diversity of filesystems available 38 Chapter 4 Application Programming on OS X Finding Verifying and Filing Bugs Occasionally while writing or porting your OpenGL application to OS X you may suspect you ve found a bug in the OpenGL implementation or other parts of the Mac OS One great thing about the Apple OpenGL team is that they want to help you succeed with your applicatio
229. ence of color index rendering Two X11 color models use color index or color mapped rendering PseudoColor and DirectColor PseudoColor is the more common of these two and represents each pixel in the framebuffer as an index into a single colormap DirectColor by contrast has a separate color map for red green and blue As you would expect each pixel in the framebuffer contains an index for each of the three color maps If you wish to run an application that uses the PseudoColor model you can launch X11 in 256 color mode To do so select the output tab from the X11 app preferences pane and select 256 colors from the Colors drop down menu You must restart X11 app for this change to take effect The TrueColor color model stores a maximum of four color component intensity values in the framebuffer one each for red green blue and alpha Modern graphics applications typically use this color model By default X11 app is configured to take the color setting from the display The display setting is typically millions for 24 bit color This setting is appropriate for TrueColor X11 applications X11 Color Models 279 This page intentionally left blank Appendix B Glossary API Acronym for application programming interface An API is a set of func tions classes and tokens used to define a particular set of software tools OpenGL is an API for graphics ARB See OpenGL Architecture Review Board Context sharing Reusin
230. ent Using Mac OpenGL There are some commonalities between efficient handling of all kinds of data for the Mac OpenGL implementation whether the data is for vertices pixels or tex els As mentioned earlier the OpenGL specification allows for a lot of flexibility for data and state management At any time an OpenGL application can query the OpenGL server for a current state or data From an application writer s per spective having this data and state on tap is convenient and relaxes the strict need for the application to maintain its current graphics state From an OpenGL implementer s perspective however this design imposes a great deal of over head because that data will likely need to be copied to make it readily available to applications Another consideration along these lines is that for OpenGL entry points that submit data to the drivers the specification naturally requires that the imple mentation is finished accessing the data by the time the function returns con trol to the application Take g1 TexImage2D for instance by the time control is returned to the application OpenGL must have completed reading the tex els provided through this interface from the application address space So if it needs to comply with the specification where does it put the texels Does it make a copy in host memory Does it go to the kernel and ask for AGP space Does it just directly put the data into VRAM Efficient Data Man
231. ent is paramount 176 Chapter 10 API Interoperability The final technique resizing the data to be a power of two is the most space efficient in terms of the hardware but at the cost of some image quality loss However this technique is the one most easily implemented so we ll explain it here Resizing an NSImage to a Power of Two Our goal in this section is to take an arbitrarily sized NSImage and resize it to a power of two sized NSImage We ll do so by exploiting the functionality of an NSImage specifically its ability to paint itself in different ways The code to do this is fairly simple so we ll look at it in Example 10 3 and explain it after its presentation Example 10 3 Resizing an NSImage to a Power of Two NSImage transformImage NSImage image toSize NSSize size t get a new image the same size as this one isFlipped override to return YES to get coord sys in upper left NSImage newlmage NSImage alloc initWithSize size newImage setFlipped YES Draw on the new Image newImage lockFocus create a draw context image drawInRect NSMakeRect 0 0 size width size height fromRect NSMakeRect 0 0 image size width image size height operation NSCompositeSourceOver fraction 1 0 newImage unlockFocus release the draw context return it return newlmage This code takes an input NSImage and a target NSSize and creates
232. ents a schematic of a typical system s architecture The reason we point this out even at this very abstract level is to help you understand where your graphics data lives and flows in a modern Mac Understanding how the CPU in your Mac communicates with and transfers data to and from the GPU will help you optimize your graphics applications on Mac OS Data Flow and Limitations It s important to understand hardware architecture when evaluating how a graphics application runs on a specific system We will cover performance tuning case studies and methods in Chapter 11 but felt it worthwhile to 24 Chapter 3 Mac Hardware Architecture discuss some macro level concepts of graphics software performance consid erations here in the hardware architecture chapter Our intention is to identify some of the general classes of performance problems that graphics applications face and to suggest how well or badly the available hardware solves these problems Specifically it s necessary to understand the fundamental limits of the various processing units buffers and busses through which the applica tion s data will pass There are two primary types of data in OpenGL pixels and vertices Each type of data has a different logical flow through the system and can therefore be sub jected to different hardware and software limitations We ll begin where your data originates and walk through the process of getting that data to the GPU for rende
233. er 11 Performance state such that it can be simply recalled when needed to draw various objects in a scene as in Example 11 8 Example 11 8 Using Vertex Array Objects Create and bind your VAO glGenVertexArraysAPPLE 1 amp tortoiseVAO ID glBindVertexArrayAPPLE tortoiseVAO ID Set up tortoise pointers glVertexPointer glNormalPointer glTexCoordPointer Do the same init sequence for the hare model Other stuff Now when you want to draw the tortoise glBindVertexArrayAPPLE tortoiseVAO ID glDrawArrays GL TRIANGLE STRIP 0 n VAOS will likely evolve into the OpenGL core specification in some form or another and are a good complement to using VBAs Vertex Array Range Prior to VBOs Apple introduced the Vertex Array Range VAR extension VAR has two key aspects that benefit the performance of vertex submission First this aggregating extension improves the efficiency of mapping regions of mem ory dedicated to holding your vertex data Second VAR allows you to make piecewise modifications to vertex arrays and to subsequently flush those spe cific changes up to the GPU Suppose you have a vertex array with 10MB of data that contains the vertex information for 10 different models in a scene If a user of your application modifies one of the 10 models ideally your application should modify the corresponding vertices of that single model and then send the changes for that model over to the GPU
234. er a call to CGLFlushDrawable is made kCGLRPMPSafe Historical Boolean indicating whether the renderer is thread safe This renderer property is no longer used as all renderers are now thread safe kCGLRPWindow Boolean used only by the AGL or Cocoa API that describes whether the renderer is capable of rendering to a window As CGL does not render to windows this renderer property should be irrelevant to your application kCGLRPMultiScreen Boolean indicating whether the renderer is currently driving multiple displays kCGLRPCompliant Boolean indicating whether the renderer is OpenGL compliant Context Management 73 kCGLRPDisplayMask The display mask describing the physical displays to which the renderer is capa ble of rendering Display masks are managed by the Direct Display API which is part of the Core Graphics API See Steps 1 and 2 in Renderer Information earlier in this chapter pages 70 71 for information on display masks kCGLRPBuf ferModes The bitwise OR of buffer mode bits for the renderer The list of buffer mode bits includes kCGLSingleBufferBit kCGLDoubleBuf ferBit kCGLMonoscopicBit kCGLStereoscopicBit kCGLRPColorModes and kCGLRPAccumModes Both kCGLRPColorModes and kCGLRPAccumModes are bitwise ORs of for mats supported by the renderer They share the same list of constants kKCGLRGB444Bit 0x00000040 16 rgb bit pixel R 11 8 G 7 4 B 3 0 y kCGLARGB
235. er hit his or her head on something a painful simula tion to be sure Perhaps your character was jogging and ran into a signpost We want to render the scene slightly blurred and wavy regardless of the method of cranial impact In this case our intermediate scene would be the original street scene rendering We would then take that image and run it through our BluntTrauma frag shader Our example code will render scenes of similar complexity or at least a teapot to demonstrate this process but the idea remains the same The basic path for performing this render is as follows 1 Render to an alternative destination 2 Configure those results for use in the final scene render 3 Render the final scene The following sections describe the various techniques available on the Mac for alternative destination rendering and subsequent reuse of those data We ll pri oritize these strategies in terms of their modernity encouraging you to use the most modern of these framebuffer objects whenever possible For a variety of reasons not least of which are simplicity and performance framebuffer objects are the best choice when your hardware supports them However as always with more advanced OpenGL features the most modern features are not al ways supported on the hardware your customers have so choosing fallbacks for those cases may require you to implement some of the other techniques We cover the basics of each below Dive in Fr
236. er s virtual screen has the majority of the application s OpenGL windows real estate is called upon to perform the rendering in full In other words if your application has an OpenGL rendering area and that window strad dles two virtual screens the virtual screen renderer that would be responsible for rendering more than 50 percent of those pixels renders all the pixels The remaining pixels that are on the minority virtual screen are filled in by a copy operation from the renderer associated with the majority virtual screen There are obvious performance consequences when such copying takes place The good news is that there is no performance penalty for having and using multiple 20 Chapter 2 OpenGL Architecture on OS X virtual screens as long as your application s OpenGL rendering area resides entirely within one of them Choosing a renderer is the first logical step in creating an OpenGL application for Mac OS Several APIs are available to set up renderers on Mac OS including GLUT CGL and AGL and you can also use the OpenGL capable Cocoa View classes defined in AppKit These methods of setting up a renderer for your ap plication are described in detail in Chapters 6 7 and 8 respectively Drivers The lowest layer in the rendering software hierarchy is the driver layer This layer contains all of the device specific logic for the installed graphics hard ware of the system The driver layer buffers rendering commands and render
237. erObjectARB GL FRAGMENT SHADER ARB myglShaderSourceARB vShader 1 amp vertsource c NULL myglShaderSourceARB fShader 1 amp fragsource c NULL myglCompileShaderARB vShader myglCompileShaderARB fShader programObject myglCreateProgramObjectARB myglAttachObjectARB programObject vShader myglAttachObjectARB programObject fShader myglLinkProgramARB programObject myglUseProgramObjectARB programObject else error No shading available endif add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate 268 Chapter 13 OpenGL Extensions userinfo nil repeats YES We ve now seen how to determine which extensions to use when they re ap propriate when you should use the baseline OpenGL versus extensions which checks to perform for compile link and run time correctness and how to dy namically bind symbols In essence we ve taken the complete tour of OpenGL extension selection and usage and shown how a lot of plumbing fits together We ll now look at a simpler way to do things that is letting someone else do all the work for us in a cross platform extension toolkit Extension Management Libraries In prior sections we looked at native ways of dealing with extensions on the Mac from the compile time to runtime means of checking and using them Dur ing this explorati
238. ering we ll be building on the foundation from the Cocoa examples in previous sections so if you ve skipped to this point without reading those sections you may want to review them to gather additional details Manipulating Images and Pixels in OpenGL Before we get into specific techniques let s talk about the various ways that an image of some sort can be moved around rendered and copied in OpenGL OpenGL provides two main paths for pixel data e Pixel path e Texture path These two paths are very different in the way they re ultimately available to be rendered The pixel path consists of two basic calls g1DrawPixels and glReadPixels which allow for drawing and reading respectively of pixels from the current write and read buffers These pixel path calls are 2D only and can read and write only screen aligned data By comparison the texture path differs from the pixel path specifically in that texture data can be rendered in 3D Because the texture path can also be used to render screen aligned images as well it is ultimately the more flexible of the two paths so we ll focus on the 300 Appendix C The Cocoa API for OpenGL Configuration in Leopard texture path here The Red Book 22 has lots of details on the imaging pipeline if you d like more information on that Any pixel data that you might want to render in an OpenGL scene you can handle through textures To do so you would download that image as a texture using glTex
239. ering with objects passed from the host to the GPU on a per frame basis Compared to retained mode rendering imme diate mode rendering implies more function calling overhead in each render ing frame in addition to more bus bandwidth used with each frame OpenGL Architecture Review Board The standards body that defines which features functionality and APIs appear in core OpenGL versions extensions and associated specifications OpenGL Shading Language The high level shading language employed by OpenGL Red Book The familiar name for the OpenGL programming guide Retained mode rendering Rendering with objects already cached on the GPU Typically g1Bind Object calls invoke retained mode rendering Display lists are another form of this style of rendering Throughput The data transfer rate that an application achieves for a particu lar form of data over some data path In graphics throughput typically refers to the rate at which data can be transferred from main memory to the graph ics processor vbl sync Vertical blanking synchronized is a configuration option of graphics applications that ties the redrawing of the framebuffer to the refresh rate of the display device Virtualized desktop A single continuous desktop that may span multiple potentially heterogeneous graphics devices Dragging windows among the displays attached to these graphics devices is seamless and continuous 282 Appendix B Glossary Appendix C The Coc
240. ers using framebuffer objects FBOs Rendering to FBOs is a technique born out of frustrations with the complexity of many of the other intermediate rendering techniques FBOs were designed to provide a simple enable disable mechanism that is familiar in usage to textures and yet provide a great deal of flexibility in terms of what can be rendered and how to use it later FBOs are an evolution from earlier extensions namely GLARBrender texture However they are a vast improvement over the older techniques as you ll hear shortly FBOs are really the only choice for new applications as they offer high performance are flexible and are easy to use That s our perspective on the matter but for reference you should defer to the extension specification as the authority The specification declares Previous extensions that enabled rendering to a texture have been much more complicated One example is the combination of GLARBpbuffer and GLAR Brendertexture both of which are window system extensions This com bination requires calling g1xMakeCurrent an expensive operation used to switch between the window and the pbuffer drawables An application must create one pbuffer per renderable texture in order to portably use GLARBren dertexture An application must maintain at least one GL context per tex ture format because each context can operate on only a single pixel format or FBConfig All of these characteristics make GLARBrendertexture both
241. ertices The method looks something like this void Leaves draw int i float v 9 1 0 1 5f 2 18 2 4 2008 Xi glColor3 0 0f 0 5f 0 0f Axioms for Designing High Performance OpenGL Applications 197 glBegin GL POLYGONS for i 0 i lt 10 i glVertex2fv v i 2 glEnd Now consider the OpenGL efficiency of instantiating this leaf class 1000 times for a small oak tree in your scene First it calls g1Co1or3f 1000 times when it needed to be called only once Second this code submits 10 vertices at a time when it could have submitted 10 000 As contrived as this example may seem it is far and away the most common OpenGL performance programming problem a large OOP class hierarchy that was designed with objects that fit the model of the domain The ignorance these class instances have of one another has drastic state management consequences for OpenGL applications The moral of the story is that you should design your application object hierarchy with an efficient scene graph that batches like state elements and can be traversed at draw time along with all that is required to represent the objects in your problem domain Retained Mode versus Immediate Mode Rendering Immediate mode rendering is the oldest and correspondingly most outdated way to render graphics in OpenGL We don t mean to completely bash im mediate mode rendering because it is definitely the easiest approach to get
242. es back we don t have the extension Conversely if all our extension queries succeed then we re off and running Example 13 3 calls the hasShaderExtensions method and upon its success calls the various methods required to configure the shaders If your environment is configured with the baseline OpenGL and shading extensions you ll see a result like that in Figure 13 1 if not you ll see our fallback ren dering the baseline material color as in Figure 13 2 Example 13 3 Querying for OpenGL Shader Extensions BOOL hasShaderExtensions BOOL has_shading FALSE 3 Because of some peculiarities in the Apple s implementation of this shading language only the first three are really necessary to use shading The last extension GL_ARB_shading_language_100 defines whether the language is fully supported and different graphics vendors interpret this dif ferently Apple interprets it to mean that while the shading stuff works its implementation at the time of this writing is not completely compatible with the language flavor defined in that extension Other vendors expose this token despite the completeness or capability of their implementations Details details A truly portable application would ensure that all four tokens were available and run only if that is the case Utilization and Binding 263 000 Window Figure 13 2 Shader Extension Application Results if Unsuccessful float versionfloat self openG
243. essage your application can cancel the power state change with a call to IOCancelPowerChange In other words if the user asks the system to sleep from the Apple menu calling IOCancelPowerChange will have no effect In fact for an active sleep request on the part of the user your application will not receive a kIOMessageCanSystemSleep message as an event You can however delay the power event in any sleep scenario If you choose not to respond to a power event with either IOAllowPowerChange or IOCancelPowerChange the system will wait 30 seconds before effecting the power state change By adding a default condition on the power event switch you will avoid this 30 second delay on messages that you had not explicitly written logic to handle The second and final step specific to handling power events is to request notifications of them from the CoreFoundation run loop When a sleeping Mac wakes up your power event handler will first receive a kIOMessageSystemWillPowerOn message and shortly after will receive a klOMessageSystemHasPoweredOn message For graphics applications it is a good idea to consider calling CGLUpdate Context when your application receives power on events If for instance a display was removed from the system while it was sleeping the system will do an implicit renderer change if your application was occupying the display that was removed In this case you want to force a synchroniza tion between the Op
244. et s use OpenGL Profiler to figure out where our application is spending its time Please note that in all example uses of Profiler your results will vary from our test system to some degree The results should be similar to Figure 11 13 Notice the monsterous 89 percent of our time being spent in g1Begin You ll often see a disproportionate amount of time devoted to g1Begin because of deferred validation Notice too the 6 percent chunk at g1TexImage2D This 6 percent is the time required to copy the texture data from application memory to OpenGL memory Recall that OpenGL must keep copies of your data to be in compliance with the specification unless some extension relaxes that requirement which many Apple extensions do The 89 percent time spent at g1Begin is primarily due to programming mistake numero uno in ptm1 c use of a texture type that is not native to 238 Chapter 11 Performance 3 texture binding for mesh Figure 11 12 Performance Tuning Exercise Application Please Tune Me the graphics hardware In ptm1 c s case this texture type is GL_UNSIGNE D SHORT 4 4 4 4 Often OpenGL programmers will use packed types such as this because they don t require the fidelity of 8 bits per component and wish to save space However because this type is not native to the hard ware a very costly transformation needs to take place to translate this data into a hardware native form This costl
245. ethods for extracting data from and importing data into NSImages We ll begin with an overview of how NSImage functions and demonstrate a few common ways of using it in an application Basic NSImage NSImage is an abstract representation of an image but it also contains and can create concrete instantiations of images A concrete instantiation of an NSImage is known as an NSImageRep and any given NSImage may contain several instantiations For the purpose of interoperating with OpenGL the most common flavor of NSImageRep we ll use will be the NSBitmapImageRep An NSBitmapImageRep contains the actual image pixels we ll need to use in OpenGL at lower levels Let s back up a step for now and look at a few useful ways to create NSImages NSImage contains a variety of helper methods to create images from common sources A few choices to get us started are found in Example 10 1 Example 10 1 Two Sample NSImage Initialization Methods id initWithContentsOfFile NSString filename id initWithContentsOfURL NSURL aURL Let s look at these methods in a more complete example using our old standby cocoa simple example as a foundation Our goal will be to extend the ex ample code so that we texture a quad using the contents of an NSImage The process we ll follow will begin by instantiating objects of each of these types in our prepareOpenGL method As before prepareOpenGL is where we s
246. ewImage Finally we deactivate newImage as a render target and return that image Now that we ve computed a flipped image we need to get the pixel data from NSImage and download it to the hardware Extracting Pixel Data from an NSImage OpenGL requires access to a raw array of pixels to download those data as ei ther texture or images to the hardware For that reason we must extract our data from an NSImage and then use the resultant transformed version to pass data down to the hardware In Cocoa a form of image data that allows direct access to pixel data is NSBitmapImageRep and its subclasses Specifically an NSBitmapImageRep has a variety of methods for determining the size and extent of its contents as seen in Table 10 1 An NSBitmapImageRep can contain a lot more information especially if its originating data source is something like an animated GIF We will assume the use of a simple image in our examples here but you can search the Apple refer ence pages for lots of details on all the stuff you can do in NSBitmapImageRep Given our simple image and the accessors in Table 10 1 for a bitmap image how do we go about getting an NSBitmapImageRep Transforming our NSImage into a bitmap is suprisingly simple as we see in Example 10 4 178 Chapter 10 API Interoperability Table 10 1 NSBitmapImageRep Accessors for OpenGL Texture Data Accessor Description int bitsPerPixel Number of bits
247. ex array RB extensions introduced to promotion process GRA pixel format EXT bgra ange bounded vertex draw elements EXT draw range elements gt a 1 2 1 1 3 ies Quo Multisampling GL_ARB_multisample Multitexturing GL ARB multitexture Texture environment modes Add Combine Dot3 GL ARB texture env add combine dot3 Texture border clamp GL ARB texture border clamp Transpose matrix GL ARB transpose matrix 14 Automatic mipmap generation GL_SGIS_generate_mipmap Blend squaring LNV_blend_square GI Depth textures GL ARB depth texture Fog coordinates GL EXT fog coord Multiple draw arrays GL EXT multi draw arrays Point parameters GL ARB point parameters Secondary color GL_EXT_secondary_color Separate blend functions GL_EXT_blend_func_separate Shadows GL_ARB_shadow Stencil wrap GL_EXT_stencil_wrap 10 Chapter 2 OpenGL Architecture on OS X OpenGL Version Extension Texture crossbar environment mode GL_ARB_texture_env_crossbar Texture LOD bias GL_EXT_texture_lod_bias Texture mirrored repeat GL_ARB_texture_mirrored_repeat Window raster position GL_ARB_window_pos 15 Buffer objects GL_ARB_vertex_buffer_object Occlusion queries L_ARB_occlusion_query Q 02 hadow functions LEXT shadow funcs 2 0 rogrammable shading L
248. exProcessing 310 1 param Currently processing vertices with GPU get kCGLCPGPUFragmentProcessing 311 1 param Currently processing fragments with GPU get CGLContextParameter Context parameters are set with CGLError CGLSetParameter CGLContextObj ctx CGLContext Parameter parameterName const long params and retrieved by CGLError CGLGetParameter CGLContextObj ctx CGLContext Parameter parameterName long params Notice that for each of the valid parameter values is prefaced by the string kCGL followed by CP CP stands for context parameter but this note will help you distinguish this CGL constant from others Each value passed to CGLSetParameter is either a parameter with a value specific to the parameter or a Boolean enabled parameter that is controlled by calls to CGLError CGLEnable CGLContextObj ctx CGLContextEnable enableName CGLError CGLDisable CGLContextObj ctx CGLContextEnable enableName A list of CGL context enables also from CGLTypes h follows Enable names for CGLEnable CGLDisable and CGLIsEnabled f typedef enum CGLContextEnable kCGLCESwapRectangle 201 Enable or disable the swap rectangle kCGLCESwapLimit 203 Enable or disable the swap async limit kCGLCERasterization 221 Enable or disable all rasterization E kCGLCEStateValidation 301 Validate state for multi screen functionality kCGLCESurfaceBackin
249. f once at initialization time using the code in Example 11 2 Example 11 2 Enabling or Disabling the Multithreaded GL Engine Turn on the MT GL Engine CGLEnable CGLGetCurrentContext kCGLCEMPEngine Turn off the MT GL Engine CGLDisable CGLGetCurrentContext kCGLCEMPEngine In short use all the CPU hardware at your disposal your users will thank you for it Besides it s fun to watch those CPU cores you paid for busily working away Minimizing Function Call Overhead When OpenGL calls are made a small cost is associated with detecting the current context from the current thread Multiply this small cost by enough OpenGL calls and it becomes a big cost You can avoid this overhead by using the macros provided in CGLMacro h and maintaining your own current context These macros bypass the top level framework layer entry points and go directly into the OpenGL engine For stand alone tests that simply pound on the OpenGL API we ve observed 20 percent performance gains using CGL macros You ll find more information about using CGL macros in Chapter 6 Minimize CPU and GPU Idle Time by Using Asynchronous Calls Asynchronous CPU and GPU operation is definitely the crown jewel when it comes to getting the most performance out of the Mac OS X OpenGL implemen tation Asynchronous features of the implementation minimize extremely costly stalls between the CPU and the GPU Nearly every application that keeps an eye on the frame r
250. f course details to deal with concerning how you target the texture into which you want to render and in some cases how you move pixels around the sys tem into your final texture Nevertheless the process is largely as simple as described Render to texture is interesting because it s a widely available tech nique and offers relatively high performance There are problems with it too It s not as clean as the most modern OpenGL technique of FBOs and there may be extra data copies Overall however it works pretty well Performance is pretty good though not as consistently good as using FBOs Even so you may sometimes run into problems when using cards from different vendors on which this technique is actually moderately expensive But if you can t use FBOs and this is the best alternative available you gotta do what you gotta do The essence of the render to texture technique is actually a bit simpler than the FBO example presented earlier The code is virtually the same but we omit the pieces of the rendering that relate to the FBO We begin by looking at the header for our custom view Example 8 14 Example 8 14 Custom View Header for Copy to Texture Example Code import lt AppKit NSOpenGL h gt import lt Cocoa Cocoa h gt interface MyOpenGLView NSOpenGLView GLuint textureID float time float angle void angleUpdate NSTimer tt void reshape end Because we re only going to render and co
251. f rendering to a window Note This attribute is implied only if neither NSOpenGLPFAFullScreen nor NSOpenGLPFAOffScreen is specified NSOpenGLPFAPixelBuffer YES Rendering to a pixel buffer is enabled NSOpenGLView 131 eoo Window Figure 8 8 Teapot Rendered with NSOpenGLView Subclass The first of these methods which is named prepareOpenGL is defined to be the first opportunity that your class will have to make some OpenGL calls prepareOpenGL will be called once a valid pixel format context and draw able are all available so you can go ahead and call anything you d like there Keep in mind that this method will be called only once so from that point on you ll have to manage your OpenGL state changes on the fly The second method to implement is drawRect This method will be called ev ery time a scene redraw is necessary you will do the bulk of your OpenGL work there As part of the drawRect signature you will be handed an NSRect containing the current origin and size of the drawing area in pixels With that introduction out of the way we ll simply point you at the code Example C 2 to add to your MyOpenGLView m file somewhere between the implementation and end tokens Once you ve added this code recompile and run the code again and you should see something like Figure 8 8 Example 8 2 Cocoa drawRect Rendering Method with Sample OpenGL Content void drawRect NSRect rect adj
252. f the material and the many comparisons and contrasts drawn with other programming environments and operating systems Given the long history of OpenGL on the Mac which we discuss later in the book you may be reading this book with an older application as your focus With this in mind we ve included content covering all OpenGL related APIs in OS X The older APIs however may not be the preferred path for new develop ment on the Mac and we ll guide you accordingly We cover all major OpenGL window system APIs on the Mac in depth but with enough guidance that even first time Mac developers can get up to speed quickly Whatever type of developer you are whatever the age of your code and no matter how you arrived at this title we welcome you and hope you find our book useful Why the Mac For those of you who are new to the Mac platform we d like to spend a moment explaining a few of the reasons why the Mac makes a great platform on which to develop your applications Specifically we d like to explore some of the reasons that you would target Mac OS X for a new OpenGL application The Mac has had a long and rich history In fact Apple recently celebrated its thirtieth anniversary The Mac has existed for more than 20 years of that 30 year span and has itself undergone many transformations over that time Through out it all the Mac platform has exhibited a few key characteristics Chief among those is one characteristic in parti
253. f these stages of the extension process allows for indus try soak time to expose the extension s strengths and weaknesses At every stage of the process vendor EXT and ARB the review board can and often does make changes to remedy any weaknesses that were uncovered through industry exposure As extensions are integrated into the core and other clarifying edits are made to the OpenGL specification the document is revised and its version number updated Version 1 0 of this specification was released in 1992 and Figure 2 1 details the timeline of versions since that time Each new revision of the core OpenGL API promoted extensions to core func tionality as shown in Table 2 1 Table 2 1 Versions of OpenGL in Which Extensions Were Promoted to Core OpenGL OpenGL Version Extension 1 1 Blending logical operations GL EXT blend logic op Framebuffer to texture copies EXT copytexture olygon offset EXT polygon offset MIQ Wa ubtexturing EXT subtexture Q Internal formats and component sizing for textures GL_EXT_texture Texture proxying EXT texture G Replacement of output fragments by source texture values GL EXT texture Continued About OpenGL 9 Table 2 1 Versions of OpenGL in Which Extensions Were Promoted to Core OpenGL Continued OpenGL Version Extension Texture objects GL_EXT_texture_object Vertex arrays EXT vert
254. fferent pixelformat NSView 137 2 proceed without a shared context o return context void lockFocus NSLog myView lockFocus ensure we are ready to draw super lockFocus get our context NSOpenGLContext cxt self openGLContext ensure we are pointing to ourself as the Drawable if cxt view self cxt setView self make us the current OpenGL context cxt makeCurrentContext void prepareOpenGL NSLog myView prepareOpenGL glMatrixMode GL PROJECTION glLoadIdentity glOrtho 1 1 1 1 1 100 void drawRect NSRect rect adjust viewing parameters glViewport 0 0 GLsizei rect size width GLsizei rect size height glClearColor 0 5 8 0 glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT glMatrixMode GL MODELVIEW glLoadIdentity glTranslatef 0 0 1 GLfloat green 4 0 1 0 0 glMaterialfv GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE green glutSolidTeapot 5 188 Chapter 8 The Cocoa API for OpenGL Configuration self openGLContext flushBuffer end In our MyView m file we start by looking at our initWithFrame overloaded method This method is called when our object is getting constructed with the desired layout of this particular view As with our MyNSOpenGLVi ew class this method is where we set up our pixel format and prepare the rest of our class for subsequent
255. ffering the token kKCGLPFAStereo is used This option produces a pixel format that contains two double buffered drawables logically a left and a right with a stereo offset to produce a 3D projected rendering If you haven t experienced the LCD shutter glass type of stereo rendering it is as if the scene is floating in space in front of the physical surface of the display The stereo effect is achieved by providing two buffers left and right each with a separate perspective frustum Each frus tum is offset by the inter ocular distance or in English the distance between your eyes The NVidia Quadro FX 4500 which was introduced in 2005 was the first hardware introduced on the Mac platform to support stereo in a window The alternative to stereo in a window is full screen stereo For any Mac configured with hardware released prior to the FX 4500 kCGLPFAStereo implies kCGLPFAFullScreen which in turn implies KCGLPFASingleRenderer Selecting a Renderer Another way of selecting a renderer is by explicitly choosing one for your application There are a number of possibilities when it comes to selecting a renderer by ID enumerated in the file CGLRenderers h You use the kCGLPFARendererID attribute to select your own renderer ID Here is a snapshot of the evolving list of possible renderer IDs RendererGenericID RendererGenericFloatID kCGLRendererAppleSWID kCGLRendererATIRagel128ID kCGL kCGLRendererATIRadeonID kCG kCGLRendererAT
256. flexibility and generality and raw performance of what can be accomplished via FBO are unmatched by these alternative techniques If you ve got older code that uses one of these approaches a move to FBOs will likely both simplify and accelerate your code Take the leap Summary In this chapter we explored how to create and configure Cocoa based OpenGL rendering areas for on screen windows and for various intermediate render tar gets We saw how to create custom pixel formats examined some of the flags that these pixel formats take and demonstrated how to configure and initialize pixel formats We also saw how to customize NSViews and NSOpenGLViews to use custom pixel formats and create contexts We considered how to share data among multiple contexts and we learned how to configure full screen sur faces Now that you know the fundamentals of OpenGL and Cocoa setup you have a solid foundation from which to begin building your own Cocoa OpenGL applications 162 Chapter 8 The Cocoa API for OpenGL Configuration Chapter 9 The GLUT API for OpenGL Configuration GLUT is an older tried and true cross platform API for quick and dirty ac cess to OpenGL application infrastructure GLUT provides a very simple and straightforward CAPI to create windows manage device input monitor win dowing events handle a run loop and so on It also provides low level prim itive construction elements such as Spheres Cubes and Torii This API is n
257. for almost a full frame for the swap to return This effect is known as frame rate quantization 208 Chapter 11 Performance Throughput Throughput is another metric of performance that is related to frame rate but is not dependent upon it Throughput measures the data transfer rate that your application achieves for a particular form of data It is limited by the bandwidth of the bus through which the data transfers Some baseline transfer rates for the main memory to graphics card path were described earlier in Chapter 2 The best way to evaluate your application performance is to use the existing Apple written OpenGL throughput applications as benchmarks These appli cations which were written by Apple OpenGL engineers will achieve max imum throughput provide a number of switches and knobs that allow you to experiment with different formats and offer a benchmark with which you can compare your application The list of these applications available from Apple s developer website 4 is always evolving but two are particularly rel evant The Texture Range sample application 7 is useful for examining and comparing as is the Vertex Performance Test application 8 These two appli cations not only provide realistic estimates of performance rates but also are available as source code They provide examples of optimal coding techniques and show you how to choose different techniques for rendering the same data Efficient Data Managem
258. for accumulation buffers AGL DEPTH MODES Supports bitwise OR of depth mode constants from AGL agl h AGL_STENCIL_MODES Supports bitwise OR of stencil mode constants from AGL agl h AGL MAX AUX BUFFERS Maximum number of aux buffers supported AGL_VIDEO_MEMORY Maximum video memory available to renderer in bytes AGL_TEXTURE_MEMORY Maximum texture memory available to renderer in bytes prefer to run on the most capable graphics card or one with which you know your code performs particularly well Context Sharing Context sharing is an essential element to high performance resource friendly OpenGL applications Context sharing allows sharable elements from one context to be used in other OpenGL contexts There is one primary reason to share contexts reuse of the same graphics data in two or more different win dows One very common example of this is sharing data between a full screen version and a windowed version of the same application There may be other reasons such as when a number of windows are all viewing the same OpenGL data but from different views Finally you might want to share data among multiple rendering destinations such as windows and pbuffers Additional Topics 107 Context sharing is typically requested when a new OpenGL context is created and the context with which it will be sharing has been created and its sharable resources have been initialized The context with items you wish to access is passed to
259. framebuffer object linking it with our texture and then unbind it so we re returned to a default state The draw method should look similar too except that in this case we first say where we re targeting our draw commands much like making an OpenGL context ac tive using g1GenFramebuf fersEXT We draw into that target and then again reset our state back to the default Finally our main draw method looks identi cal to that of Example 7 11 This is because we ve drawn our contents directly into the framebuffer Using the texture linked with that framebuffer now gets us the proper results as seen in Figure 7 6 Example 7 12 AGL Initialization and Draw for a Framebuffer Object and Main Buffer void initGLstate glMatrixMode GL PROJECTION glLoadIdentity Alternative Rendering Destinations 117 glOrtho 0 0 1 0 0 0 1 0 1 0 1 0 glClearColor 0 0 0 5 0 8 1 0 enable generate and bind our texture objects glEnable GL TEXTURE 2D glGenTextures GLsizei 1 amp textureID glBindTexture GL TEXTURE 2D textureID const unsigned int texdim 64 const unsigned int nbytes 3 char data texdim texdim nbytes memset data Oxff texdim texdim nbytes unsigned int ii for ii 0 ii texdim texdim ii data ii nbytes 0 Oxff gluBuild2DMipmaps GL_TEXTURE_2D 0 GL_RGB texdim texdim 0 GL_RGB GL_UNSIGNED_BYTE data glTexEnvf GL TEXTURE ENV GL TEXTURE ENV MODE
260. full screen application managed by Carbon you d need to create a Carbon event handler to capture mouse and keyboard events We ll provide demo code on this book s website www macopenglbook com to show how this works and a preview in the next section here showing a windowed visual selection and event handling loop 94 Chapter 7 The AGL API for OpenGL Configuration Table 7 2 Pixel Format Specifiers for Use with aglChoosePixel Format Token Description AGL_ALL_RENDERERS Choose from all available renderers This can include non OpenGL compliant renderers Usually better to specify Type Boolean n a Default n a Policy n a AGL BUFFER SIZI LS Number of bits per color buffer If AGL_RGBA is specified this value is the sum of all components If a color index pixel format is specified the buffer size is the size of the color indices Type Unsigned integer n a Default n a Policy Greater than or equal to value AGL LEVEL Level in plane stacking Used to specify overlay or underlay planes Type Integer n a Default n a Policy Exact AGL_RGBA Choose an RGBA format Type Boolean GL_TRUE Default GL FALSE Policy If GL TRUE search only RGBA pixel formats else search only color index pixel formats AGL DOUBLEBUFFER Select double buffered pixel formats
261. g Return non zero if the exten sion exists and zero if it does not e glutGetProcAddress glExtensionNameARB Return a function pointer for the named extension if it exists and NULL otherwise These two API entries together constitute a complete set of extension testing and API binding operations for extension functions in a cross platform fashion Extension Management Libraries 273 If the complexity of GLEW isn t something you need and writing GL level man agement isn t your bag either these tools may be just what you re looking for In Example 13 12 we present C code for checking the OpenGL version number as a component of our example shading extension tests adapted for GLUT In Example 13 13 we reimplement our Cocoa shader test using the GLUT exten sions As you can see the code is very similar to that used for both Cocoa and raw GL Example 13 12 Query for OpenGL Version Information Using GLUT float openGLVersionNumber char versionstring char glGetString GL_VERSION std string vs versionstring return atof vs substr 0 vs find c_str Example 13 13 Query for Shader Extensions Using GLUT bool hasShaderExtensions t bool has shading false float versionfloat openGLVersionNumber if versionfloat 1 21 bool has_vs glutExtensionSupported has_fs glutExtensionSupported GL ARB vertex shader GL ARB fragment shader
262. g destinations In Apple s terminology off screen denotes a rendering tar get that is without hardware acceleration For this reason and because creat ing hardware accelerated render targets with no on screen footprint is so easy you ll probably want to avoid pixel formats with off screen attributes We ll describe a few caveats of creating and managing these entities but only for ref erence If you see off screen surfaces used in a modern application it s probably a good time to consider refactoring to use framebuffer objects Alternative Rendering Destinations 109 Creation and use of off screen surfaces begins with specification of the GL_AGL_OFFSCREEN token when constructing a pixel format Only an AGLContext that has been successfully created with a pixel format using this token can be used to perform true off screen rendering After creation of a con text the next steps are to bind this off screen render area to make it active for rendering and to render As with full screen and windowed rendering there is an analogous command ag1SetOffScreen to perform this binding The target of this binding is a memory buffer you specify in the call rather than an existing Carbon window The Apple documentation pages have detailed infor mation on all the arguments these calls take As this isn t really recommended practice we won t describe this technique in more detail Consult the Apple documentation for the most complete descriptions
263. g resources from one OpenGL context in another OpenGL context Deferred validation The caching or postponement of data or state changes in OpenGL until these changes are required at drawing time Direct memory access A hardware to hardware fetching of data In the con text of graphics it usually entails the GPU fetching data from a region of specially mapped or reserved host system memory Display capture To take over a particular display as part of a full screen ap plication Fragment A collection of all framebuffer state information for a single pixel A fragment may have some or all of color alpha depth stencil and other re lated data The data associated with a fragment is defined when the drawable or surface for the framebuffer containing this fragment is constructed Framebuffer A destination buffer to which the results of OpenGL rendering are written Frame rate quantization A description of the artifact observed when analyz ing the performance of double buffered OpenGL windows where the frame rate moves between discrete states defined by integer divisors of the mon itor refresh rate For example a 60Hz monitor refresh may cause a double buffered application to run at 60Hz 30Hz or 20Hz GLSL Acronym for OpenGL Shading Language GLX The OpenGL and X Windows interface layer The GLX specification describes how OpenGL contexts and drawables interact with X Windows widgets and windows 281 Immediate mode rendering Rend
264. g the definitive extension management toolkit Apple even has its own version of something like GLEW though it s just example code Apple has written a little tool it calls g1 Check If you re interested in learning the details of ways of managing extensions it s worth a look 6 Because GLEW and GLUT are supported on multiple platforms those tools are preferable in the authors estimation However all OpenGL extension and Extension Management Libraries 269 feature management toolkits tend to perform the same basic functions so at the time of this writing GLEW will be our preferred toolkit due to its comprehen sive nature and modernity Now if you re roped into thinking Man insert extension management API name here stinks GLEW for example I guess I ll just have to rewrite my own toolkit from the ground up we hope you ll at least first consider trying to work with the authors of the package you choose in an effort to make it better Okay we now step down from our high horse Let s first look at the tool GLEW and then explore an example in which we use it in an application GLEW GLEW is a toolkit comprising a library for extension management and a few tools for introspection of system graphics capabilities GLEW is a cross platform tool that will build on Windows Linux various UNIXes and of course the Mac In addition to handling extensions for OpenGL GLEW manages ex tensions for window system layers such
265. gSize 305 Enable or disable surface backing size override kCGLCEDisplayListOptimization 307 Ability to turn off display list optimizer CGLContextEnable Context Management 65 Read Write Parameters kCGLCPSwapRectangle If your application occupies much more screen space whether the full screen or windowed than you are typically drawing to a kCGLCPSwapRectangle may be specified as an optimization hint for OpenGL When a swap rectangle is defined the Mac OpenGL implementation may be able to optimize your ap plication by only swapping the back to the front buffer in the region defined by this swap rectangle As with any hint this behavior is not guaranteed Fur thermore the region outside the swap rectangle may be swapped or flushed by the Quartz windowing system itself This is often the case in a compositing situation where windows overlap kCGLCPSwapInterval The swap interval parameter allows applications to control the frequency at which the buffers are swapped in a double buffered application The swap inter val allows your application to tie buffer swaps to the retrace rate of the display This behavior is often desirable for real time applications that wish to guarantee a specific frame rate rather than running as fast as they can This mechanism allows synchronization of your application with an external device that gener ates interrupts at a fixed time interval If the swap interval setting i
266. gin glEnd pair Until glEnd is called the vertex data must be retained by OpenGL until needed for rendering This simple example can be extended to textures as well Thus if you consider how large textures can be and how many vertices you typically submit it s easy to see how much of a performance problem the copying of this data can be The OpenGL Multithreaded Engine As mentioned earlier the OS X OpenGL implementation has some unique fea tures that distinguish it from other implementations One detail worth noting is its long history of running on multiprocessor systems This means if you thread your application today you ll immediately have a sizable audience that will benefit from your application A major benefit of threading an OpenGL application aside from the obvi ous gains from having additional processing power is the possibility of finer grained control over processing tasks By having two or more threads you can limit the blocking that occurs when the GPU is waiting for the CPU and vice versa The recommended approach for threading OpenGL applications is to have all drawing commands originate from a single thread Other threads can then be used for handling application tasks such as culling and scene management processing of audio samples or perhaps physics and collision detection The more CPU processing your application needs to do whether it s to pre pare data for drawing or to carry out other
267. glCompressedTexImage API to upload them Alignment Considerations On the upside the precedent for having power of two sized textures relieves some of the alignment problems you might see in the pixel paths On the Textures 225 downside texturing can aggravate the alignment problem when you are doing glTexSubImage calls By its very nature g1TexSubImage replaces an arbitrary region of pixels within the texture The curse word in the previous sentence is arbitrary when it comes to alignment concerns In short you should try to subtexture such that the replacement of texels falls on natural alignment boundaries if possible Sometimes it can t be done but it s always worthy of consideration Shaders Shader performance like many features of OpenGL depends on the gen eration of graphics hardware used The introduction of shaders meant that graphics hardware had to transition from fixed function silicon to hybridized silicon consisting of both fixed function and programmable silicon to all programmable silicon On modern graphics hardware a fixed function state is handled using programs that are generated by the framework and or driver when that state is specified through the API There is a fair amount of residual wisdom from the hybridized time when it made sense to use fixed function state wherever possible for performance rea sons The confusion was somewhat compounded by the different paths chosen
268. gn your bug You will want to short circuit this process as much as possible by providing as much essential information as possible Honing your bug report as described earlier by trying different renderers trying different graphics cards checking the GL error state and so on is a great start The next thing is to specify the precise steps to reproduce the bug If you have a very complex environment requiring a sophisticated license mechanism or hardware dongles see if you can pry the problem out of this environment and make it reproducible in a more simple setting Other essential information includes the OS X build number which can be ob tained by clicking the Version text of the About This Mac dialog you can bring up from the Apple menu Also provide information on the graphics hardware that is installed on the test system One final note on bug filing Try to attain the holy grail of bug reporting a small test application Sometimes this is impractical but often it s not too hard 40 Chapter 4 Application Programming on OS X to create a small application with the offending OpenGL state that produces the problem Don t hesitate to ask Apple for template applications that can be augmented to create a test application The company has templates that use all of the windowing system interfaces to OpenGL on Mac OS X CGL AGL and Cocoa With a smart and informative title some coverage testing as described earlier ste
269. h precision or 64 bit math If so then the G4 may not be sufficient but G5 and IA64 capable Intel CPU performance results are going to be very good Establishing the processor baseline will also give you some clues about the available graphics bandwidth of the system For instance no Mac system with a G3 processor supports greater than AGP 1x No Mac system with a G4 processor supports greater than AGP 4x G5 processor based Macs support up to AGP 8x and PCI Express Intel based Macs support PCI Express throughout the prod uct line and have different characteristics for memory bandwidth as well The point here is that it s important to consider the data rates that your application may request of and realistically attain from the system By knowing the basic system CPU you can make a few assumptions about how much bandwidth is available Bus Two primary busses come into play with today s Mac computers the memory bus and the graphics bus 28 Chapter 3 Mac Hardware Architecture Memory The physical data path between main memory the CPU and other subsystems is known as the memory bus The memory bus is the primary path over which data flows when it is being loaded to and from a disk a network or graphics Memory bus speeds are implicitly related to the performance of the CPU so knowing one gives insight into the other Historically there has always been an even multiplier between the clock rate of the memory bus and that of
270. h and the fallback The fallback may not ac tually satisfy those features so instead of the feature you want you should choose a plausible standby visualization for example simple texture ver sus shaded surface Second write code to make sure your application will compile regardless of which OpenGL tokens are available in the headers on the system on which you re building This means you should protect re served tokens by using a combination of preprocessor tokens Third write code for runtime validation of the features and fallback path you re interested in using We ll now look at this process concretely and with code Our first step is to choose the extensions and the preferred combination of OpenGL version and extensions an alternative combination of OpenGL version and extensions and a fallback visualization if neither the preferred nor the alternative path is avail able In this example we will begin with our standby quad visualization code and decide to shade it What combination of extensions and versions will satisfy our needs Well we look at the latest OpenGL specification for guidance The OpenGL specification is available at the OpenGL website 2 for this example we ll use the OpenGL 2 0 specification 1 as our baseline Shading is supported natively in this ver sion so our preferred path will be to use OpenGL 2 0 We then look back in ear lier versions referenced by the specification and find that prior to this ver
271. h care so as not to introduce memory or performance problems in your appli cations Rendering to them requires either switching the drawable of your CGL context or doing a context switch from your main rendering context to a con text you ve dedicated to the pbuffer Neither of these operations is particularly cheap Fortunately pbuffers have been handily superseded by the introduction of framebuffer objects in OpenGL 2 0 The framebuffer object extension to OpenGL was one of the largest and most carefully considered additions in OpenGL s his tory Therefore there is no reason to use pbuffers for new software development on the Mac Of course there is plenty of existing software that uses the pbuffer API so it s worthy of discussion here The pbuffer API in CGL consists of the entry points seen in Table 6 1 To create a new pbuffer use CGLError CGLCreatePBuffer long width long height unsigned long target unsigned long internalFormat long maxLevel CGLPBufferObj pbuffer Notice the target and internalFormat parameters target may be either GL TEXTURE 2D GL TEXTURE RECTANGLE EXT or GL TEXTURE CUBE MAP 78 Chapter 6 The CGL API for OpenGL Configuration Table 6 1 CGL Pbuffer Functions Function Description CGLCreatePBuf fer Creates an AGL pixel buffer for use with an OpenGL texture type CGLDestroyPBuffer Destroys an AGL pixel buffer CGLDescribePBuf fer Gathers inform
272. h each of the major OpenGL interface APIs on the Mac showing how to use each in a sample appli cation and how to customize those applications for your specific needs We will also explore the surrounding OpenGL infrastructure on the Mac from tools to secondary APIs used to get data into OpenGL Finally we will attempt to bring 4 Chapter 1 Mac OpenGL Introduction a sensibility and a practicality to all of our discussions not trying to explain everything there is in all APIs examples and tools but just what s necessary and useful We approach this entire topic from the perspective of an application developer who is trying to get a high performance great application developed on the Mac OpenGL on the Mac is a large domain but we have a good filter for what is important and have written this book with an eye toward ensuring the reader s enjoyment of this learning experience The Book 5 This page intentionally left blank Chapter 2 OpenGL Architecture on OS X Overview The Mac hardware platform has historically varied widely with regard to CPU I O devices data busses and graphics cards The transition to Intel processors brings yet another step in this evolution to developers who now have ano ther Mac platform to consider with many different specifications Despite the fact that the underlying hardware on the Mac differs so widely the software architecture of OpenGL provides programmatic consistency for graphical a
273. hapter 5 Chapter 6 Application Programming on OS X OV VCE VAC P Mac OS X Versions cicclllese e m RE RR RR eden System Configuration 00 ce cece eee eee ene hehe Power Managementin 6a tleiwddauliicad Paese da evet ia eset dateadints Pilesystemic 4 452450 400 Gi HEURE PO PREIS IPTE RE Finding Verifying and Filing Bugs 00008 Threading 22 2 69 y ads Pre ads eee eae eee ee od Data Parallel Computation SIMD 00 eee eee PowerPC esse ee RR sees ey esa ENERET EE ESEE E TEES nee OpenGL Configuration and Integration API Introductions and Overview 0000 cece eee eee eens Mac Only APIS 2 date e bec EIE Rebate deer tk ad Urdu anaes Cross Platform APIs Supported on the Mac 0565 API Introduction and Overview Wrap Up sssssessesssse Configuration API Relationships esee Sharing OpenGL Data Between Contexts 00005 Framebu lffers i 2 onssvlLekesrer elu erre eR AISdeD BUTUESDHE UPS The CGL API for OpenGL Configuration OVEIVICW io iissa pisart sipo ma E EEEE EE E EEE EE EE Error Handling 2 2022 ehe asne RII a E E EES Pixel Format Selection 2ccsses esce seeker eere CGLChoosePixelbormat ecarri mede DL ple beeen eg Policies and Butter DIZNE 2 ssere mer ame oe asses eeRPRER IRURE M VE Render Targets D niae eaa RO MERRIPREREARUEPPOU EF GRIS Multisanipling si oseere tesa perenne rmn Ree Mes pe gs VI
274. hat is used as a desti nation for rendering This block of memory must be allocated by your applica tion and submitted to CGL through a call to CGLError CGLSetOffScreen CGLContextObj ctx long width long height long rowBytes void buffer You must allocate a buffer that is at least rowBytes height in size As you might expect because the off screen buffer is in host memory off screen rendering is the slowest kind of rendering of all the possibilities If you wish to retrieve the off screen buffer as well as its size parameters and do some processing on the pixel data you can do so with a call to CGLError CGLGetOffscreen CGLContextObj ctx long width long height long rowBytes void buffer If a call is made to CGLGetOffscreen when the drawable associated with the context is not an off screen buffer all size parameters are set to 0 and the buffer pointer is set to NULL Full Screen Drawables Unlike pbuffers and off screen drawables full screen drawables are not created as separate entities from the context Instead they are created implicitly by spec ifying kCGLPFAFullScreen as a parameter for the pixel format you use to create the context Not all renderers support full screen rendering with the Apple software ren derer being the most notable example You can test for full screen support of a renderer during the pixel format selection process as shown in Example 6 3 Example 6 3 Testing for Full Screen
275. have a lot of capability the core of what GLUT is remains unchanged It is a simple and uniform way of bringing up an OpenGL application in a platform independent way 163 GLUT Appkit AGL CGL CoreGraphics Figure 9 1 GLUT API and Framework in the Overall OpenGL Infrastructure on the Mac Overview The GLUT API is part of the overall Apple OpenGL infrastructure It leverages AppKit for its windowing and event requirements Figure 9 1 shows where the GLUT API and framework reside relative to other API layers The GLUT API lives in your particular SDK framework path or in System Library Frameworks GLUT Framework As with other APIs linking against GLUT requires specification of this framework path in our code examples specifying the variable SDKROOT Compiling using headers from the GLUT framework will also require specification of the framework The rele vant locations for building and linking with the GLUT framework are found in Table 9 1 GLUT is an interface for complete stand alone applications that provides a comprehensive set of windowing event management device input OpenGL setup OpenGL configuration and a few other miscellaneous functions If for whatever reason you can t find the interface you need within GLUT you re best off investigating one layer beneath it such as Cocoa or CGL For the most part GLUT provides a rich feature set that can be used to meet al
276. he basic process for ensuring that our runtime environment is valid is this Query the version number and query the extension list to confirm that our shading extensions are available Because these are runtime checks they must take place within a valid OpenGL context so we perform them within prepareOpenGL seen in Example 13 2 We first check whether our running OpenGL version is inclusively greater than 1 3 our baseline version for OpenGL functionality Example 13 2 Querying the OpenGL Version Number float openGLVersionNumber NSString versionstring NSString stringWithUTF8String char glGetString GL VERSION NSArray versioncomponents versionstring componentsSeparatedByString return versioncomponents objectAtIndex 0 floatValue The next code fragment in Example 13 3 uses our extension dictionary to query for four key components of the OpenGL Shading Language Each of these 262 Chapter 13 OpenGL Extensions eoo Window Figure 13 1 Shader Extension Application Results if Successful Texture cour tesy of NASA s Earth Observatory extensions implies a combination of tokens API entry points and functionality This code first builds a list of OpenGL extensions queried by the call g1Get String GL EXTENSIONS and then wrangles this list into a dictionary as shown in Example 13 4 We simply look up a value in the dictionary for ex ample GL ARB vertex shader and if a nil com
277. he displays supported by the installed display devices seamlessly For your application this means that an OpenGL window can be dragged from one virtual screen to another each of which has different rendering capabilities In this event CGL will automatically switch the renderer you are interacting with to a renderer representing the new territory that your application now occupies This feature has obvious implications if this new renderer does not have the same capabilities as your original renderer If your application then proceeds to draw but now lacks the capabilities it relies upon to render all kinds of unpleas ant things could be displayed For example one consequence might be that your application is running on a renderer that has half the texture resources or that your application is running with a surface that doesn t have stencil capability If you relied on having stencil capability for some form of pixel test your appli cation may not be able to get those results computed on this new renderer In the texture case your application may suddenly begin swapping textures in and out of graphics memory with each frame yielding dramatically slower perfor mance Of course the most extensive set of consequences from changing virtual screens could relate to a raw OpenGL capability change It s possible that an OpenGL extension you were using on one screen will be unavailable on another screen Fortunately the Mac OS X software arc
278. hen reading the CGL reference guide segment on CGL ChoosePixelFormat You may or may not find additional information on your topic but it s a good information path to keep in mind We hope we ve disuaded you from using either the surface texturing or pbuffer methods of rendering to textures on OS X in favor of using OpenGL framebuffer objects Taking pbuffers out of CGL simplifies its usage to renderer selection and context management Popular belief says that Carbon applications are a thing of the past and that the future belongs to Cocoa applications on OS X While we re not here to weigh in on this opinion remember that CGL is not part of the Carbon Cocoa equation CGL is part of the OpenGL framework and will be supported with as much vigilance as OpenGL itself Summary 87 This page intentionally left blank Chapter 7 The AGL API for OpenGL Configuration Overview OS X has both Carbon and Cocoa windowing interfaces to OpenGL AGL or Apple OpenGL is the Carbon windowing interface to OpenGL Like CGL and Cocoa the AGL interface provides a set of routines for managing pixel formats OpenGL contexts and drawables a k a surfaces As far as Apple technologies are concerned AGL is overshadowed by the more modern and objectified Cocoa Still AGL has its place in today s applications and is still a first class citizen when it comes to Apple s ongoing support of the API Despite AGL being the old way to do t
279. her new feature with 10 3 was the introduction of hardware accelerated pixel buffers Pixel buffer operations are known on many platforms as pbuffers and on Mac OS X a specific extension exposed these hardware accelerated off screen render targets That extension which was named GL APPLE pixel buffer was really the underpinning of how Apple itself achieved UI acceleration 10 4 Tiger Atthe end of May 2005 Apple released Mac OS X 10 4 also known as Tiger This particular evolution of the operating system offered some significant enhance ments for those in the graphics world In particular Tiger brought high level programmable shading languages to the Mac the latest OpenGL Architecture Review Board extensions and a continuing movement toward hardware based 246 Chapter 12 Mac Platform Compatibility acceleration of all elements of the UI through a technology known as Quartz 2D Extreme Aside from the obvious performance benefits the later trend can provide to user experiences through the windowing system it raises an inter esting point for your application to consider You are not alone What we mean by this statement is that your application and the window system itself share the resources of the graphics card As a consequence both the graphics memory and the graphics bandwidth are in use by the UI and your application simulta neously Thus you have fewer resources in both areas when it comes time to run your application whi
280. hes for pixel formats for each AuxBuffer that has its own depth stencil buffer NSOpenGLPFARendererID Unsigned integer ID of renderer Selection policy Prefer renderers that match the specified ID Refer to CGLRenderers h for possible values NSOpenGLPFAAccelerated YES Modify the selection policy to search for pixel formats only among hardware accelerated renderers NO default Search all renderers but adhere to the selection policy specified Selection policy Prefer accelerated renderers NSOpenGLPFAClosestPolicy YES Modify the selection policy for the color buffer to choose the closest color buffer size preferentially This policy will not take into account the color buffer size of the current graphics devices NO default No modification to selection policy NSOpenGLPFABackingStore YES Constrain the search of pixel formats to consider only renderers that have a back color buffer that is both the full size of the drawable and guaranteed to be valid after a call to a buffer flush NO default No modification to the pixel buffer search NSOpenGLPFAWindow YES default Search only among renderers that are capable of rendering to a window Note This attribute is implied only if neither NSOpenGLPFAFullScreen nor NSOpenGLPFAOffScreen is specified NSOpenGLPFAPixelBuffer YES Rendering to a pixel buffer is enabled 292 Appendix C The Cocoa API for O
281. hese baselines and ex plains their implications for your application CPU and Clock Rate Consider this minimum configuration example with regard to CPU and clock rate On Mac OS 10 3 also known as Panther the minimum required CPU is a 300MHz G3 processor 128MB of RAM and no explicit requirements on VRAM of the graphics card What does it mean to you if the system has a G3 processor Aside from clock rates being lower we know that a G3 processor has no vector engines to process AltiVec code If your application requires intense vector code to sustain a minimum frame rate of 30 frames per second FPS it s not going to perform well or maybe even at all on a G3 Note that G3 support was dropped in Leopard Also you should recognize that the lack of a vector engine will create some nonlinearities in what might be expected of a system based on its clock rate alone For instance if performance on a G3 based system was estimated simply by scaling the performance on a test run carried out on a G4 you may be in for some surprises To further aggravate these results the Mac OS software itself relies heavily on the AltiVec engines wherever possible In the absence of these vector units the performance bottleneck of your application could shift from somewhere in the graphics processing to the CPU How about having a G4 as a minimum requirement A G4 does get you some on chip vector engines but does your application do a great deal of hig
282. hether QuickTime thinks it can open this particular file and all subsequent usage of the loaded movie is enabled or disabled by successful or unsuccessful loads respectively It s probably a good thing to check in your own applications too before going through the effort of creating textures and loading movies Earlier we mentioned NSMovie and explained why using it is undesirable but what about the Movie Toolbox The Movie Toolbox has existed since the very early 1990s For those of you who are old enough to remember the early 1990s it was a very different coding world in general C was prevalent C wasn t yet a huge thing and Objective C hadn t made its debut on the Mac in a big way QuickTime 189 e080 Window Figure 10 3 Subsequent Frames of the Movie NeXT was cranking away on Objective C and a lot of really interesting ideas for user interface libraries which would much later become the Cocoa API for Mac OS X However the mainline Mac world was still focused on Pascal and in some measure C At that time the Mac was known for many things but none of them was ease of coding The QuickTime Movie Toolbox matches that expectation to this day Though it is possible to use the movie Toolbox with OpenGL and we ve done projects for clients using it we won t discuss it here The main reason for avoiding it at this point is simplicity We re not writing this book so that you can learn eso teric corners of general Mac APIs bu
283. hey re pretty much boilerplate OpenGL Let s now look at the entirety of our example application main method and see how a pixel format is declared described and initialized Example 7 3 AGL Full Screen Application main Method int main int argc char argv create pixelformat AGLPixelFormat pixelFormat GLint attribs AGL_DOUBLEBUFFER AGL_ACCELERATED AGL_NO_RECOVERY AGL_RGBA AGL_NONE ub pixelFormat aglChoosePixelFormat NULL 0 attribs create context amp bind to full screen context aglCreateContext pixelFormat NULL aglDestroyPixelFormat pixelFormat aglSetCurrentContext context aglSetFullScreen context 0 0 0 0 main loop initGLstate draw sleep 3 cleanup aglSetCurrentContext NULL aglDestroyContext context return 0 In Example 7 3 we build code in a few main sections The first of these meth ods creates and fills out an AGLPixelFormat structure In it we specify the desired attributes of our OpenGL render target in this case that we would like an RGBA double buffered hardware accelerated drawable Each pixel format specification must end with the AGI NONE token or you ll encounter unexpected pixel format selections at best and crashes at worst Next we issue the command to actually find a pixel format matching our cri teria using aglChoosePixelFormat The last argument is our attribute list and the first two arguments are a hand
284. hich OpenGL was supported was X11 This windowing interface to OpenGL is called GLX GLX running under X11 is anal ogous to Cocoa or Carbon running under the Quartz windowing system of the Mac X11 was introduced to OS X in OS 102 Jaguar The X11 server runs within the Quartz windowing system in either full screen mode or windowed mode The X11 server also takes care to present some widgets and UI elements in the Aqua style so that even if your application is just a simple port of another X11 based application at least some of the UI elements are rendered in the Mac style This behavior makes the X11 environment a possible alternative to a full scale port However no native Mac user will be fooled because X11 doesn t have nearly the visual richness of the native Mac UI elements A better path to bringing an OpenGL X11 application to the Mac may be to start with the simple port work out some of the OpenGL bugs and as time and budget permit rework the UI in native Cocoa or Carbon In this appendix we ll examine the capabilities APIs and behavioral character istics of using OpenGL on the Mac under GLX and X11 Installation X11 is available as an install option on OS X install disks versions 10 3 and later The system requirements for installing X11 are as follows 277 e 256MB RAM e 200MB of available hard disk space e A built in display or a display connected to an Apple supplied video card When the installation is complete
285. hings from the perspective of hard core Apple technology buffs it has its advantages Because Cocoa is defined as an Objective C class hierarchy there are some obvious reasons why adapting an existing application not written in Objective C would pose more challenges This is especially true if the existing application doesn t have a distinct soft ware abstraction defining its view in the model view controller design pattern In other words if the UI logic is not easily separated from the application logic it s difficult to replace the UI logic with code from a different object based UI library like that of Cocoa Another potential challenge of using Cocoa is its use of Objective C Although Objective C applications can be written as a conglomeration of C C Objective C and even Java moving between the syntax and semantics of different programming languages always imposes some overhead to the soft ware development process AGL then being defined as a simple procedural C API has its advantages It can more easily be integrated into existing C and C applications Developing 89 a porting strategy from windowing interfaces of other platforms such as GLX or WGL is relatively simple To make the Cocoa versus AGL decision even more complex the Carbon event model in the humble opinion of the authors is more complicated than the event model used by Cocoa One of the most redeeming aspects of AGL is its clear and apparent simi
286. his means that you avoid not only off card copies to and from the host but also avoid on card copies in good implementations of the extension Second framebuffer objects present a consistent platform agnostic interface in terms of their usage There just isn t a more simple interface to intermediate rendering than these objects largely due to the evolutionary process by which OpenGL is developed Third framebuffer objects avoid expensive context switching that can cost you a great deal of performance A variety of intermediate target rendering APIs and implementations have been explored over the years culminating in today s design and implementation Framebuffer objects are the best choice for modern rendering on the Mac regardless of whether you re using AGL CGL or Cocoa Alternative Rendering Destinations 119 Summary In this chapter we explored how to create and configure AGL based OpenGL rendering areas for on screen and full screen windows and for various interme diate render targets We also saw how to create custom pixel formats explored some of the common flags that these pixel formats take and demonstrated how to configure and initialize contexts and pixel formats In addition we saw how to integrate a variety of rendering destinations into an AGL application We learned how to share data among multiple contexts and to configure full screen surfaces Now that you have explored the fundamentals of AGL OpenGL setup cover
287. hitecture will switch renderers for your application to meet its needs automatically For example if the user moves your application s window from a screen supported by a higher performance graphics device such as a high end ATI Radeon to a screen supported by a lesser performance graphics device Mac OS X OpenGL can switch from us ing the Intel GPU to its native software renderer and perform your render ing on the host CPU This performance is much slower of course but at least it provides your application with logic capable of producing the correct output Renderers 19 Whenever an application crosses a virtual screen boundary it must make a call to synchronize its OpenGL context across the two different renderers In other words the context should be synchronized whenever your application win dows are moved This is due to the fact that in addition to the OpenGL context that you manage every OpenGL application has a context that is maintained in the OpenGL runtime engine This context holds all of the application s OpenGL rendering state The renderer for each virtual screen also contains a context of rendering state When an application crosses a virtual screen boundary the renderer is im plicitly changed by CGL At this time the new renderer doesn t know what s going on with the application s rendering state The explicit or implicit call to CGLUpdateContext serves to synchronize the new renderer state to that of the applica
288. hould do anything we want to do once per context but not more often Download ing textures is a good example of an operation that should not be performed 174 Chapter 10 API Interoperability per frame so it fits well in prepareOpenGL Let s add two NSI based on a URL and another based on a file Example 10 2 Example 10 2 Initialize NSImages void prepareOpenGL glMatrixMode GL_PROJECTION glLoadIdentity glOrtho 1 1 1 1 1 100 NSURL url NSURL URLWithString Q http www yosemite org vryos turtlebackl jpg NSImage url image NSImage alloc initWithContentsOfURL url NSImage file image NSImage alloc initWithContentsOfFile System Library Screen Savers Cosmos slideSaver Contents Resources Cosmos07 jpg resize our image to a power of 2 NSImage file_image_resized self transformImage url image toSize NSMakeSize 512 512 download an image as a texture self downloadImageAsTexture file image resized configure texture environment glTexEnvf GL TEXTURE ENV GL TEXTURE ENV MODE GL REPLACE glEnable GL TEXTURE 2D add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES mages one There s really not much to this phase of the example and everything works as expected We should howe
289. ializing an NSView so we can do the fun bits in creating a context and a drawable too This step is necessary if you want to do more advanced context things such as share data with another context More on that in later sections Moving along now that you know how to choose a pixel format it s prob ably an appropriate time to discuss what the various flags mean to an NSOpenGLPixelFormat These flags are generally well documented by Ap ple but we re including a list of all the flags in one spot for handy reference here Take a look at Tables 8 2 and 8 3 see which values make sense for your application and try a few in the code we ve just developed Table 8 3 contains a fair bit of exposition on these flags including what the various values mean and how you might use them it s worth a quick read In particular pixel format selection can have a profound impact on both the per formance of and the video memory usage by your application Keep in mind that choosing pixel formats with more capabilities may lead to slower perfor mance than choosing pixel formats with fewer options and smaller buffers For example if you have a choice between a pixel format with a color buffer size of say 8 bits per color component 32 bits total or one with a color buffer rep resented as a 32 bit floating point number per component 128 bits total it s pretty clear that writing to a single pixel in your drawable requires four times the bandwidth just for c
290. ied design consid erations from various industry interests that only open standards can Indeed these diversified corporate and educational interests contributions are the very reason OpenGL runs on the widest array of devices Furthermore because de sign decisions are better decoupled from proprietary interests the result is quite simply a better and more generalized design If you re new to the base OpenGL API we won t be much help to you in this book because we re focused on Mac specific infrastructure However there are other great books and resources on the subject out there The canonical refer ence the so called Red Book 22 and the OpenGL website 2 provide a good foundation for OpenGL developers There are also other more compact guides such as the recent OpenGL Distilled 19 The bibliography lists a few other ref erence books of note including those describing in detail how to use OpenGL on other platforms 15 18 This book is a companion to those resources focus ing on the infrastructure performance and integration of OpenGL on the Mac The Book What we describe in this book is the essence of OpenGL usage and integration on the Mac We won t try to motivate you to choose the Mac or OpenGL fur ther but will rely on you to make your own informed decision after reading our text We will describe in detail the rendering architecture used by Mac OS X and note how OpenGL integrates into it We will explore in dept
291. iger 10 4 by default but it is also available for Panther 10 3 through installation of QuickTime 7 and the associated SDK OTKit is a very comprehensive and powerful API and it simplifies the process of using QuickTime by removing a lot of legacy Movie Toolbox data types so that a new programmer can simply focus on the Cocoa techniques However OTKit is still a big API with lots of dark corners and complexity In this section we ll try to remove as much of that complexity as possible and provide an example that QuickTime 185 accomplishes our goal of rendering to OpenGL as efficiently as possible in terms of both performance and overall amount of code Our plan of attack to integrate your QuickTime content in OpenGL is simple We ll use similar baseline code as we included in our NSImage example but take advantage of the fancy media handling capabilities within QuickTime to decide which frame we need to play and when to download it to the graphics The overall process is this Initialize OpenGL Create a Movie object with content Configure the Movie Grab the current display and use it as the texture Render the OpenGL data using that texture C DES It s actually not that much more complex to do this in code so let s dive in We ll begin by looking at a snippet of code to initialize our OpenGL buffer and the OTMovie We add code to our existing prepareOpenGL method replac ing the NSImage initialization code from our pri
292. ing CGLTexImagePBuffer First a texture ID of 0 otherwise known as the default texture is off limits You must bind a non zero texture ID gen erated through use of g1GenTextures by using g1BindTexture to a tex ture with pbuffers Second you must use a clean newly generated texture ID that has not been populated or more accurately contaminated with data from any OpenGL call that is capable of doing so Examples are any variant of glTexImage glCopyTexImage glCopyTexSubImage orglTexSubImage You can purify a contaminated texture ID only by deleting the texture and by chance getting the same ID back from a call to g1GenTextures For clarity the sourceBuf fer argument should have been implemented in the API with a type of GLenum sourceBuf fer refers to the source buffer for tex turing from the pbuffer It must correspond to a valid OpenGL buffer that was defined as part of the pixel format used to create the renderer for this pbuffer The set of possible values for sourceBuf fer is simply GL FRONT or GL BACK If neither is specified a kCGLBadValue error code will be returned Pbuffer contents may be read back by using a call to g1Get TexImage2D when the main rendering context is current and your pbuffer is bound as the cur rent texture or by using a call to g1ReadPixels when the pbuffer s context is current Drawables 81 Off Screen Drawables Off screen drawables are simply a block of host memory t
293. ing a pointer to the new context The next method we will create is an overloaded method of NSView named lockFocus NSView uses this method to make the current view the focus so that it s the target of whatever drawing commands follow Quoting the Co coa documentation lockFocus locks the focus on the receiver so subsequent commands take effect in the receiver s window and coordinate system This command essentially tells the windowing system that we will require some spe cific configuration to be set up and active before we render into this window Why do we need this Well every OpenGL context is essentially a snapshot of the entire OpenGL state used during rendering Thus if you ve painstakingly configured some precise combination of OpenGL data rendering paths and other information the same context in which you ve done that work is likely the one in which you d like your subsequent OpenGL commands to be executed Put more succinctly you want your context to be active In context parlance NSView 139 this is known as making your context current lockFocus is the place in the Cocoa framework where your view is made current and where you can then make your context current If we now look at our code we can see that we need to overload this method to do the usual lockFocus work when we call our superclasses lockFocus We then do work to get our OpenGL context and make it current And that as they say is that We ve got
294. inimally configured and quiescent Mac using the util ity application Activity Monitor or Big Top can give you a basis for determining how much free memory you can reasonably expect to have available Doing so early in your development cycle may help you later diagnose memory related performance headaches Summary Graphics application writers should have a solid understanding of the often well known hardware limitations for the software they are writing or intend to write If your application will handle a great deal of vertices you should antic ipate the effects of potential transform or shader limitations for these vertices and design your software and data structures accordingly Similarly if your ap plication is heavier on the back end of the OpenGL pipeline where heavy raster ization is required you can program defensively for those limits In either case knowing the overall VRAM requirements of your application the VRAM re quirements of Mac OS X itself and the available VRAM of the target hardware is as important to application performance as a consideration of the general system s RAM The hardware landscape for Macs is quite diverse Nevertheless it s essential to get a handle on these configurations so that you can develop applications that are highly optimized yet usable on a rather diverse class of Mac hardware 32 Chapter 3 Mac Hardware Architecture Chapter 4 Application Programming on OS X Overview Th
295. is task and describe possible variations at each step Many readers will be able to just glance at the example and get all the information they need If so you can skip the individual steps In any case immediately follow ing the steps is a full description of the complete set of renderer properties Most developers will be interested in reading through this list to determine the appli cability to their application Now the example Example 6 2 Creating and Inspecting Renderer Info Objects include lt OpenGL OpenGL h gt include OpenGL gl h include lt OpenGL glext h gt include lt CoreGraphics CGDirectDisplay h gt include lt stdio h gt include lt stdlib h gt 68 Chapter 6 The CGL API for OpenGL Configuration int main int argc char argv Grab the display mask for the main display using kCGDirectMainDisplay steps 1 amp 2 of 4 CGOpenGLDisplayMask displayMask CGDisplayIDToOpenGLDisplayMask kCGDirectMainDisplay CGLPixelFormatAttribute attribs kCGLPFAFullScreen kCGLPFADisplayMask displayMask 0 CGLPixelFormatObj pixelFormatObj CGLContextObj contextObj CGLRendererInfoObj rendererInfoObj long i numPixelFormats rendererCount vram texMem rendererID Create the context CGLChoosePixelFormat attribs amp pixelFormatObj amp numPixelFormats CGLCreateContext pixelFormatObj NULL amp contextObj CGLDestroyPixelFormat pixelFormatObj CGLSetCurrent
296. ison Wesley 1995 17 IST IST OpenMotif website http www istinc com DOWNLOADS motif_download html 18 Mark J Kilgard OpenGL Programming for the X Window System Boston MA Addison Wesley 1996 19 Paul Martz OpenGL Distilled Boston MA Addison Wesley 2006 20 OpenMotif OpenMotif website http www opengroup org openmotif 21 Randi J Rost OpenGL Shading Language Second Edition Boston MA Addison Wesley 2006 22 Dave Shreiner Mason Woo Tom Davis and Jackie Neider OpenGL Programming Guide Fifth Edition Boston MA Addison Wesley 2006 324 Appendix C Bibliography Index Note Information presented in tables and figures is denoted by t and f respectively A Activity Monitor 227 Advanced Graphics Port 29 30t AGL see Apple OpenGL AGL_ACCELERATED 99t AGL_ACCUM_ALPHA SIZE 97t AGL ACCUM BLUE SIZE 97t AGL ACCUM GREEN SIZE 97t AGL ACCUM RED SIZE 96t AGL_ALL_RENDERERS 95t AGL ALPHA SIZE 96t AGL_AUX_BUFFERS 96t AGL AUX DEPTH STENCIL 98t AGL BACKING STORE 100t AGL BLUE SIZE 96t AGL_BUFFER SIZE 95t AGL CLOSEST POLICY 97t AGL COLOR FLOAT 98t AGL DEPTH SIZE 96t AGL_DOUBLEBUFFER 95t AGL_FULLSCREEN 98t AGL GREEN SIZE 96t AGL LEVEL 95t AGL MAXIMUM POLICY 97t AGL MULTISAMPLE 98t AGL MULTISCREEN 100t AGL NO RECOVERY 99t AGL_NONE 101t AGL OFFSCREEN 98t AGL PBUFFER 100t AGL PIXEL SIZE 97t AGL RED SIZE 96t AGL REMOTE PBUFFER 101t A
297. isplay list drawing commands in VRAM and the inability to change the list contents if the data is dynamic Notice that the g1Begin glEnd method of specifying polygonal data was used in this example rather than the vertex array method cited earlier Vertex arrays along with any other OpenGL client state may not be used in display lists As a consequence an OpenGL client application may reside in the address space of one machine while the OpenGL server exists in the address space of another If a client address pointer showed up in a display list the OpenGL server on another system wouldn t know how to resolve it Finally we come to the latest and most general mechanism for submitting ver tices vertex buffer objects VBOs VBOs are more sophisticated than other retained mode or immediate mode rendering methods in that they provide the performance benefits of display lists yet support the dynamism of simple immediate mode rendering When VBOs are created they are initialized with parameters that character ize their anticipated pattern of use which in turn allows the OpenGL imple mentation to allocate the most effective resources and choose the most effective rendering paths for the data in the VBOs Example 11 6 shows how to use VBOs Example 11 6 Immediate Mode Vertex Submission Vertex Buffer Objects OpenGL context setup Preprocess vertex data as triangle strips into vertex buffer Create and bind a VBO ID glGen
298. ists of two basic calls gd1DrawPixels and glReadPixels which allow for drawing and reading respectively of pixels from the current write and read buffers These pixel path calls are 2D only and can read and write only screen aligned data By comparison the texture path differs from the pixel path specifically in that texture data can be rendered in 3D Because the texture path can also be used to render screen aligned images as well it is ultimately the more flexible of the two paths so we ll focus on the 140 Chapter 8 The Cocoa API for OpenGL Configuration texture path here The Red Book 22 has lots of details on the imaging pipeline if you d like more information on that Any pixel data that you might want to render in an OpenGL scene you can handle through textures To do so you would download that image as a texture using g1TexImage 123 D calls Let s provide an overview of this process and then translate it into code 1 Create and configure a texture g1GenTextures glBindTexture glTexImage2D glTexEnv glTexParameter 2 Bind that texture g1BindTexture 3 Draw using that texture glBegin glTexCoord2f glEng This book isn t meant to teach you fundamental OpenGL rendering techniques but the preceding sequence is essential to understand for two key reasons First texturing is the primary means by which you ll access the data you render to off screen surfaces and the primary way by which you ll re
299. it you say what about the rest of the key OpenGL configuration pieces the context and the drawable or surface By subclassing NSOpen GLView you re getting the last two pieces configured for you you lucky dog no extra work required The base NSOpenGLView class creates a context from the pixel format you passed in and it creates a drawable such that it can be visualized in the window we created with our CustomView back in Interface Builder Later however we ll go through the process of specializing an NSView so we can do the fun bits in creating a context and a drawable too This step is necessary if you want to do more advanced context things such as share data with another context More on that in later sections Moving along now that you know how to choose a pixel format it s prob ably an appropriate time to discuss what the various flags mean to an NSOpenGLPixelFormat These flags are generally well documented by Ap ple but we re including a list of all the flags in one spot for handy reference here Take a look at Tables C 2 and C3 see which values make sense for your application and try a few in the code we ve just developed Table C 3 contains a fair bit of exposition on these flags including what the various values mean and how you might use them it s worth a quick read Table C 2 Selection Policies and Behaviors Policy Description Match Choose only from the set of pixel formats that match exac
300. ities folder Try increasing the width height parameter and watching the effect on CPU usage Figure 11 1 shows one possible configuration of this example Clicking the Test button in the interface will provide a consistent performance measurement as it tumbles the model in space and updates the Frame Rate field upon finishing The fact that the routine that modifies the vertex data and the fact that GL QUADS is used rather than GL QUAD STRIPS are efforts to make the updates more costly and push on the CPU harder Again the point of this example is to load the system in various ways and move the performance bottleneck around so that you can get a feel for how to manage vertex submission in your own applications Efficient Handling of Texture Data Many applications are far more texture intensive than vertex intensive these days Here are some things to keep in mind when you are handling large quan tities of texture data Formats and Types The number of pixel types and formats in OpenGL has been on the rise since its inception This increase has been driven to a large extent by scientific and entertainment visualization work in which the data is acquired from a device Efficient Handling of Texture Data 221 eoo Double Buffered VBO sa 379 ML M APPLE flush buffer range Polygons og Depth Use 1 Color VBO Use glMapBuffer Fill MPix 170 39141 O O O Use 2 Color VBOs Use glBufferSubData Frame Rate Crest 4
301. ive to sleep Many application writers do not need to be concerned about the sleep semantics on the Mac If however your applica tion needs to respond to the sleep powering up or powering down events we thought we would include some of the essentials here From a device driver perspective consideration of power management can be rather complex Fortunately for user applications the task is much simpler The power management API is designed to accommodate a hierarchical set of power domains For application development the root power domain which covers all system sleep and power on events is all you will likely need to consider 34 Chapter 4 Application Programming on OS X For symmetry it is easiest to consider power on events as wake up events Sometimes these events may be misunderstood to mean the system has pow ered up from an off state based on the naming conventions used In reality a wake up event means that the system is coming out of a low power mode and is notifying your application of that state change So now that we have the sleep and wake up terminology straight let s consider sleep events There are two kinds active sleep events which are generated from the user selecting the Sleep option in the Apple menu and idle sleep events which occur in response to an inactive system Example 4 1 shows an example of power management code on the Mac Example 4 1 Power Management on OS X include include
302. ject is a handle to the base type and all its associated configuration state Another way to think of a framebuffer is as a collection of logical buffers arranged in a stacked or stratified manner Each logical buffer is a scalar field containing values specific to this layer in the rendered output Examples of these logical buffers are color buffers red green blue or alpha depth buffers stencil buffers and accumulation buffers An individual 1 pixel column through each of these layers is known as a fragment The related concepts of frame buffers and fragments are important in understanding both what s written and perhaps what s read from the framebuffer when your OpenGL commands are completed There are performance considerations here as well which we ll examine in later chapters Each scalar in these logical buffers is represented by some number of bits For instance an 8 bit red color buffer contains width height 8 bit scalar values and a 32 bit depth buffer contains width height 32 bit depth values The composition of these mixed size or same size logical buffers makes up a frame buffer Figure 5 2 depicts a typical framebuffer Configuration API Relationships 53 Total 24 Depth Fragment Size 24 Color Height Width Figure 5 2 Framebuffer Strata Framebuffers are a core resource for OpenGL They along with texture ob jects vertex array objects shader objects and other OpenGL resources must be cr
303. ke walking through the steps or would like to see the finished product first check out the sample code from our website www macopenglbook com Open the Resources folder and double click on the MainMenu nib icon This will open the nib file for this project in Interface Builder Now switch to Interface Builder In the MainMenu nib window click on the Classes tab and navigate through the three pane system until you finally click on NSView The panes should look like Figure 8 9 when selected Next click on the Classes menu and Subclass NSView item to create a new derived class based on the NSView type A new text entry field will appear suggesting the name MyView Accept the default name by pressing the Enter key or choose something more interesting Your results should look similar to Figure 8 10 As before we must create headers and code In the MainMenu nib window click on the Classes tab navigate to MyView and select it Click on the Classes menu and Create Files for MyView item It will prompt you to eoo 9 MainMenu nib Instances Classes Images Sounds Nib m Q Search java lang Object acd ger NSObject gt NSMenultem NSMovie NSResponder nd NSSou I SCNibObjectinfoManage fii Figure 8 9 Subclassing NSOpenGLView in Interface Builder 134 Chapter 8 The Cocoa API for OpenGL Configuration 000 Ei MainMenu nib Instances Classes images Sounds Nib A NSApplica
304. l GLUT_STENCIL Token to select a stencil buffered visual GLUT_MULTISAMPLE Token to select a multisample visual Automatically degrades to another visual if multisampling is not available GLUT_STEREO Token to select a visual with stereo abilities Configuration and Setup 169 a limited form of this capability through a complementary function called glutInitDisplayString Inno way is the GLUT process nearly as complete as the CGL AGL or Cocoa methods but it does allow you to exert a fair degree of control Among the capabilities exposed through this method a caller can specify the number of bits in various color or depth channels the number of samples in multisample visuals and the policy regarding how to select which visual matches We present a selection of states that can be specified through such a call in Table 9 3 and a complete description of these flags and their de faults can be found at the manual page man glutInitDisplayString So how are these flags used to specify a visual The tokens in Table 9 3 specify the individual visual elements to be specified With each we can also attach an optional policy The code for doing so requires the use of a standard set of operators with meanings equivalent to those operators meanings in C code For example to specify a visual with all buffer bits including alpha of depth 8 or greater we would write rgba gt 8 as part of ou
305. l 1 glMatrixMode GL MODELVIEW glClearColor 0 0f 0 5f 0 8f 1 0 glClear GL COLOR BUFFER BIT Generate a texture ID to allow pbuffer texturing glEnable GL TEXTURE 2D glGenTextures 1 textureID glBindTexture GL TEXTURE 2D textureID Set up the texturing environment glTexEnvi GL TEXTURE ENV GL TEXTURE ENV MODE GL MODULATE 112 Chapter 7 The AGL API for OpenGL Configuration glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL CLAMP TO EDGE glTexParameteri GL TEXTURE 2D GL TEXTURE WRAP T GL CLAMP TO EDGE glTexParameteri GL TEXTURE 2D GL TEXTURE MIN FILTER GL NEAREST glTexParameteri GL TEXTURE 2D GL TEXTURE MAG FILTER GL NEAREST Specify the pbuffer as the source for our texture data This acts as a substitute for a glTexImage2D call aglTexImagePBuffer context pbuffer GL FRONT The draw methods for each of the pbuffers and the main window are as you would expect In this case our pbuffer clears to yellow that s what we draw into it and then we use that result as a texture on a GL QUAD drawn as shown in Figure 7 4 Many more interesting things can be done using this technique such as rendering reflection images for glass or water scenes and rendering intermediate computations for use in GPGPU applications However this sec tion deals with the infrastructure for performing the rendering and that s what we ve presented here OOO A
306. l buffer precision single Boolean enabling single buffer mode double Boolean enabling double buffer mode stereo Boolean enabling quad buffer stereo mode samples Number of multisamples to use 170 Chapter 9 The GLUT API for OpenGL Configuration Figure 9 6 GLUT Project Results Showing Visual Selection and Rendered Object for Anti Aliased Pixel Format to Example 9 2 are subtle because the only differences involve the addition of the stencil and anti aliasing The results of the anti aliasing are visible in Figure 9 6 For a much more verbose description of these flags ways to use this initialization call and more check the manual page for this call using man glutInitDisplayString Example 9 3 Initializing a GLUT Visual Using a String glutInitDisplayString stencil 2 rgb 8 double depth gt 16 samples Summary In this chapter we saw how GLUT works on the Mac and pointed out the key configuration differences from other platforms GLUT is useful for rapid pro totyping in that it lets you portably and efficiently bring up a window config ure the visual with a fair degree of specificity and draw In essence this API gets you rendering quickly although it doesn t mesh particularly well with the more native ways of integrating OpenGL drawing into a window especially for the Mac We devoted the majority of our discussion in this chapter to the minor differences between the Mac and other platforms
307. l cre ate your project set it to link properly against the Cocoa frameworks and create a sample main program from which we ll begin If you do not feel like walking through the steps or would like to see the finished product first check out the sample code from our website www macopenglbook com Open the Resources folder and double click on the MainMenu nib icon This will open the NIB file for this project in Interface Builder Now switch to Inter face Builder Table C 1 AppKit Cocoa Headers Frameworks and Overview Framework path System Library Frameworks AppKit framework Build flag framework AppKit Header include lt AppKit NSOpenGL h gt 284 Appendix C The Cocoa API for OpenGL Configuration in Leopard MainMenu nib e Gal ij fa J OO View Mode Info Search Field e 9 File s Owner First Responder Application MainMenu Window Wind N cocoa opengl xcodeproj Figure C 2 Window and NIB Ready to be Edited in Leopard Interface Builder In the MainMenu nib window double click on the Window icon and you ll see the window that will be your application window open Position and scale it as you like and you should end up with something like Figure C 2 when finished Next bring up the Library and Inspector tools both available in the Too1s menu Navigate to the Inspector icon in the Library window and drag the custom view out and into our window Position and
308. l of your full screen windowed and accelerated off screen needs With the fundamentals of GLUT described and armed with the locations in which to fully explore the frame work let s move directly into GLUT configuration Table 9 1 GLUT Headers Frameworks and Overview Framework path System Library Frameworks GLUT framework Build flag framework GLUT Header include lt GLUT glut h gt 164 Chapter 9 The GLUT API for OpenGL Configuration Configuration and Setup Configuring and using GLUT is pretty straightforward and given what we ve covered in prior chapters it should all feel somewhat familiar We ll waste no time in this section we ll just jump right into a code example and cover the only Mac specific change you ll need to be aware of for GLUT applications on the Mac Begin by going to XCode and creating a new project of type C tool as seen in Figure 9 2 We re choosing a C project just because we feel like it and prefer some C idioms rather than because GLUT requires C In fact as men tioned earlier GLUT is a C API In Figure 9 2 we create a new project in Figure 9 3 we add the GLUT frame work and in Figure 9 4 we see what the resultant framework should look like Specifically in Figure 9 3 navigate to System Library Frameworks and select GLUT framework to add to the project Now that we ve got a project we must address the first Mac specific element linking against the li
309. lar When it comes down to it you are trying to get vertices and pixels from the address space of your application to the screen for display Moving that data through the enormous state machine that is OpenGL may seem daunting at first but it s simply a matter of staying on the paths most traveled The good thing about the most traveled paths is that like any good freeway they have the best pavement and get the most attention from the road crew In this case our road crew is the Apple s OpenGL engineering team plus the driver engineers from the graphics vendors The performance of your application is one of their top priorities This chapter looks at some of the best practices to avoid common performance pitfalls of OpenGL application programming on Mac OS X 195 Axioms for Designing High Performance OpenGL Applications Before describing the individual blessed logical paths in OpenGL we thought it best to put down in black and white some mantras you may want to repeat to keep yourself on the straight and narrow Wandering into the weeds can cost you a lot of frame rate For any of these performance awareness axioms you may find it best to think to yourself If I were implementing OpenGL which performance considerations would I have to take into account when implementing this feature of the API Put bluntly OpenGL system software developers are just software developers and computer hardware is well just computer
310. larity to CGL It has the simplicity of CGL with the additional logic and entry points required to build windowed applications Software Layering The composited desktop of Mac OS X arguably provides the best user experi ence of any OS available The underpinnings of such an amazing user experi ence are necessarily more complex than conventional windowing systems This complexity manifests itself to some extent in the software layering of AGL and its related APIs see Figure 7 1 As we ve said AGL is built on top of CGL Because of the compositing interac tion of Quartz window server and drawables used as a destination for render ing in AGL applications AGL also has dependencies on the Core Graphics API Add the obvious interaction with OpenGL and you have all the pieces with which AGL interacts The AGL API lives in either your particular SDK framework path or System Library Frameworks As with other APIs linking against AGL requires specification of this framework path Similarly compiling using headers from the AGL framework requires specification of the framework Table 7 1 indicates the relevant locations for building and linking with the AGL framework AGL is an interface for Carbon applications It is incompatible with Cocoa ap plications Because AGL is built on top of CGL you may make CGL calls from an AGL application so long as you respect the distinct data structures and types for the two APIs NSGL AGL
311. latform APIs Supported on the Mac If you ve made it this far you likely have an application that you re bringing to the Mac from another platform or you want a simple low impact way of setting up an OpenGL rendering area on the Mac Either way the next two options provide ways for you to quickly get an application from another plat form running on the Mac GLUT The OpenGL Utility Toolkit GLUT is a toolkit encapsulating OpenGL setup and configuration and many other things that has existed for many years on many platforms GLUT provides hooks for easily setting up a window draw ing to it capturing input device data such as mouse and keyboard events and even some extra goodies such as basic 3D shape rendering GLUT also runs on just about any platform you can think of and if it doesn t the source code is available so you can make it run there So far so good However while GLUT is great for getting an application up and running it s most useful as a test bed or demonstration system as it provides a lot of functionality but doesn t integrate so seamlessly with other native win dow elements on most platforms Nevertheless because of GLUT s simplicity and portability it s very easy to find GLUT based code examples that compile and run on the Mac In fact Apple ships a set of GLUT examples in its developer tools When should you use GLUT If you re developing some code that you need to run on many platforms but that doesn t re
312. le to a list of graphics devices and the number of devices respectively Specifying NULL as the list indicates that all devices should be searched for matching visuals In this example that s what we ll do and see what we get back The aglChoosePixelFormat call will Pixel Format and Context 93 return an opaque handle that describes one or many pixel formats supported by the devices and attribute combination in the call If this were production code you d want to ensure that the returned pixel format results were valid and if they were not check for other pixel formats that would better meet your needs If a variety of pixel formats met the criteria you specified you will want to call aglNextPixelFormat to cycle through the pixel formats in the return value and then examine each of those options using ag1DescribePixelFormat to see which characteristics each has and if any of them are particularly well suited to your needs One final note on pixel format specification and selection A variety of AGL functions can generate verbose errors much like OpenGL does through its glGetError mechanism You should look at Apple s reference documenta tion to see which calls can generate these errors and to learn when to query them using ag1GetError So what are all the tokens that you can specify in conjunction with ag1Choose PixelFormat There are quite a few and the Apple documentation describes them reasonably well We include ou
313. lease of 17t renderer support 12t tokens and extensions 259 60 260t Trace view 231 32 232f U unidirectional data flow 199 200 Unix core 33 user experience on Mac 2 V VAR extension see Vertex Array Range extension VBOs see vertex buffer objects VBOs vendor extensions 8 version information access 14 vertex array objects 214 15 Vertex Array Range extension 215 20 vertex arrays 10t 205 7 211 12 vertex buffer objects VBOs 212 15 220 21 vertex data handling 210 21 vertex data processing 26 vertex shaders 200 201 vertex submission 210 21 video editing limitations 27 video memory 30 31 virtual desktops 19 virtual screen management 83 84 VRAM see video memory Ww window management in GLUT 169 169t windowed application in AGL 101 4 windowing systems consistency between 15 data structure of 15 16 X X11 15 49 277 79 X11 APIs 277 79 X11 color models 279 XCode 3 OpenGL Titles from Addison Wesley ww OpenGL Programming Guide Sixth OpenGL Programming Guide Sixth Edition The Official Guide to Learning OpenGL Version 2 1 OpenGL Architecture Review Board Dave Shreiner Mason Woo Jackie Neider and Tom Davis 0 321 48100 3 OpenGL Programming Guide Sixth Edition provides definitive comprehensive information on OpenGL and the OpenGL Utility Library This sixth edition of the best selling red book describes the latest features of
314. ll discuss which graphics and OpenGL pieces have changed and been added in various versions of Mac OS X since 10 0 We ll also explore the compatibility of the various OpenGL drivers and hardware and introduce some ideas that will help you manage the evolution of OpenGL hardware and software 10 0 through 10 1 In the beginning there was 10 0 It was released in March 2001 and lo it was good But slow But good Versions 10 0 and 10 1 were Apple s first releases of Mac OS X and represented substantial leaps forward in architecture and design from OS 9 and earlier In their first versions however they had rough spots and were not entirely complete Because of the rapid evolution of the early OS X versions OpenGL also evolved a lot in these early versions Some would ar gue that Mac OS X wasn t really usable until 10 2 others would insist that the OpenGL implementation really firmed up around 10 3 and so on We re not taking sides in that particular flamewar so we ll focus our discussions on where things are today and what you need to know to develop applications for the future At the time of the writing of this book considering targeting OpenGL applications for versions 10 0 and 10 1 is really a bad idea These versions and their OpenGL implementations are so old as to be utterly obsoleted by later 245 versions They served their purpose well at the time and we appreciate their efforts but time marches on and so do we 10 2
315. ll find this information important for linking but probably even more crucial when you want to browse headers Table 5 1 summarizes the APIs short names nicknames and framework paths discussed in this section Note that all frameworks are relative to System Library Frameworks the standard Apple framework path Table 5 1 API and Framework Locations Function Long Name Prefix Nickname Framework Path Cocoa NS AppKit AppKit framework Carbon AGL AGL framework Core OpenGL CGL OpenGL framework CoreGraphics CG ApplicationServices framework 50 Chapter 5 OpenGL Configuration and Integration Sharing OpenGL Data Between Contexts To conserve VRAM and bandwidth throughout the system it is a good idea to share data across contexts whenever possible Sharing resources across contexts is one of the most commonly discussed topics in the OpenGL ARB and with good reason Sharing falls under the purview of the windowing system inter face to OpenGL These shared resources are created managed and destroyed by OpenGL ARB members in a sense represent different windowing systems be cause they come from IHVs and ISVs that are working with different platforms The convergence of all this information makes this one hot topic for debate When ARB members meet to discuss the sharing of objects across contexts in OpenGL the GLX specification is often at the center of that discussion Because these design discus
316. lled in the system cannot Thus in many cases even older Macs have rela tively modern versions of OpenGL running on them However this also means that you may want to test the performance of crucial graphics features of your application perhaps the more modern features on a variety of Macs to ensure they meet your performance needs Software developers for OpenGL on the Mac OS don t have the luxury of writ ing applications that will function on only graphics cards from a single graphics 14 Chapter 2 OpenGL Architecture on OS X vendor Fortunately the additional burden of communicating with different de vices is largely shouldered by the implementation of OpenGL on the Mac OS At the same time the decision to tailor an application for peak performance or the cutting edge frequently requires reliance on features of specific graphics cards The choice to specialize is a decision that lies in the hands of the devel oper and must always be weighed against the size of the customer base that will use the application and have the graphics devices so targeted We ll explore in Chapter 13 how to take advantage of specific extensions for either performance reasons or feature enhancements The architecture of OpenGL on Mac OS also provides developers with a degree of consistency between the two windowing systems available to Mac users Quartz and X11 Under either windowing system the Mac OS OpenGL implementation can support multiple heterogene
317. lloc 10016 memory allocation y kCGLBadConnection 10017 CoreGraphics connection CGLError Pixel Format Selection A pixel format is simply a set of attribute value pairs that describe the de sired configuration for the framebuffer All graphics hardware has limitations in terms of the allowable framebuffer configurations it supports For instance a specific video card may support an RGBA 8 bits per component double buffered pixel format but it may not support an RGBA 12 bits per component double buffered pixel format Because of these differences pixel format APIs Pixel Format Selection 57 such as CGL provide a selection mechanism that attempts to match a set of re quested attributes as closely as the underlying renderer can support The CGL pixel format API consists of three entry points for creating querying and destroying pixels CGLChoosePixelFormat CGLDescribePixelFormat CGLDestroyPixelFormat CGLChoosePixelFormat CGLChoosePixelFormat creates a pixel format using a NULL terminated mixed array of attributes and if applicable the attribute s value Let s look at Example 6 1 which shows how to create a simple pixel format before we dive into the details of all the possible pixel format attributes Example 6 1 CGLChoosePixelFormat Usage include lt OpenGL CGLTypes h gt CGLPixelFormatAttribute attribs kCGLPFADoubleBuffer kCGLPFAColorSize 247 kCGLPFADepthSize 16 kCGLP
318. location of the application window where your drawing occurs Consider what would happen if in a desktop system with an ATI and NVIDIA card installed and the OpenGL rendering window residing on a display connected to the ATI card calls to CGLSetVirtualScreen change the NVIDIA renderer Because the window location is not updated with this call and because OpenGL commands and rasterization occur on the NVIDIA hardware the results of rendering must be propagated by the Mac OpenGL implementation from the backing store re served for the NVIDIA hardware the framebuffer to that of the ATI hardware for display As a consequence the rendering takes place on the NVIDIA hard ware and the results are copied to the ATI hardware The copying of framebuffer bits from the backing store of one device to the back ing store of another device will have major consequences for applications that are performance sensitive Use care when explicitly setting the virtual screen configuration Tf it is so costly why would an application ever do an explicit virtual screen change you may ask In the event that one renderer is more capable than an other yet you need to see the results of the more capable renderer on a less capable device explicit setting of the virtual screen may be the way to go A good example of this configuration is when you have one hardware device that is capable of doing hardware shaders and another device that is not Consider an applic
319. mber of either the major minor or major minor sub style Additional fields are optional after this first one GL_EXTENSIONS Extensions available on this platform The list is space delimited accepts the tokens defined in Table 12 1 and can be used to get the results for the renderer and version these results when combined uniquely define a tar get OpenGL graphics environment Keep in mind that as with any OpenGL call you must invoke this query only from an active context So what are some results for this command A sampling of a few graphics cards in our possession yielded strings like these e 1 5 ATI 1 4 18 e 1 1 APPLE 1 These strings can easily be parsed for extraction of the OpenGL version num ber and therefore for checking of baseline functionality as seen in Chapter 13 But the entirety of the string version and renderer label completely define an OpenGL platform On the Mac it means that we re using a specific code path within a renderer This is a useful piece of information to know not only when filing bugs but also when fixing them in your own code You can check this string at runtime If some particular well known problem exists in that renderer you can then avoid that rendering path Mac OS Version Identification We ve seen how to query our OpenGL environment to determine its platform now what about a particular version of the Mac OS itself Can we determine its version a
320. merly achieved through multiple passes through fixed function hardware and very costly read backs can now be done simply in different shaders There are two shader types in OpenGL fragment and vertex Obviously there are typically far more fragments in a scene that there are vertices In many cases a visual effect can be achieved using a vertex program yet a fragment program is used instead Successfully using a vertex program to replace a fragment pro gram effect can have a profound impact on your application s performance 200 Chapter 11 Performance Shader Instruction Limits At present we re still relatively early in the shader evolutionary chain Much of the graphics hardware in circulation places limits on the number of shader instructions supported If those limits are exceeded your application could very unpleasantly find itself on a software rendering path Mac OS X has CGL parameters available to allow you to query this unfortunate condition as shown in Example 11 1 Example 11 1 Querying Shader Limits GLint gpuVertexProcessing gpuFragmentProcessing CGLGet Parameter CGLGetCurrentContext kCGLCPGPUVertexProcessing amp gpuVertexProcessing CGLGet Parameter CGLGetCurrentContext kCGLCPGPUFragmentProcessing amp gpuFragmentProcessing Remember that when setting up your pixel format at OpenGL context creation time you can set kKCGLPFANoRecovery or its Cocoa and AGL analogs to avoid falling back to s
321. mmensely useful Adding or deleting applications 228 Chapter 11 Performance Volumes Data projects pleasts Volumes Data projects pleasc Volumes Data projects pleas a Volumes Data projects pleasi M Figure 11 2 OpenGL Profiler Main Window with Launch Settings Open from the launchable list is done using the plus and minus icons If you select the Attach to application option the launchable application list will switch to a list of currently running processes that are candidates for being attached to Now let s go through the Views menu in Profiler which is where we find the substance of the application Breakpoints View From the authors perspective the Breakpoints view is the mothership of all views Figure 11 3 It is here that OpenGL Profiler steps out of the realm of being a mere analysis tool and becomes a full fledged debugger The power of Profiler is realized when the Breakpoints view is used in conjunction with the other views to refine logical or performance problems in your application First things first What s the worst thing about OpenGL error state management from a developer s perspective If you answered this question the way many others do you said You can t tell where the error occurs without instrument ing the code with g1GetError calls The Breakpoints view allows you to break on a GL error When one occurs you get a stack trace and the precise GL function that genera
322. mple C 16 Cocoa drawRect Routine for Copy to Texture Rendering void drawRect NSRect rect setup and render the scene self drawIntermediateContents copy it to a texture glBindTexture GL TEXTURE 2D textureID glCopyTexSubImage2D GL TEXTURE 2D 0 0 0 0 0 64 64 render final scene self drawFinalContents complete rendering amp swap glFlush self openGLContext flushBuffer Notice two things in Example C 16 First our draw routines are the same as the FBO example so we won t present them again The first method draws the stuff to be used as a texture and the second draws the scene using the texture gen erated from the first method Second there is no binding or other redirection of where this routine renders Instead we do all of the rendering in the back buffer and then copy it to a texture This approach has one important implication This technique really works only for double buffered visuals Another consequence of the way this technique works is that we re actually copying the contents of the back buffer to a texture so performance may be less than that in the FBO case Specifically we perform this copy between each of the self draw methods Thus performance is likely to be slower than in the FBO case but there s a lot of bandwidth available in modern graphics hardware so if you can spare it this technique will be pretty efficient But the reason we re explai
323. n expensive operation used to switch between the window and the pbuffer drawables An application must cre ate one pbuffer per renderable texture in order to portably use GL ARB render texture An application must maintain at least one GL context per texture format because each context can operate on only a single pixel format or FBConfig All of these characteristics make GL ARB render texture both inefficient and cumbersome to use GL EXT framebuffer object on the other hand is both sim pler to use and more efficient than GL ARB render texture The GL EXT framebuffer object API is contained wholly within the GL API and has no non portable window system components Under GL EXT framebuffer object it is not necessary to create a second GL context when rendering to a texture image whose format differs from that of the window Finally unlike the pbuffers of GL ARB render texture by changing color attachments a single framebuffer object can facilitate rendering to an unlimited number of texture objects mediate rendering and look at code to do so as well The overall algorithm for using FBOs is straightforward 1 2 3 4 We ll begin by revisiting our old standby Cocoa example and extending it to configure and render to an FBO We will then use those results on our final rendered object Example 8 10 shows our custom view header which indicates Build and initialize the target object to be used with this FBO This obj
324. n fact it simplifies your life substantially because you don t have to care about the fastest way to read and subload images from a movie Please download and examine this example for details It s a little bit complex to set up but once the infra structure is in place it s fast and easy 192 Chapter 10 API Interoperability Summary In this chapter we saw how to read and write QuickTime movies interfac ing their content with OpenGL To do so we relied on previously introduced techniques for downloading textures manipulating NSImages and perform ing basic OpenGL configuration You should now have a solid idea about how to use any form of video content accessible via QuickTime with your OpenGL application QuickTime 193 This page intentionally left blank Chapter 11 Performance Overview Performance tuning your OpenGL application for OS X may well be the most satisfying part of your project No other platform can compare with OS X s great set of performance tools especially for OpenGL based applications Because OpenGL is a first class citizen on OS X the implementation and tools have been given years of scrutiny and improvements to make your optimization process dare we say enjoyable Because the implementers of OpenGL and indeed other 3D graphics APIs face the same performance challenges the strategy for writing an application that performs well using those APIs is often the same or at very least simi
325. n on another machine for example a desk top that has an NVIDIA part To qualify your bug a step further and if you have the machines at your dis posal you can test your application on different GPU cores from the same graphics hardware vendor By and large if you ve tested your application on one GPU core from a specific vendor you re going to get the same results on other GPUs that use the same core When filing bugs it s imperative that you ve verified that your application is not relying on undefined behavior Apple sees many bug reports filed where a developer has written code that depends on OpenGL behavior that is explicitly declared as undefined in the OpenGL specification When behavior is specified to be undefined all bets are off You truly don t know what you re going to get for a rendering and Apple isn t going to be able to fix your problem Finding Verifying and Filing Bugs 39 Perhaps even more common than bugs filed where applications rely on unde fined behavior are bugs filed that state Application X runs on OS 10 x y but not on OS 10 x z where z is a later revision than y From a developer s perspective this can feel like a certainty that there is a bug in OS 10 x z This may well be the case but consider this The Mac OS OpenGL implementation gets stricter in its compliance with the OpenGL specification and arguably better with each release If an application begins to misbehave after a software upd
326. n on the Mac With a collaborative effort you ll get great results If you re inclined to file an OpenGL bug here are a few tips to support your report First check the GL error state when you re finished rendering a frame You can do so by adding the code to your application and recompiling or even easier use the OpenGL Profiler application to break on OpenGL errors for you You can simply open the breakpoint view and check the Break on Error op tion Your goal in this step is to ensure that you re not causing an OpenGL error That is you re trying to validate that the bug actually lies in the rendering not in your usage of OpenGL The next step you can take to provide fortifying data for a bug re port is to try the new software renderer You do so by selecting the kCGLRendererGenericFloatID as your renderer ID See Chapters 6 7 and 8 for more information on choosing different renderers Once you ve chosen the software renderer compare the results you got when rendering with the hardware renderer you were using If the results are the same the problem most likely lies in your software rather than in Apple s If they re different Apple will want to know about it You can also try your application out on different cards from different vendors to fortify your bug report In particular you may want to test your application on one machine say a laptop with an ATI part and then compare the re sults with running your applicatio
327. n pointers and use them later Example 13 5 Storage for the Discovered Symbols interface MyOpenGLView NSOpenGLView bool hasShader float time float angle GLhandleARB vShader fShader programObject GLhandleARB myglCreateShaderObjectARB GLenum void myglShaderSourceARB void myglCompileShaderARB GLhandleARB myglCreateProgramObjectARB void myglAttachObjectARB void myglLinkProgramARB void myglUseProgramObjectARB 266 Chapter 13 OpenGL Extensions BOOL resolveShaderSymbols BOOL hasExtension NSString ext inExtensions NSArray exts BOOL hasShaderExtensions float openGLVersionNumber void angleUpdate NSTimer tt void reshape end Example 13 6 Opening a Segment for Symbol Lookup void resolveSymbol char symname void lib dlopen void sym dlsym dlclose lib return sym lib symname Example 13 7 Looking Up Symbols BOOL resolveShaderSymbols CreateShaderObjectARB resolveSymbol glCreateShaderObjectARB ShaderSourceARB resolveSymbol glShaderSourceARB CompileShaderARB resolveSymbol glCompileShaderARB myg1 myg1 myg1 myglCreateProgramObjectARB resolveSymbol glCreateProgramObjectARB myglAttachObjectARB resolveSymbol glAttachObjectARB myglLinkProgramARB resolveSymbol glLinkProgramARB myglUseProgramObjectARB resolveSymbol glUs
328. name this custom view Now go back to MainMenu and drag from the Library a custom Object into the MainMenu window In the Inspector change its Class name to that of the custom view from the last step As before we must create headers and code From the File menu Write Class Files and then import those files by dragging them to your XCode project NSView 295 With that configuration out of the way we move straight into the code phase Save your MainMenu nib and switch to XCode As before with the NSOpenGLView derived project we ll do many of the same things includ ing creating a pixel format and creating a subclassed version of drawRect We ll also mimic some of the infrastructure automatically provided in NSOpenGLView so you can see how it does its work This time around we ll present all the code in the final versions of both the header file Example C 3 and the source file Example C 4 first and then walk you through each Example C 3 Myview h Final Header import lt Cocoa Cocoa h gt interface MyView NSView private NSOpenGLContext _context NSOpenGLPixelFormat _pixelformat NSOpenGLContext openGLContext void prepareOpenGL end We begin by looking at the MyView h header We ve inserted both a few mem ber variables and a few methods We ve also created member variables to store pointers to our context and to our pixel format we ll create code to initialize these variables in the so
329. nd in the Headers directory of the OpenGL framework direc tory Commonly used CGL headers include CGLTypes h CGLRenderers h and CGLMacros h We ll talk more about these headers in this chapter Error Handling CGL error handling is based on the values returned from each of the CGL func tions All CGL functions return 0 when successful Upon failure a number of different return values may be returned that describe the nature of the failure The full list of possible error values is part of the CGLError enum and can be found in System Libraries Frameworks OpenGL framework Headers CGLTypes h Error return values from CGLGetError uA typedef enum CGLError kCGLNoError D no error invalid kCGLBadAttribute 10000 pixel format attribute kCGLBadProperty 10001 renderer property y kCGLBadPixelFormat 10002 pixel format kCGLBadRendererInfo 10003 renderer info T kCGLBadContext 10004 context kCGLBadDrawable 10005 drawable kCGLBadDisplay 10006 graphics device ati kCGLBadState 10007 context state wf kCGLBadValue 10008 numerical value 7 kCGLBadMatch 10009 share context J kCGLBadEnumeration 10010 enumerant A kCGLBadOffScreen 10011 offscreen drawable rA kCGLBadFullScreen 10012 offscreen drawable x kCGLBadWindow 10013 window kCGLBadAddress 10014 pointer ey kCGLBadCodeModule 10015 code module y kCGLBadA
330. nd when it is appropriate to use for functionality queries and testing Turns out that there s a Carbon method that s been around since time immemo rial for exactly this purpose This method can tell you a lot of information on a Mac OS Version Identification 249 lot of aspects of your running Mac system but we ll use it for just the version number here That Carbon call is Gestalt It has been said that brevity is the soul of wit so we may therefore assume that the documentation of what the Gestalt method does is among the wittiest on the Mac The documentation pages say that Gestalt obtains information about the operating environment Now that s just the overview to the function but really all Gestalt does is return information about your Mac environment There is copious documentation on the zillions of queries that it can perform but our token to query is gestaltSystemVersion This query returns a 1ong value with a hexadecimal representation of the Mac version Note however that this value encodes the version in a somewhat stylized form which is not directly usable as a value For example the return value for this function on Mac OS X 10 3 1 would be 0x1031 and on 10 4 4 would be 0x1044 We coded a quick little version in Example 12 1 which unpacks the major in 10 X Y the X value and the minor in 10 X Y the Y value and returns the raw result To use this function in your own application make sure you include the CarbonCar
331. ndant data transfer limits your potential rendering performance to the bandwidth of the graphics bus and in some cases the performance of the CPU and the host memory system as it manages state changes and state synchronization with the graphics device We do advocate one habit namely retained mode rendering Retained mode rendering refers to any rendering that depends on a state that was established at some time and then referenced for rendering at some time in the future The first retained mode rendering in OpenGL consisted of display lists but additional modes of this style of rendering have been added to OpenGL with nearly every major release since display lists were introduced A big part of the retention in retained mode rendering for modern computers is in keeping data and state resident on the graphics adapter This residency avoids all the travel time by bus between the computer s CPU and the GPU of the graphics adapter Here are the primary mechanisms for retained mode rendering in OpenGL e Display lists e Texture objects e Buffer objects vertex and pixel e Shader objects e Pixel buffer objects e Framebuffer objects The advantage of using retained mode rendering is that it allows you to get as close as possible to the theoretical bandwidth limits between the GPU and VRAM eliminating as much correspondence with the CPU as possible If you ve seen the theoretical bandwidth numbers for today s modern graphi
332. ndered object Example C 10 shows our custom view header which indicates where we ll store our texture object and FBO IDs Example C 10 Custom View Header for FBO Example Code import lt Cocoa Cocoa h gt import lt OpenGL OpenGL h gt interface MyOpenGLView NSOpenGLView GLuint fboID GLuint textureID float time float angle void angleUpdate NSTimer tt void reshape end We next look at the code in our prepareOpenGL method As before this is the place where we create and initialize things that we need to set up once per context We look at the entire prepareOpenGL method in Example C 11 so essentially we see the first two phases of our outlined FBO usage build and ini tialization for both our target texture and our FBO We begin by creating and initializing a texture object which we ll both bind to our FBO and use in our final rendering We then create an FBO and bind it to that texture for color ren dering Finally after configuration we unbind our current FBO by binding the FBO ID of 0 314 Appendix C The Cocoa API for OpenGL Configuration in Leopard Example C 11 OpenGL Setup for FBO Rendering void prepareOpenGL glMatrixMode GL PROJECTION glLoadIdentity glOrtho 1 1 1 1 1 100 enable generate and bind our texture objects glEnable GL TEXTURE 2D glGenTextures GLsizei 1 amp textureID glBindTexture GL TEXTURE 2D textureID const unsigned int
333. ndowed pixelformats hw accel pixelformat double buffered pixelformat 24 bits for color channels 8 bit alpha channel 24 bit depth buffer Additional Topics 145 NSOpenGLPFAMinimumPolicy meets or exceed reqs 0 un _pixelformat NSOpenGLPixelFormat alloc initWithAttributes NSOpenGLPixelFormatAttribute attributes if _pixelformat nil NSLog SharedContext No valid OpenGL pixel format matching attributes specified at this point we d want to try different sets of pixelformat attributes until we got a match or decided we couldn t create a proper working environment for our application else _context NSOpenGLContext alloc initWithFormat _pixelformat shareContext nil return self NSOpenGLPixelFormat pixelFormat return pixelformat NSOpenGLContext context return context SharedContext instance if _sharedContext nil _sharedContext SharedContext alloc init return sharedContext end If you re familiar with the singleton pattern the instance method and idea should be familiar to you If not consult the classic Design Patterns book by the notorious Gang of Four 16 Essentially instance provides a handle to our static context manager object Upon its creation this object allocates a pixel format and a context based on that pixel format This code should look familiar 146 Chapter
334. ne at that for graphics driver writers for OS X kCGLRendererATIRagel28ID kCGLRendererATIRadeonID kCGLRendererATIRageProID kCGLRendererATIRadeon85001ID kCGLRendererATIRadeon9700ID kCGLRendererATIRadeonX10001D kCGLRendererGeForce2MXID kCGLRendererGeForce3ID kCGLRendererGeForceFXID kCGLRendererGeForce8XXXID kCGLRendererVTBladeXP2ID kCGLRendererIntel900ID kCGLRendererMesa3DFXID If you wish to restrict pixel format matching to a device specific hardware ren derer you may use the list above to do so When you ask for a specific renderer ID of this sort your software will run only on the requested hardware On other devices your pixel format selection will fail Most graphics application developers are familiar with the ATI NVIDIA and Intel graphics hardware described in the renderer ID strings above Less famil iar is the kCGLRendererVTBladeXP2IDID which corresponds to the Village Tronic hardware renderer kCGLRendererMesa3DFXID is outdated and will eventually be removed from the list of renderer IDs Context Management The CGL type CGLContextObj is the fundamental data type for an OpenGL context on the Mac CGL contexts are created as follows CGLError CGLCreateContext CGLPixelFormatObj pixelFormat CGLContextObj sharedContext CGLContextObj ctx Contexts may be duplicated with a call to CGLError CGLCopyContext CGLContextObj src CGLContextObj dst unsigned long stateMask The stateMask
335. ners of OpenGL anticipated the need to avoid duplicating resources among multiple rendering areas This anti redundancy capability is exposed at the window system level as a feature called context sharing This capability is typically requested when a new OpenGL context is created after the first rendering context has been created and used The context with items you wish to access is passed into some form of initialization for your new context usually along with a pixel format For two contexts to be compatible their pixel formats must be compatible which is why you see these two things specified together to successfully enable sharing What makes pixel formats incompatible On the Mac usually it s one thing incompatible renderers As a rule of thumb if you can choose pixel formats that use the same renderers you can share contexts created with those pixel formats Additional Topics 301 So we ve covered the how and why of sharing a context but what exactly is shared when context sharing is enabled Interestingly enough most OpenGL objects are shared but the overall context state is not That s not entirely intu itive but it correlates well with what people usually want to do You save valu able card memory by reusing heavyweight objects in multiple spots but still preserve the ability to customize each OpenGL view as needed Specifically the following entities are shared e Display lists e Vertex array objects VAOs e B
336. ng OpenGL operations This tech nique is a capable fallback for when FBOs are not available Pbuffer Off Screen and Other Intermediate Targets There exist a variety of other ways of writing intermediate rendering results for reuse in later final renderings in your OpenGL application Among these are pbuffers off screen render areas and a variety of extensions for directly rendering into textures Though many other choices are possible we faced a difficult decision when writing this book either to cover them all or to cover only a subset To free up some weekends we chose the latter option To be fair since we began this project the FBO extension has really come of age and we would recommend it without hesitation for those cases when you need intermediate rendering The other techniques that we do not cover here are all genealogical predecessors to the FBO extension and in many ways are inferior to it Specif ically off screen render areas regardless of the interface CGL AGL or Cocoa are software renderers and so have only nominal performance They should be avoided for interactive or real time applications Pbuffers are complex and un wieldy to implement Although they often perform at native hardware speeds the complexity of managing the interface is not worth the headache if you can write to a modern render target like an FBO instead The pure simplicity flexibility and generality and raw performance of what can be accom
337. ng can go wrong with this call If the pbuffer argument is NULL kCGLBadAddress will be returned Getting information about an existing pbuffer is done using CGLError CGLDescribePBuffer CGLPBufferObj obj long width long height unsigned long target unsigned long internalFormat long maxLevel Each of the pointer arguments to CGLDescribePBuf fer is used by this func tion to fill in its corresponding value The values for these parameters are fixed at the time the pbuffer was created so there should be no concerns while Drawables 79 debugging that another CGL call has altered the configuration of the pbuffer Again only a NULL pbuffer object parameter will cause CGLDescribePBuf fer to return its single possible error condition kCGLBadAddress To associate a pbuffer with a CGL context for rendering call CGLError CGLSetPBuffer CGLContextObj ctx CGLPBufferObj pbuffer unsigned long face long mipmapLevel long virtualScreen Like most APIs CGL defers as much work as it can until as late as is logically possible This is the case with the relationship between CGLCreatePBuffer and CGLSetPBuffer Despite its name CGLCreatePBuffer doesn t do nearly as much work to establish a draw able for rendering as CGLSet PBuf fer does This difference arises because you must call CGLSetPBuffer to associate it with a CGL context before render ing into it This makes sense because there is no CGL context argument to the CGL
338. ng environment and to mitigate circumstances that give rise to bugs the Mac OS OpenGL implementation has been modularized as a plug in architecture at multiple levels Figure 2 3 At the highest level the OpenGL interface is managed as a dispatch table of entry points These entry points can be changed out according to hints or other environmental factors The most common reason for changing these entry points arises when you are using CGL macros to reduce the overhead of calling into the OpenGL API itself Chapter 6 provides more discussion of CGL macros Beneath the dispatch table another plug in layer exists On OS X this is referred to as the OpenGL engine layer This logical abstraction layer is responsible for handling all of the device independent OpenGL state The OpenGL engine layer checks the error state maintains any client state required by the OpenGL spec ification and is responsible for assembling OpenGL commands into a buffer for submission to the underlying renderer By logically separating this set of functionality at the OpenGL engine layer entire OpenGL engines can be loaded or unloaded so as to most efficiently leverage the underlying CPU platform The multithreaded OpenGL engine announced at WWDC 2006 and available for Leopard is an example of a functional module that can be selected for the OpenGL engine interface Below the OpenGL engine exists another plug in architecture for loading ren derers These driver plug ins
339. ng of virtually anything running on your system If your binaries have not had their symbols stripped away and your source files are available Shark profiles can correlate perfor mance sampling values at the source and assembly levels This tool will show you the breakdown of time spent in your application time spent in system li braries and even time spent in the Mach kernel Shark is capable of sampling either PowerPC or x86 binaries and it can provide valuable information on your application s performance on those different hardware architectures Getting useful information from Shark couldn t be any easier Start your application Start Shark Click the Start button Time elapses Click the Stop button oF O Ne At this point Shark will generate a table showing sampling times for the rou tines used in your application s call stacks Using Shark is a snap in its simplest form as described above Becoming an expert on all the intricacies of Shark is another matter however Thankfully most developers merely need to scratch the surface of Shark s capabilities For those interested in more detail the Shark user manual is an excellent resource you ll find lots more information there Suffice it to say that if you are suffering a performance problem in your code Shark is the most comprehensive tool for examination and evaluation of those problems Activity Monitor Activity Monitor is useful for monitoring
340. ning this method at all is that the hardware on which you run 320 Appendix C The Cocoa API for OpenGL Configuration in Leopard potentially might not support a real off screen technique like FBO so a tech nique like render to texture may be required And that brings us to the final point This technique is window dependent You ll notice that we re copying only a fixed area of pixels from within our drawing surface in our example If we wanted to capture the entire area we d have to monitor the size of the drawable area using the reshape routine and ensure that the width and height of the copy call were updated accordingly Another way of looking at this problem is to consider texture resolution You ll need a window at least as big as the texture size you want to use because you re directly copying pixels from within it Thus if your user wants a win dow smaller than this texture size either you have to fall back to a smaller sized texture or you have to limit the window minimum size At any rate the hairy details of the bookkeeping surrounding pixel sizes are not the most fun part of this technique and constitute another way in which FBOs are a better solution In this section we ve covered how to perform textured renders from the con tents of a texture filled by another render The technique is very portable but carries some overhead concerning texture and window sizes and has some per formance limitations based on the underlyi
341. nt nec essary later both to choose a pixel format from a specific device and then to create a window on it This section also chooses the pixel format looking in particular at a specific graphics device First we find the main graphics de vice and store it in a variable we then set up a Rect defining our window size and finally we declare a handle to our window The next part of this code is familiar from our earlier full screen example that is the declaration of an AGLPixelFormat and the population of it with our desired pixel format parameters As a reminder this list must end with the AGL NONE token Finally we invoke agl1ChoosePixelFormat but in a different form than in the full screen example instead of passing it a NULL as the first argument we specify a particular device to be searched in this case our main device on the sys tem Excepting that one addition the same caveats from the full screen example apply Check the return values for validity and ensure that the resultant pixel format matches your needs The second section of the code creates the AGL context cleans up the pixel format creates a Carbon window and binds the AGL context to the window also know as an AGL drawable Creating a context is done as in our prior 1 It s probably useful to mention the two data types in AGL that are remapped from basic Carbon types for window and device management When using AGL methods that interface with devices thes
342. nt shader vertexShader glCreateShaderObjectARB GL VERTEX SHADER ARB fragmentShader glCreateShaderObjectARB GL FRAGMENT SHADER ARB glShaderSourceARB vertexShader 1 amp vertsource c NULL glShaderSourceARB fragmentShader 1 amp fragsource c NULL glCompileShaderARB vertexShader glCompileShaderARB fragmentShader programObject glCreateProgramObjectARB glAttachObjectARB programObject vertexShader glAttachObjectARB programObject fragmentShader Identification Selection Query and Usage 261 glLinkProgramARB programObject glUseProgramObjectARB programObject else error NO shading will be available endif add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES Utilization and Binding An astute reader will notice that in the prior section we just checked that the API entry points exist in headers at compile time If our OpenGL library doesn t actually export those entries we ll fail at link time or runtime with some form of unresolved symbol error That s not a good thing for a well behaved appli cation to do so how can we ensure at runtime that we ve got a valid envi ronment as defined by our OpenGL level and extensions in which to run We perform a variety of checks specifically those shown in Examples 13 2 and 13 3 T
343. ntent on using CGL only in your appli cation recommended solely as an academic exercise and not for production code your surface texturing will be limited to using pbuffers as the drawable source of the surface texture itself There are no other surface IDs obtainable through CGL See Chapter 7 for more information on surface texturing kCGLCPSurfaceOrder kCGLCPSurfaceOrder is used to control the overlay ordering of visible draw ables on the desktop A value of 1 the default orders the surface in front of existing windows A value of 1 orders the surface behind existing windows kCGLCPSurfaceOpacity kCGLCPSurfaceOpacity is used by the Quartz windowing system when compositing the drawable associated with the current context kCGLCPSurfaceOpacity is a Boolean value describing whether the surface is opaque 1 or has transparency 0 kCGLCPReclaimResources kCGLCPReclaimResources provides application writers with the flexibility to free all data allocations associated with the current context These resources include memory allocated for e Draw pixels textures used for faster drawing Display lists Texture objects Vertex buffer objects Vertex array objects e Any device specific data Because the memory is released and pointers nullified for all of these resources you should expect a slowdown in your application if you subsequently use OpenGL entry points that create modify or use the data described in the list abov
344. ntext alloc initWithFormat _pixelformat shareContext SharedContext instance context if _context nil NSLog No valid OpenGL context can be created with that pixelformat we can fail a few ways 1 bogus parameters nil pixelformat invalid sharecontext etc 2 share context uses a different Renderer than the specified pixelformat recovery techniques 1 choose a different pixelformat 2 proceed without a shared context zy return _context As you can see in Example C 7 the only changes we made from our original custom view example are to use the SharedContext instance pixelFormat accessor to create a pixel format for this view and then sim ilarly to use the SharedContext instance context accessor when constructing our context We should always of course confirm that all pixel formats and contexts are successfully created for our production code as well So add code like this to your existing code and then make one Additional Topics 307 00o Window e200 Window Figure C 10 Context Sharing Two Windows Demonstrating Common Shared Data and Unshared Clear Color Context Data last change specifically change the clear color in one of your custom View drawRect methods If everything works as planned your application should produce results like these shown in Figure C 10 Remember that the OS X OpenGL implementation follows the conventions esta
345. ntext to share but one approach that is par ticularly nice from an architectural perspective is to use an external context provider In this model we configure and create a context in a separate class and then share it with any OpenGL view that needs to render using its shared objects In our example we ll use the pattern of a singleton that is an object based wrapper around a static object This code is very straightforward so we ll present it here and then discuss a bit more after presentation The header code lives in Example C 5 and the source code is found in Example C 6 302 Appendix C The Cocoa API for OpenGL Configuration in Leopard MyOtherOpenGLvView Figure C 7 Two Views Contexts Shared Example C 5 Singleton Class Declaration for Managing a Shared Context import lt Cocoa Cocoa h gt interface SharedContext NSObject NSOpenGLPixelFormat _pixelformat NSOpenGLContext _context NSOpenGLPixelFormat pixelFormat NSOpenGLContext context SharedContext instance end Additional Topics 303 x cocoa_2win_contextshare gt a Other Sources 2 Resources 2 Frameworks ae Products gt Targets gt CJ Executables gt 9 Errors and Warnings vq Find Results gt Q Bookmarks gt SCM Project Symbols gt G Implementation Files gt f NIB Files L1 g Appkit framework Cocoa framework v cocoa 2win contextshare app cocoa 2win contextshare Prefi
346. o measure performance Defining a few metrics for performance is an essential first step Frame Rate The first metric useful in performance analysis is the frame rate The frame rate measures the number of frames per second your application displays Unlike most performance metrics the frame rate is a discrete measurement You cannot for instance have a frame rate of 12 5 frames per second FPS Metrics 207 Table 11 1 Pixel Format Buffer Selection Mode API Double Buffer Single Buffer CGL kCGLPFADoubleBuffer kCGLPFADoubleBuffer GL_TRUE GL_FALSE AGL AGL_DOUBLEBUFFER GL TRUE AGL DOUBLEBUFFER GL FALSE Cocoa NSOpenGLPFADoubleBuffer NSOpenGLPFADoubleBuffer YES NO GLUT GLUT DOUBLE GLUT SINGLE Further if your application is vertical blank synchronized your frame rate will be quantized by the refresh rate of the display device you are using For ex ample a monitor can update its contents only at a fixed rate say 60Hz for a particular monitor If your application is attempting to display results on a mon itor as fast as possible your application will never display more than 60 distinct frames per second Let s look at frame rate and monitor refresh rates in more detail See information on KCGLSwapInternal in Chapter 6 for more details on configuring your Mac OS X application to be vertical blank synchronized vbl sync d There are two basic ways of buil
347. oa API for OpenGL Configuration in Leopard Mac OS X 10 5 Cocoa also known as AppKit is the Objective C API for writing modern Mac OS X applications Cocoa provides a high level object oriented set of classes and interfaces for the OpenGL subsystem and for user interface interaction Cocoa is the modern successor to the NextStep API from NeXT Computer the company s initials explain the NS prefix on all of the class definitions and data types Cocoa provides a more object oriented API than any other option on the Mac which is useful for building UIs handling events and functioning as an interface to OpenGL We presume you re reading this appendix with a fundamental understanding of the Objective C language and basic Cocoa so we won t spend any time review ing core Cocoa concepts like the Objective C language views actions outlets Interface Builder and so on We also assume you ve already read one of the many good books on these key background elements of Cocoa If not we ve got a reference or two for you in Appendix D In the following sections we ll ex plore two ways of creating a Cocoa based application one that relies heavily on Interface Builder and one that requires more code but yields a bit more flexibil ity and capability We ll also tackle some advanced OpenGL topics concerning off screen rendering context sharing and more This appendix is a repeat of the earlier chapter focused on Cocoa and OpenGL but wi
348. ode and release the display CGReleaseAllDisplays return error For simplicity we use the global form of display capture that is the form in which all displays are captured You may have a need or a preference to control which display you capture more precisely For those circumstances Apple pro vides CGDisplayCapture and CGDisplayRelease to specify a particular display And that s really all there is for display capture as it relates to OpenGL except for the event handling part which we ll discuss next Event Handling One key caveat to full screen windows regardless of the amount of OpenGL window system integration relates to event handling Who s handling the events now that your window system and UI elements are hidden Yes Virginia this is another headache of full screen windows but you ve got to do it Otherwise nothing will be handling events making it very difficult to even quit your application So what s an application to do especially in Cocoa As we do a number of times throughout the book we will not go into the details of this operation as numerous Cocoa books deal with this topic Here we simply present Example C 9 in which code modeled closely on an Apple source exam ple shows what you might do with events while you re in a full screen mode 310 Appendix C The Cocoa API for OpenGL Configuration in Leopard Example C 9 Custom Controller Event Handling Loop in a Full Screen Context
349. of the methods Pbuffers Pixel buffers are another alternative rendering destination commonly used for off screen rendering However unlike the named off screen areas pbuffers can be fully hardware accelerated That makes them quite useful for real time generation of textures among other things Pbuffers are an invention of the late 1990s circa 1997 and though fully functional they contain a bit of complexity that more modern render implementations such as framebuffer objects do not In essence pbuffers are useful analogs to framebuffer objects but for modern code framebuffer objects are preferred Table 7 4 shows the list of functions within AGL useful for creation and use of pbuffers Chapter 6 showed the same procedure necessary for this task so we ll simply summarize and show some example code here The basic process is as before Create a pbuffer ag1CreatePBuf fer make it active ag1 Set PBuffer and perform some rendering into it Example 7 8 demonstrates the main loop per forming the basic AGL context and AGL pbuffer context creation tasks Table 7 4 AGL Pbuffer Functions Function Description aglCreatePBuffer Creates an AGL pixel buffer for use with an OpenGL texture type aglDestroyPBuffer Destroy an AGL pixelbuffer aglDescribePBuffer Gather information about an AGL pixelbuffer aglGetPBuffer Query a context for the pixelbuffer attached to it aglSetPBuffer Set the pixel buffer to be th
350. oftware paths This would obviate the need to check for hardware shader support but also has a small problem your application may simply not launch on some systems There is no mechanism at present to allow querying for the number of instruc tions supported by a given GPU The general rule of thumb is that if you re targeting lower end GPUs for your application write your shaders with in struction count conservation in mind and use the methods in Example 11 1 to empirically test your application on specific configurations OpenGL for Mac OS X Rules of Thumb for Performance With the disclaimer that some of the ideas presented in this section may be ap plicable to any platform we ll proceed with some Mac based rules of thumb The OS X OpenGL implementation has some distinguishing features relative to other platforms Taking advantage of some of these features will likely make a profound difference in the performance of your application Minimize Data Copies To maintain compliance with the OpenGL specification OpenGL implementa tions often need to make copies of submitted vertex and pixel data and OpenGL on OS X is no exception This necessity arises from needing to return control to an OpenGL application after data has been submitted yet not needing to yet OpenGL for Mac OS X Rules of Thumb for Performance 201 submit that data for rendering Consider as a simple example what happens when glVertex3f is called between a glBe
351. oing to render and copy into a texture that s the extent of the information we need to keep track of throughout our methods Because cre ation of textures is so universal we present the initialization and draw code all at once in Example 7 10 This code shows three things the overall initialization the draw methods for both the textured scene and the texture itself Example 7 10 AGL OpenGL Initialization and Draw Functions for Copy Texture Rendering void initGLstate t lMatrixMode GL PROJECTION ILoadIdentity lOrtho 0 0 1 0 0 0 1 0 1 0 1 0 IClearColor 0 0 0 5 0 8 1 0 Q Q QQ enable generate and bind our texture objects IEnable GL TEXTURE 2D lGenTextures GLsizei 1 amp textureID IBindTexture GL TEXTURE 2D textureID const unsigned int texdim 64 const unsigned int nbytes 3 char data texdim texdim nbytes memset data Oxff texdim texdim nbytes unsigned int ii Q Qu for ii 0 ii texdim texdim ii data ii nbytes 0 Oxff 114 Chapter 7 The AGL API for OpenGL Configuration gluBuild2DMipmaps GL_TEXTURE_2D 0 GL_RGB texdim texdim 0 GL_RGB GL_UNSIGNED_BYTE data glTexEnvf GL TEXTURE ENV GL TEXTURE ENV MODE GL REPLACE glBindTexture GL TEXTURE 2D 0 unbind texture void drawTexture glClearColor 1 0 1 0 0 0 1 0 glClear GL_COLOR_BUFFER_BIT GL DEPTH BUFFER BIT glBindTexture GL T
352. ok performed heroic feats of editing and have made this book much better for their efforts Many thanks go to Dave Shreiner Paul Martz Thomas True Terry Welsh Alan Commike Michel Castejon and Jeremy Sandmel Thanks too to the many other friends and relatives who contributed ideas en couragement and support Finally the authors would like to individually thank a few people J D s Acknowledgments I cannot fully express my gratitude for the support of my wife Samantha She has been with me for the duration of this challenging project and always responded to the rough patches with compassion and a smile I also wanted to extend a special thanks to my friend Alex Eddy who reviewed this material with unmatched expertise on the subject matter of the current OS X OpenGL implementation its history and its incarnations Finally I wanted to thank my parents Andrew and Sue who never wavered in their support of my education and career From their visionary gift in 1979 of a Timex Sinclair computer that started me down the road to software develop ment to the present day they have always been at my side Bob s Acknowledgments Thanks very much to my wife Kim for her support encouragement and love She s been my muse and a voice of reason throughout the often arduous pro cess of shepherding a book from inception to publishing I d also like to thank my parents for getting me raised well and without major injury and for main
353. olor We ll get into these performance implications later and explore issues like this one in more detail For now just realize that a good rule of thumb for choosing pixel formats is to choose the one that most closely matches your application s needs Example 8 1 Configuration of an OpenGL View in initWithFrame include lt OpenGL gl h gt include lt GLUT glut h gt NSOpenGLView 127 include lt math h gt import MyOpenGLView h implementation MyOpenGLView id initWithFrame NSRect frame time 0 angle 0 GLuint attributes NSOpenGLPFAWindow choose among pixelformats capable of rendering to windows NSOpenGLPFAAccelerated require hardware accelerated pixelformat NSOpenGLPFADoubleBuffer require double buffered pixelformat NSOpenGLPFAColorSize 24 require 24 bits for color channels NSOpenGLPFAAlphaSize 8 require an 8 bit alpha channel NSOpenGLPFADepthSize 24 require a 24 bit depth buffer NSOpenGLPFAMinimumPolicy select a pixelformat which meets or exceeds these requirements 0 NSOpenGLPixelFormat pixelformat NSOpenGLPixelFormat alloc initWithAttributes NSOpenGLPixelFormatAttribute attributes if pixelformat nil NSLog No valid OpenGL pixel format NSLog matches the attributes specified at this point we d want to try different sets of pixelformat attributes until we got a match or decide we couldn t cre
354. on we made clear some of the complexity that is extension and version management in OpenGL and we offered advice on some ways to manage that complexity All of the express ways of managing extensions from preprocessor token checks to dynamic symbol loading and executing are per fectly fine for managing extensions In fact if you re using only a few extensions manually checking for them may be the easiest way to get up and running as our example has shown However if you write a large application and use a va riety of extensions you ll eventually end up writing a lot of code just to manage extensions At that point you might start to wonder why you bothered in the first place because you re spending a lot of time writing infrastructure and not a lot of time writing the next Killer App Fortunately a variety of people over the years have encountered this same OpenGL extension management issue and decided to do something about it In this section we ll present two toolkits with capability for extension man agement GLUT and an open source project called the GL Extension Wrangler GLEW GLEW and GLUT both wrap up the techniques we ve discussed ear lier not just for the Mac but on a variety of platforms Both are a great way to get up and running with extensions to OpenGL without writing the infrastructure yourself Other choices are also available out there in the wilds as every few years someone else decides to take a crack at writin
355. onlineDisplayArray CGDisplayCount onlineDisplay ReturnCount 70 Chapter 6 The CGL API for OpenGL Configuration CGGetOnlineDisplayList will return active displays mirrored displays and sleeping displays To distinguish this function from CGGetActiveDis playList mirrored displays may or may not be drawable and sleeping displays are not drawable Display IDs can also be obtained based on spatial parameters CGGetDisplaysWithPoint CGPoint point CGDisplayCount displayArraySize CGDirectDisplayID displayArray CGDisplayCount displayReturnCount CGGetDisplaysWithRect CGRect rect CGDisplayCount displayArraySize CGDirectDisplayID displayArray CGDisplayCount displayReturnCount In the point case the display list will contain a single display in extended desk top mode In mirrored mode the display list may contain multiple displays that encompass the same point In the rect case the display list returned will be all displays intersected by the specified rectangle and behaves as the point case does for mirrored mode Step 2 Obtaining an OpenGL Display Mask from a Display ID The second step in the process of obtaining renderer information is to obtain an OpenGL display mask This step is a simple matter of calling CGOpenGLDisplayMask CGDisplayIDToOpenGLDisplayMask CGDirectDisplayID display This function is invertible if you will by calling CGOpenGLDisplayMask ToDisplayID or CGGetDisplaysWithOpenGLDispla
356. ooking for more almost seems greedy but let s in dulge Figure 11 16 shows the profile of ptm4 The great thing about Profiler is the number of surprises it can uncover in your software We ve heard innumerable times I didn t even know I was calling that Often the revelations are more subtle In this case glReadPixels has made its way to the top of the list Fortunately there are ways to address this problem Please Tune Me 5 To subdue the g1ReadPixels problem ptm5 introduces pixel buffer objects not to be confused with pbuffers Pixel buffer objects PBOs can be used as Putting It All Together 241 C Statistics o Save As Text Clear GL Function of Calls Total Time usec Avg Time usec 9 GL Time App Time glReadPixels 942 21701008 23037 16 70 77 66 37 0 glEvalMesh2 30 112 6403438 212 65 20 88 19 58 glTexSublmage2D 941 1218914 1295 34 3 98 3 73 CGLFlushDrawable 943 503004 533 41 1 64 1 54 glCallList 942 468730 497 59 1 53 1 43 glTeximage2D 2 121243 60621 93 0 40 0 37 glBitmap 9 410 54952 5 84 0 18 0 17 glTexCoord2f 323 208 34893 0 11 0 11 0 11 Total elapsed GL function time 30663673 59 usec Estimated time in GL 93 78 Show slice lt 25 of 25 gt Context ID All Contexts Figure 11 16 ptm4 OpenGL Statistics retained mode containers of pixel or texture data which can then be sourced for rendering by texturing calls or g1DrawPixels In this case we ve established the PBO as a
357. or interoperability example with QTMovie initialization code First the code see Example 10 9 and then a discussion Example 10 9 Initialize QTMovie void prepareOpenGL glMatrixMode GL PROJECTION glLoadIdentity glOrtho 1 1 1 1 1 100 open and configure our movie movie QTMovie movieWithFile tmp Sample mov error nil NSLog Sd n movie if movie nil movie retain movie play configure texture environment 1 We ve said it before and we ll say it again This is not the optimal technique for high performance movie playback in OpenGL on the Mac There are other specialized APIs that enable full rate play back of movies as textures within OpenGL It just so happens that they re pretty complex to set up and get running but at the end of the day the usage in your actual run loop is pretty similar That s what we are trying to demonstrate here If you are interested in the highest performance tech niques see CoreVideo in Apple s documentation or check our website www macopenglbook com for updates 186 Chapter 10 API Interoperability glTexEnvf GL TEXTURE ENV GL TEXTURE ENV MODE GL REPLACE glEnable GL TEXTURE 2D add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES QTMovie is an API with a lot of entry points The
358. or kCGLPFAAccumSize is specified with a non zero value then the largest possible corresponding buffer size will be chosen for your pixel format object kCGLPFAClosestPolicy is applicable to only the color buffer size attribute kCGLPFAColorSize it does not consider the size specified for the depth or accumulation buffers With this attribute the color buffer size of the returned pixel format object will most closely match the requested size This policy is most similar to the behavior that the X11 window system uses when choosing visuals As you may have gathered by now kCGLPFAMinimumPolicy is the de fault policy for buffer sizing Also notice that neither of the nondefault poli cies KCGLPFAMaximumPolicy and kCGLPFAClosestPolicy is applicable to the kCGLPFAAlphaSize or kCGLPFAStencilSize attribute Apply a little deductive reasoning and we have a new rule The pixel format matching semantics for kCGLPFAAlphaSize and kCGLPFAStencilSize follow the kCGLPFAMinimumPolicy behavior only Render Targets You may have noticed when running a game or other full screen application that only the primary display the display with the Apple menu bar is cap tured for the full screen application The reason for this is that full screen ren dering is supported only with a single renderer on the Mac OS Therefore if you include the kCGLPFAFullScreen attribute to qualify your pixel format only renderers capable of supporting full screen rendering
359. or you Cocoa OpenGL Cocoa is the hip newer and remarkably powerful user interface API on the Mac as anyone following the Mac scene since OS X knows If you re writing an application from scratch on the Mac Cocoa makes it very easy to get a pretty 1 Or old depending on how much attention you paid to the brief NeXT empire Cocoa s heritage comes directly from NeXT right down to the prefix NS that prepends every Cocoa API entry API Introductions and Overview 47 complex application up and running quickly Cocoa offers other benefits as well but it s the most modern of the user interface choices on the Mac with all the associated object oriented benefits you d expect Interestingly many of the Mac APIs for many other things start as lower level APIs and are later incorporated into high level Cocoa classes that do a lot of the painful configuration work for you NSMovieView for example takes care of all of the QuickTime setup and configuration necessary to get a movie loaded playing and on screen Similarly NSOpenGLView takes care of all of the basic OpenGL infrastructure setup and configuration so that you can launch into writing OpenGL code directly It s a reasonably simple decision at this point If you re writing for a new or an exist ing Cocoa application you should use the Cocoa OpenGL API Taking a broader view Cocoa is the best place to begin if you re starting a new application from scratch on the Mac Cross P
360. orking the results include reliable high performance seamless video play back as an OpenGL texture Overview QuickTime was first introduced in late 1991 At the time it represented a great leap forward for multimedia not just on personal computers in general but for the Mac in particular The architecture of QuickTime data is quite compre hensive including a variety of features that were designed in from the start including multiple tracks of audio and video content and extensibility through out This extensibility will eventually allow QuickTime to evolve to support modern compressors such as AAC and MPEG4 In 1994 Apple introduced QuickTime version 2 0 first for the Mac and then later the same year for Windows This was both a clear shot across Microsoft s media bow if we may clumsily use a nautical metaphor and the first sign that Apple was serious about making QuickTime into a real standard Although QuickTime has always been fighting an uphill battle in Microsoft s backyard it was very clear then and is still clear today that the format operation and general standard that is QuickTime are just flat out better regardless of the platform on which it is used In the years since then QuickTime has continued to evolve supporting more advanced formats for audio video and images parallel processing capabilities and better developer interfaces Most recently Apple introduced QuickTime 7 which extended the QuickTime API to n
361. osing a pixel format creating a rendering context and issuing OpenGL commands on the Mac Now that we ve introduced the five Apple supported APIs for doing OpenGL setup and configuration on the Mac we ll explore a bit of the history behind these window system integration APIs and describe each of them in detail Configuration API Relationships There are two types of windows on OS X Carbon windows and Cocoa windows AGL provides the integration between OpenGL and Carbon win dows AppKit provides the integration between OpenGL and Cocoa windows NSWindows Unlike AGL and the AppKit interface to OpenGL CGL has no corresponding window type and accordingly no window event mechanism de fined As a result windowed OpenGL applications must rely on either AGL and the Carbon framework or the AppKit framework to provide access to their re spective windows and the event mechanisms behind them The CoreGraphics framework which is located in the System Library Frameworks ApplicationServices framework CoreGraphics frame work directory is the lowest level interface to the Quartz window system on OS X CGL AGL and AppKit all depend on CoreGraphics for integration with the windowing system Whether the windows are visible invisible or full screen doesn t affect this dependency Typically only the Quartz Services API of the CoreGraphics framework will be called upon by your OpenGL application Configuration API Relationships 49 NSGL AGL
362. ot unique to the Mac in fact you ll find it on most every platform GLUT allows you to quickly prototype some OpenGL code in such a way that you can test it on every platform on which you must deploy Although not really a good infrastructure for more complex applications it s a great way to get started In this chapter we ll provide only a cursory examination of the API on the Mac because with only one or two extremely minor exceptions GLUT on the Mac is the same as GLUT on any platform GLUT first arrived in November 1994 as a creation of Mark Kilgard of SGI It was created as a basic infrastructure for quickly and simply bringing up a window for OpenGL rendering Over the years GLUT evolved into a cross platform API providing support through its same basic interface to bring win dows up for OpenGL rendering on most Unix systems including Linux and eventually adding Windows and Mac support GLUT evolved in scope too as it grew beyond its windowing roots to provide a variety of other wrapper functions These wrapper functions focus on tasks such as device handling from keyboard and mouse to SpaceBall joysticks and more There are also wrap per functions for quick and easy creation of objects such as spheres cones and cubes In addition font handling video resize functions render to texture ca pabilities and basic dynamic function binding are all features that GLUT has acquired over the years Although GLUT has evolved to
363. ot a surprising requirement as this situation is completely analogous to critical regions when doing multithreaded programming The GLX specification has more information regarding this popular topic among ARB members if you re interested Framebuffers When an OpenGL application performs its rendering the output of that ren dering is directed to a buffer that contains the resulting pixels In the language of the OpenGL specification the official name of this buffer is a framebuffer Given all of the other terminology sometimes used to describe this buffer such as window pbuffer logical buffer and off screen buffer it is good to be clear about the meaning of this term A framebuffer is a destination for rendering Whether or not this buffer is visible and where this buffer physically resides are not part of its definition Also it s important to distinguish a framebuffer from a framebuffer object A framebuffer object is a container of framebuffer meta information rather than the framebuffer itself An analogue is a texture object which is a convenient reference to a parcel of texture data but not the actual data itself OpenGL is actually a really well designed system much like the Mac Although its use involves many terms and interfaces once you ve mastered a few key concepts you can reuse them again and again Thus the distinction between a hypotheti cal OpenGL type foo and a foo object is always the same across the API The ob
364. ou find a possible gaffe please bring it to our attention through our website This book has been a project long in the making and rumblings of Leopard Mac OS X 10 5 have been part of our plan since the beginning However due to information embargoes the paucity of information available to the public and publishing timelines our best efforts at incorporating final released Leopard specific details are thwarted Although we ve accounted for most major changes to OpenGL programming for Leopard in this book there was still some de gree of flux for Leopard features at the time this book was published Never fear we ve put together a detailed Leopard change synopsis for OpenGL and accounted for the flux in Leopard on our website in an extra chapter You ll find this bonus chapter at our website www macopenglbook com A few words on Leopard that we can say at this time with authority First Leop ard will provide OpenGL 2 0 and OpenGL ES support OpenGL 2 0 is a great baseline for OpenGL developers providing the most modern of OpenGL foun dations upon which to develop Also of interest is the inclusion of OpenGL ES in this release ES stands for embedded system and is a nice stripped down ver sion of OpenGL largely targeting handheld devices At this time if writing an application for a desktop system it would still be most sensible to target OpenGL 2 0 However if you re building and testing a cross platform device that might be u
365. ous graphics cards concur rently and provide a virtualized desktop among multiple graphics devices This greatly simplifies application development when compared to creating and maintaining display connections for each device installed in the system API Layers OpenGL is defined as an abstracted software interface to graphics hardware As with most operating systems OpenGL on the Mac OS is a software layer that interfaces with hardware Applications and other APIs depend on this layer to provide a common interface to the varied graphics hardware they wish to control Unlike many operating systems the Mac allows explicit selection of specific rendering paths and has a few other unique features as well On Mac OS the dependencies between the graphics driver stack layers and sometimes even just the names of those layers can be tough to get a handle on Although OpenGL is defined to remain separate from the windowing system of the operating system on which it runs OpenGL must implicitly interface with it to observe the rules of drawing in a windowed environment This need for in teraction has a variety of implications from application performance to window selection and we ll explore those in later sections The layering of the various APIs on Mac OS X occurs in a specific way to allow this window system inte gration and permit a bit of legacy interoperability Hence a few choices must be made when deciding how to open a window for OpenGL ren
366. out peer The Mac is a fun and efficient platform on which to develop appli cations thanks to the set of OpenGL drivers at its core that support a rich and deep feature set great performance and deep integration in OS X The Mac has excellent and usable tools for quickly monitoring OpenGL behavior rapidly prototyping shaders and digging deep to analyze OpenGL behavior in the application and driver The Mac makes OpenGL development efficient and fun Although the development tools and environment are powerful and helpful many corners of OpenGL on the Mac remain under documented A developer must choose among several development languages user interface UI tool kits window managers and additional Mac APIs such as QuickTime and Core Image yet still ensure that his or her software runs well on a variety of target Mac platforms All of these factors can make using OpenGL on the Mac a chal lenging task even for developers who have been writing OpenGL applications on other platforms for years This book was put together with an eye toward simplifying and clarifying the ways in which OpenGL can be used on the Mac It is our hope that by codifying all the information available about OpenGL on the Mac in one place and by presenting each interface with clarity and depth developers will have a one stop reference for all things OpenGL on the Mac Who Should Read This Book This book is intended for OpenGL programmers who wish to develop applic
367. ow its graphics workstation market share the com pany needed to use a graphics API that was an industry standard Ultimately the applications that independent software vendors ISVs were producing were what sold the hardware they were building By making IrisGL into an open standard OpenGL SGI could greatly help lower the ISVs development costs to reach multiple platforms which in turn would encourage them to adopt the use of the OpenGL API To make OpenGL an open standard SGI formed the OpenGL Architecture Review Board ARB in 1991 to oversee and develop the specification with a broad range of industry interests in mind The ARB includes both software and hardware focused vendors in the graphics industry with an interest in further ing an open graphics API standard In its simplest form OpenGL is a specification document To develop the OpenGL standard a formal process has been established by which new func tionality may be added to the OpenGL specification But where do these exten sions come from Who decides they want one and how do those new extensions get put into the standard New extensions to OpenGL are typically created by individual companies or organizations that are interested in including the new extension in the ver sion of OpenGL they ship These extensions are known as vendor extensions They are specific to the company that created them and are named accordingly For instance an extension unique to Apple is th
368. ow the core OpenGL specification evolves There are many paths to adding functionality to the core of OpenGL but the OpenGL API itself largely evolves through the process defined below This pro cess may be familiar to some as it s modeled on School House Rock s How a Bill Becomes a Law We kid of course but the process is fairly democratic and open to all good ideas from members of OpenGL s governing body the OpenGL Architecture Review Board Here s the process for a hypothetical new feature 1 A new hardware or software feature exists 2 A vendor creates an OpenGL extension GL APPLE new feature name This is known as a vendor extension 3 A specification is published describing tokens and API entry points 4 Time elapses 5 Other vendors adopt the vendor extension and GL APPLE new feature name becomes available on several platforms at which point it is promoted from a vendor extension to an EXT extension 6 Several vendors lobby the OpenGL Architecture Review Board to standard ize the EXT extension as GL ARB new feature name The extension is then known as an ABB extension 7 Time elapses 8 The extension s purpose and utility become very clear to many developers and vendors 9 A quorum of vendors lobbies the OpenGL Architecture Review Board again to include this ARB extension in the next version of the official OpenGL specification 10 The extension is incorporated into core OpenGL X Y
369. p plications across these varied configurations OpenGL provides an abstraction layer that insulates application developers from having to develop specific logic for the unending array of systems and graphics devices At present the Mac OS OpenGL implementation supports graphics devices from four vendors ATI Intel NVIDIA and VillageTronic And of course the graphics drivers support either PowerPC or Intel CPUs feeding these devices The Mac also supports a virtual graphics device that processes OpenGL ren dering commands on the CPU of the system This virtual device is canonically known as the software renderer In this chapter we ll explore the software architecture of the OpenGL on the Mac including the history of OpenGL itself and the way in which the Mac software architecture supports flexible graphics application development using this API About OpenGL To understand OpenGL on the Mac let s begin by looking back at the evolu tion of OpenGL itself Silicon Graphics SGI began development on OpenGL in 1990 with version 1 0 of the software being released in 1992 OpenGL was a logical evolution from its predecessor IrisGL named in accordance with the graphics hardware for which it was built IrisGL was initially released by SGI in 1983 It included all of the necessary API entry points that unlike OpenGL han dled windowing system tasks unrelated to actual graphics pipeline rendering SGI soon realized that to gr
370. parameter should be set using a bitwise OR of the enum values used with the OpenGL call g1PushAttrib It provides a handy mechanism to filter which state elements you wish to copy from the source context to the destination context Context Management 63 Specifying GL_ALL_ATTRIB_BITS for your state mask will yield as close as pos sible to a duplicate of your source context The faithful reproduction of the copy is limited only by the scope of state encapsulated by the g1PushAttrib glPopAttrib state management API within OpenGL Various OpenGL state elements such as feedback or selection settings cannot be pushed and popped The OpenGL specification has a detailed description of this state management API if you need to further scrutinize the details of your context copy To free a context and set the current context to NULL use call CGLError CGLDestroyContext CGLContextObj ctx Setting or getting the current context in CGL is a simple matter of calling CGLError CGLSetCurrentContext CGLContextObj ctx or CGLContextObj CGLGetCurrentContext void You may find CGLGetCurrentContext to be the most useful entry point in the API It s very handy for debugging CGL AGL and NSOpenGLVi ew based OpenGL applications You can simply insert this call in your code anywhere downstream of context initialization and use the result for the full gamut of reasons you use contexts It s quite handy for debugging configu
371. pen links and loads a dynamic chunk of code The second function dlsym finds and resolves a named symbol within that code Thus in Example 13 6 first we use dlopen to get a handle to our running application and then we use dlsym to resolve the passed in function name If we get a NULL back the symbol doesn t exist and we shouldn t call it unless we want a hasty exit from our application Two final notes on the dl calls First notice that we symmetrically dlclose at the end of our resolveSymbol function This is absolutely a good and necessary thing to do but for performance reasons you d prefer to dlopen dlclose once and resolve a lot of symbols in the middle For our example we do it for every symbol within our resolveSymbol method as a demonstration and for simplicity There isn t a huge performance penalty however because you don t shouldn t wouldn t call these methods each time you need a symbol Instead you would cache the result of resolveSym bol which is a function address and simply use those cached results later in your run loop Utilization and Binding 265 The second note on these calls relates to the symbol names Function names within libraries are changed or in compiler terms mangled into another form stored within those libraries The mangling scheme is usually something you can learn about and figure out but the d1 calls are designed to work with the human readable versions of these names For example
372. penGL Configuration in Leopard In particular pixel format selection can have a profound impact on both the per formance of and the video memory usage by your application Keep in mind that choosing pixel formats with more capabilities may lead to slower perfor mance than choosing pixel formats with fewer options and smaller buffers For example if you have a choice between a pixel format with a color buffer size of say 8 bits per color component 32 bits total or one with a color buffer rep resented as a 32 bit floating point number per component 128 bits total it s pretty clear that writing to a single pixel in your drawable requires four times the bandwidth just for color We ll get into these performance implications later and explore issues like this one in more detail For now just realize that a good rule of thumb for choosing pixel formats is to choose the one that most closely matches your application s needs We ll finish this Cocoa example by adding a few more useful methods to our code These will allow two more key tasks namely context setup that is things you might do in an OpenGL application such as glEnable certain states and bind textures and drawing The first of these methods which is named prepareOpenGL is defined to be the first opportunity that your class will have to make some OpenGL calls pre pareOpenGL will be called once a valid pixel format context and drawable are all available so you
373. pendix C The Cocoa API for OpenGL Configuration in Leopard glEnable GL TEXTURE 2D glBegin GL QUADS float ww 9 float hh 9 float zz 0 0 glTexCoord2f 0 0 glVertex3f ww hh zz glTexCoord2f 1 0 glVertex3f ww hh zz glTexCoord2f 1 1 glVertex3f ww hh zz glTexCoord2f 0 1 glVertex3f ww hh zz glEnd So what does our example do Our goal is to render a textured quad to the screen where the texture represents an intermediate rendered result We begin by configuring our FBO and texture so that they refer to each other In the ren der loop we make the FBO active clear to yellow and then unbind the FBO Because of the magic of FBOs those results are now usable as a texture so we render a textured quad to the screen When we set up the texture environment parameters for texturing we specified GLRI EPLACE to wholly replace any color on the quad with the texture image If everything works as we ve described and it does we should see the final rendered image as shown in Figure C 11 Figure C 11 Results of Rendering to an FBO and Texturing a Quad with That Result Texture Courtesy of NASA s Earth Observatory Alternative Rendering Destinations 317 You can do a lot more with FBOs including capturing other rendering results such as depth stencil and other render targets but this kind of advanced usage is beyond the scope of this book We refer yo
374. perform increasingly complex calculations during vertex trans formation so this bottleneck should not be discounted you can still become bottlenecked by this phase The other primary data type pixels or texels as pixels are known if they con sist of texture data encounters performance limits during rendering as well When an application has to rasterize or fill a large amount of screen real es tate the application may become fill limited The term fill originates from the need to fill polygons with pixels when drawing them These rasterization stage output pixels are known as fragments in OpenGL However fill doesn t necessarily just refer to the fragments that you see it also implies all the sec ondary data that is rendered per pixel including stencil depth alpha and other capabilities of the visual you re using In short a lot of secondary data is moved around for every pixel that ends up reaching the fragment engines and too many fragments being processed can lead to a fill limitation Fill limited applications are quite common these days although not necessarily for your application As always you will need to evaluate your specific application for this risk The ultimate destination of the data in a graphics application is the display on which it will be shown These devices have their own limits in terms of refresh rate or response time that will affect how fast you can render your graphics A common
375. performance problem with graphics applications and monitor refresh rate occurs when your application only achieves frame rates that are some in teger multiple of the refresh rate For example your monitor may be refreshing at 60Hz but your application only sees 30Hz or 20Hz that is you never see 26 Chapter 3 Mac Hardware Architecture 27Hz or 34Hz or 19Hz only integer multiples This is due to an effect called frame rate quantization which we ll explore briefly in Chapter 11 Problem Domains Each domain from which a graphics application originates tends to have its own points of early saturation limits for general purpose graphics hardware like the Mac Here are some examples e Gaming CPU bound when computing the physics of the characters and objects in their scenes Video editing Upload limited when manipulating multiple high definition streams of video during transitions between video streams e CAD CAE and modeling Transform limited This software will take con structive solid geometry or surface models and create incredibly dense meshes of tetrahedra or other 3D primitives for the purpose of stress analysis by finite element engines Each of these 3D primitives is represented by poly gons that must be transformed to manipulate the model e Medical imaging volume rendering Fill limited Arrays of 2D image scans from medical or seismic oil and gas equipment are reconstructed into three dimensions by this softwa
376. ple Generic Renderer Geforce 2 MX 4 MX Rage 128 10 4 10 Tiger 2 0 Apple Float Renderer Radeon HD 2400 HD 2600 Radon X1600 X1900 Geforce 8600M Geforce Quadro FX 4500 Geforce 6600 6800 Geforce FX 1 5 Radeon X800 Radeon 9600 9700 9800 1 3 Radeon 9200 Radeon 9000 Radeon 8500 Radeon 7000 7200 7500 Geforce 4 Ti Geforce 3 1 2 GMA 950 Tl Geforce 2 MX 4 MX Rage 128 Continued 12 Chapter 2 OpenGL Architecture on OS X Table 2 2 Mac OS Hardware Renderer Support for Versions of OpenGL Continued Mac OS Version OpenGL Version Renderer 10 5 Leopard 2 1 Apple Float Renderer 2 0 Radeon HD 2400 HD 2600 Radon X1600 X1900 Radeon X800 Radeon 9600 9700 9800 Geforce 8800 8600M Geforce Quadro FX 4500 Geforce 6600 6800 Geforce FX 1 3 Radeon 9200 Radeon 9000 Radeon 8500 Radeon 7000 7200 7500 Geforce 4 Ti Geforce 3 1 2 GMA 950 1 1 Geforce 2 MX 4 MX This software renderer is limited to 1 21 compliance on PowerPC systems and was released supporting 2 1 on the newer 8600M and HD 2400 HD 2600 systems These are limited to 1 5 compliance on PowerPC systems Table 2 2 illustrates the rather complex version landscape of the relationship be tween devices hardware renderers software renderers and Mac OS X software releases Version compliance for any hardware renderer or the latest software renderer may change we hope
377. plication is con figured albeit at the cost of greater complexity The most important limitation and one that neither AGL nor the Cocoa in terface to OpenGL has is that there is no way to build a windowed OpenGL application using only CGL A CGL only application can render full screen or off screen images only Because AGL and Cocoa are layered on top of CGL you may freely mix CGL calls with an AGL application or a Cocoa application Be aware that when doing so you have to be careful not to introduce bugs because your AGL or Cocoa calls are undoing or redoing the same tasks as CGL In most cases you ll find that AGL and Cocoa interfaces should provide enough flexibility and control so that direct use of CGL is not required Apple OpenGL AGL is the Carbon interface to OpenGL on the Mac Carbon is a set of C level APIs to most Mac systems and is the foundation of many an older Macintosh application Carbon is by no means a deprecated API set in fact quite the op posite is true Carbon layer APIs tend to be the first place you see lots of new functionality for the Mac You can also create full featured modern Mac OS X applications written entirely in Carbon But the goal here is not to motivate to you to either use or not use Carbon but rather to help you decide whether this API is of relevance to you The quick litmus test for using AGL is this If you have a Carbon application into which you re adding OpenGL then AGL is the API f
378. plished via FBO are unmatched by these alternative techniques Alternative Rendering Destinations 321 If you ve got older code that uses one of these approaches a move to FBOs will likely both simplify and accelerate your code Take the leap Summary In this chapter we explored how to create and configure Cocoa based OpenGL rendering areas for on screen windows and for various intermediate render tar gets We saw how to create custom pixel formats examined some of the flags that these pixel formats take and demonstrated how to configure and initialize pixel formats We also saw how to customizeNSViews and NSOpenGLViews to use custom pixel formats and create contexts We considered how to share data among multiple contexts and we learned how to configure full screen sur faces Now that you know the fundamentals of OpenGL and Cocoa setup you have a solid foundation from which to begin building your own Cocoa OpenGL applications 322 Appendix C The Cocoa API for OpenGL Configuration in Leopard Appendix D Bibliography 1 The OpenGL Architecture Review Board OpenGL 2 0 specification http www opengl org documentation specs version2 0 glspec20 pdf 2 The OpenGL Architecture Review Board OpenGL website http www opengl org 3 Apple Computer About this Mac build information http docs info apple com article html artnum 106176 4 Apple Computer Apple developer website http developer apple com 5 A
379. policy For non zero buffer specifications prefer the largest available buffer for each of color depth and accumulation buffers NSOpenGLPFAOffScreen YES Consider only renderers capable of rendering to an off screen memory area that have a buffer depth exactly equal to the specified buffer depth size An implicit change to the selection policy is as described Selection policy NSOpenGLPFAClosestPolicy NSOpenGLPFAFullScreen YES Consider only renderers capable of rendering to a full screen drawable Implicitly defines the NSOpenGLPFASingleRenderer attribute NSOpenGLPFASampleBuffers Unsigned integer The value specified is the number of multisample buffers required NSOpenGLPFASamples Unsigned integer The value specified is the number of samples for each multisample buffer required Continued NSOpenGLView 291 Table C 3 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat Continued Token Description NSOpenGLPFAColorFloat YES Consider only renderers capable of using floating point pixels NSOpenGLPFAColorSize should also be set to 64 or 128 for half or full precision floating point pixels Mac OS 10 4 NSOpenGLPFAMultisample YES Consider only renderers capable of using supersample anti aliasing NSOpenGLPFASamp1leBuf fers and NSOpenGLPFASamp les also need to be set Mac OS 10 4 NSOpenGLPFAAuxDepthStencil If present searc
380. pple Computer Apple technote 1188 getprocaddress and openGL entry points http developer apple com qa qa2001 qa1188 html 6 Apple Computer Apple technote 2080 understanding and detecting openGL functionality http developer apple com technotes tn2002 tn2080 html 7 Apple Computer Apple texture range sample code http developer apple com samplecode TextureRange TextureRange html 8 Apple Computer Apple Vertex performance sample code http developer apple com samplecode VertexPerformanceTest VertexPerformanceTest html 9 Apple Computer Configuring and running X11 on Mac OS X http developer apple com opensource tools runningx11 html 323 10 Apple Computer Core video and QuickTime with OpenGL http developer apple com samplecode QTCoreVideo101 index html 11 Apple Computer Mac OS Versions and builds since 1998 http docs info apple com article html artnum 25517 12 Apple Computer Quick Start guide for AltiVec http developer apple com hardware ve quickstart html 13 Apple Computer SSE performance programming http developer apple com hardware ve sse html 14 Alex Eddy OpenGL version renderer GLSL table http homepage mac com arekkusu bugs GLInfo html 15 Ron Fosner OpenGL Programming for Windows 95 and Windows NT Boston MA Addison Wesley 1997 16 Erich Gamma et al Design Patterns Elements of Reusable Object Oriented Software Boston MA Add
381. ps to reproduce the bug and a test application you ll skip the maximum number of people and get the best turnaround time for your bug report Threading A thread on OS X and on many other operating systems contains all the re quired state elements for executing instructions on a processor Threads have an associated call stack have their own set of register states and share the vir tual address space of the process in which they are created Threads are quite lightweight and high performance Provided you give them some work to do thread switching and synchronization overhead can be amor tized with relative ease In this manner threads are the doorway to full utiliza tion of multiprocessor Mac computers which unlike with some platforms has been a common configuration for many years At the lowest level OS X threading is implemented as Mach threads This level however is generally not interesting for application development and should be avoided if possible Above Mach threads OS X conforms to the industry standard POSIX threading model If you re porting from other platforms OS X s use of POSIX threads can be a real relief POSIX threading is the foundation of threading logic for application developers working on OS X Depending on whether your application is a Carbon application or an Objective C Cocoa application there are different abstraction layers for threading above the POSIX interface For Carbon there are two thr
382. pt to enable the threaded OpenGL engine on a single processor system it will automatically fail to enable thus no logical provisions need to be made by your application for uniprocessor Macs The other implication of the additional work imposed by the multithreaded en gine is that if your application by way of the GL commands it submits forces the internal OpenGL threads to serialize with each other you may find your application actually running slower and using more memory than if you hadn t enabled the threaded OpenGL engine at all Read on for details about whether the threaded OpenGL engine is right for your application As in the threaded application case using the threaded OpenGL engine is most effective for applications that are CPU processing bound which most appli cations are Along with being CPU bounded your application needs to be well written to leverage the advantages offered by the multithreaded GL en gine Well written means that the application infrequently stalls the graphics pipeline that is it makes minimal calls to g1Flush glFinish or any type of g1Get Furthermore it means that your application uses retained mode rendering wherever possible Display lists vertex buffer objects pixel buffer objects and framebuffer objects are good examples of retained mode rendering constructs Obviously using some immediate mode calls in your application is acceptable If your application predominantly uses g1Begin
383. py into a texture that s the extent of the information we need to keep track of throughout our view class We then look at the initialization code which is again very similar to the FBO example but now without the FBO configuration Example 8 15 Example 8 15 OpenGL Setup for Copy to Texture Rendering void prepareOpenGL glMatrixMode GL PROJECTION glLoadIdentity Alternative Rendering Destinations 159 glOrtho 1 1 1 1 1 100 glMatrixMode GL MODELVIEW enable generate and bind our texture objects glEnable GL TEXTURE 2D glGenTextures GLsizei 1 amp textureID glBindTexture GL TEXTURE 2D textureID const unsigned int texdim 64 const unsigned int nbytes 3 unsigned char data texdim texdim nbytes memset data 0 texdim texdim nbytes unsigned int ii for ii 0 ii texdim texdim ii data ii nbytes 0 Oxff gluBuild2DMipmaps GL_TEXTURE_2D 0 GL_RGB texdim texdim 0 GL_RGB GL_UNSIGNED_BYTE data glTexEnvf GL TEXTURE ENV GL TEXTURE ENV MODE GL REPLACE add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES As before our main drawRect routine does the bulk of the work but here is where the code differs from the FBO version Let s look at it now in Example 8 16 and talk about the differences and
384. quire a complex UI GLUT is appro priate If you re doing anything more complex than a keyboard or simple menu interface the Mac specific OpenGL APIs and windowing systems are the place to look 48 Chapter 5 OpenGL Configuration and Integration X11 The last major API set for graphics on the Mac is an old standby X11 X11 APIs for windowing and OpenGL have existed for many years and Apple fully sup ports a set of them through its X11 SDK If you re bringing an application from another Unix platform to the Mac it s likely that the application uses X11 at its core Apple has taken great effort with OpenGL and X11 on the Mac to ensure that OpenGL runs at full speed within X and because of this excellent perfor mance a straightforward port of a legacy X11 application to the Mac is often a very viable route to take This strategy will get an application up and run ning on the Mac but the look and feel of that application won t fit well with the rest of the Mac experience Even so this is an expedient path to bringing an application to the Mac If you ve got a code base that uses X11 then the X11 set of APIs is the right path for you By contrast if you re starting from scratch on the Mac or porting an application to the Mac and want to ensure the best look and feel then one of the Mac only APlIs is the right place to begin API Introduction and Overview Wrap Up In summary there are five API choices for opening a window cho
385. r 7 The AGL API for OpenGL Configuration 000 AGL Window Figure 7 3 AGL Window Example Results your renderer supports You can query the renderer information independently of any OpenGL context and then you can use this discovered renderer informa tion with your AGL pixel format to customize it to your needs We now present some example code to search the list of renderers through AGL and query some properties in Example 7 5 Example 7 5 AGL Renderer Query Example int main int argc char argv AGLRendererInfo ri aglQueryRendererInfo NULL 0 if ri NULL unsigned int ii 0 while ri NULL GLint vram tram accel id GLint mm 1024 1024 aglDescribeRenderer ri AGL RENDERER ID amp id aglDescribeRenderer ri AGL ACCELERATED amp accel aglDescribeRenderer ri AGL VIDEO MEMORY amp vram aglDescribeRenderer ri AGL TEXTURE MEMORY amp tram cout renderer ii Additional Topics 105 lt lt id lt lt id lt lt hardware accel endl cout lt lt NE vram Mb vram mm tram Mb tram mm endl ri aglNextRendererInfo ri ii H H else GLenum error aglGetError cout lt lt error lt lt error lt lt endl return 0 This code begins by getting the renderer information structure for all devices on this Mac using ag1QueryRendererInfo with NULL to indic
386. r extensions even in the latest version of OpenGL However as we ve seen with PowerPC and with lots of API changes over the years all good things must come to an end While this is the case today it may not always be The authors recommend that you try to use core OpenGL features whenever possible and modernize your code to take advantage of these features directly rather than hoping that your extensions will always exist Identification Selection Query and Usage 259 Table 13 1 Preprocessor Tokens for Extension Usage Path OpenGL Token Extension Token Preferred GL_VERSION_2_0 None Alternative GL VERSION 1 3 GL ARB shading language 100 GL ARB program objects GL ARB vertex shader GL ARB fragment shader Fallback Any None But in code how do we wrap things Well anywhere code uses either tokens or API entry points specified by these extensions we need to check for their existence prior to using that code These tokens come from different places on different platforms On the Mac all of the necessary extension tokens and OpenGL version information are included with the g1 h header file On other platforms such as Windows Linux and other versions of Unix a similar sit uation may exist or there may be a companion glext h header file The Mac also has a glext h header file although the baseline g1 h header files already include these tokens At this point in the discussion it turns out th
387. r fallback visualization and color it yellow if shading is available It s not a shiny bumpy infinitely detailed anti aliased shader but it gets the point across The second step is to write the combination of preprocessor token checking op erations to ensure that regardless of the machine on which we build our appli cation even one without proper extension headers the application still builds properly This may be something you want to leave broken at least for now because if you do build your application in an environment without proper tokens you won t get the behavior you want from your application on any plat form We explicitly handle this possibility by adding an terror message in the case that our OpenGL extension preprocessor checks fail It will warn us that the environment is not configured properly Next we look at the tokens we need based on our criteria for our OpenGL en vironment defined earlier Table 13 1 shows our combination of preferred and alternative rendering path preprocessor tokens There s a fairly straightforward naming convention for preprocessor tokens in OpenGL as the table illustrates 2 Apple in a very vague and informal way in TechNote 2080 6 says No extension should ever be removed from the extensions string as part of a larger discussion about when an extension should be used and when a core version of OpenGL should be used Theoretically and currently you can continue to use the shade
388. r overall string For other specifications such as to consider visuals of other constraints we would use any one of lt gt lt gt or A final syntax element the character is used to specify a match that is greater than or equal to the number specified but preferring fewer bits rather than more This is a good way of getting close to your literal specification but with some fail over capability preferring visuals of better quality For a complete example of how this specification works we ll examine a re placement for the call glut InitDisplayString in our previous example but now modify it to use this form of visual selection instead Example 9 3 is set up to try to find a visual with at least 2 bits of stencil precision double buffered with an RGBA visual of 8 or greater bits as closely matching 8 as possible a 16 bit or greater depth and multisample anti aliasing The results of this change Table 9 3 glutInitDisplayString Policy and Capability Strings Label Description alpha Bits of alpha channel color buffer precision red Bits of red channel color buffer precision green Bits of green channel color buffer precision blue Bits of blue channel color buffer precision rgba Bits of red green blue and alpha channels color buffer precision acca Bits of RGBA channels accumulation buffer precision depth Bits of depth channel buffer precision stencil Bits of depth channe
389. r own descriptions of a useful selection of these tokens in Table 7 2 Among the things that can be specified are stereo or monoscopic rendering capabilities also known as quad buffering stencil planes depth and color buffer sizes floating point pixels anti aliasing and even exact specification of the renderer and pixel format by ID There s quite a lot of capability and there are close analogs to any of the pixel format tokens exposed in Cocoa as well Read the table experiment some decide which best fit your needs and then customize your baseline code with your pixel format requirements The second major component of the code in Example 7 3 creates and sets the context for our rendering We simply call ag1CreateContext and clean up our pixel format using aglDestroyPixelFormat since our context is bound to that pixel format We then make the new context current by using aglSetCurrentContext and bind our context to a full screen drawable by using aglSetFullScreen As before robust production code should check for failure at any step in this process and subsequently use ag1GetError to provide detailed error information for user feedback The final component of the code in Example 7 3 is a main loop one in which you d handle events For purposes of our example that is raw simplicity our event loop simply contains calls to initialize the OpenGL machine draw our scene and display the results for a few seconds Because this is a
390. r sections We then choose our pixel data format enumerator based on the number of bytes per pixel in this bitmap The code from this point on is pretty standard OpenGL texture object manip ulation We generate a new texture object for our use and then build mipmaps using the ever useful GL utility library function glBuild2DMipmaps Finally we relinquish our interest in this new bitmap and return our texture object ID In this section we ve seen an end to end process for converting an NSImage to an OpenGL texture We ve demonstrated a few techniques to generate NSImages from common sources and then taken those images and created code to allow for flexible manipulation and downloading of an NSImage to the Cocoa Image NSlmage 181 graphics hardware These fundamental techniques will be used again and again as we look at other methods of manipulating images and video on the Mac OpenGL to NSImage In the previous section we saw how to create an OpenGL downloadable ob ject from an incoming NSImage Of course you might want to do the con verse as well That is you might want to extract an image from the graphics hardware for later use elsewhere The techniques demonstrated in this section are primarily designed to cross from graphics hardware back to main memory As a consequence they re not at all the right thing to do if you re trying to use an image already in hardware for another rendering pass or for another
391. raints of both setting up and transferring data between the host and graphics processor Once your data is on the GPU however the graphics processor can directly process the uploaded data for display or store it in VRAM If the application overcommits the VRAM by for instance defining a great deal of vertex texture or framebuffer objects the data will be continuously paged in as needed from the host CPU memory subsystem The upload limit becomes a key bottleneck at this point Data Flow and Limitations 25 We have now described the various forms of bottlenecks that can arise in getting your data from the disk to the graphics To review the main data flow bottle necks your application will face from the system perspective are as follows Disk I O Memory I O CPU I O GPU I O Modern graphics cards internally look a lot like the host CPU architecture That is they have a memory controller sometimes several processors a main memory with various caches busses connecting the various components and a bunch of other plumbing Let s consider the processing of vertex data first On older graphics cards the notion of being transform limited was quite common This limit describes the required time to transform in space clip and light vertices in the scene With the degree of parallelism in today s CPU this has become a less common bottleneck for all but the heaviest users of geometry However shaders now allow people to
392. ration related issues Context Parameters and Enables Like any logical object a CGLContextObj has an associated set of parameters that are scoped to the context itself Some parameters are read write others are read only and simply allow the application to inspect the running configuration of the context Here s a code fragment from the CGLTypes h file on a Tiger system that lists the valid context parameter values Parameter names for CGLSetParameter and CGLGetParameter ud typedef enum CGLContextParameter kCGLCPSwapRectangle 200 4 params Set or get the swap rectangle x y w h kCGLCPSwapInterval 23222 1 param 0 Don t sync n Sync every n retrace kCGLCPDispatchTableSize 224 1 param Get the dispatch table size kCGLCPClientStorage 226 1 param Context specific generic storage kCGLCPSurfaceTexture 2 228 3 params SID target internal format kCGLCPSurfaceOrder 202355 1 param 1 Above window 1 Below Window 64 Chapter 6 The CGL API for OpenGL Configuration kCGLCPSurfaceOpacity 236 1 param 1 surface is opaque default 0 non opaque kCGLCPSurfaceBackingSize 304 2 params Width height of surface backing size kCGLCPSurfaceSurfaceVolatile 306 1 param Surface volatile state kCGLCPReclaimResources 308 0 params kCGLCPCurrentRendererID 309 1 param Retrieves the current renderer ID kCGLCPGPUVert
393. rbon window and process events We ll begin by presenting the main routine seen in Example 7 4 and then we ll walk through it Example 7 4 AGL Windowed main Example int main int argc char argv AGLPixelFormat pixelFormat GDHandle display GetMainDevice Rect windowRect 100 100 100 width 100 height Pixel Format and Context 101 Figure 7 2 AGL Full Screen Example Results WindowRef window GLint attribs AGL_DOUBLEBUFFER AGL_ACCELERATED AGL_NO_RECOVERY AGL_RGBA AGL_NONE ub Context creation pixelFormat aglChoosePixelFormat amp display 1 attribs context aglCreateContext pixelFormat NULL aglDestroyPixelFormat pixelFormat aglSetCurrentContext context Window creation CreateNewWindow kDocumentWindowClass kWindowStandardDocumentAttributes kWindowStandardHandlerAttribute kWindowResizableAttribute kWindowLiveResizeAttribute kWindowCloseBoxAttribute amp windowRect amp window 102 Chapter 7 The AGL API for OpenGL Configuration SetWindowTitleWithCFString window CFSTR AGL Window ShowWindow window aglSetDrawable context GetWindowPort window aglUpdateContext context opengl setup and render initGLstate draw mainloop while done processEvent cleanup aglSetCurrentContext NULL aglDestroyContext context return 0 The first section of code performs some Carbon window manageme
394. re are dozens of ways to use this API Consider yourself lucky however as this number is down from the more than 2500 entry points to the original QuickTime Movie Toolbox At any rate our code for creating our movie is pretty simple and uses only a few methods First we create a movie using the class initializer methods Next and this is important we retain that movie because it s allocated using an autorelease pool which means it may go out of scope at the end of the method and cause you headaches later As an aside whenever you see weird memory issues usu ally caused by a lack of documentation about how some method has allocated and returned an object think about the retain release cycle and start digging into FAOs message boards and other sources At this point we specify a method that can be used to set almost any param eter of a movie in our case to keep the movie playing Finally we provide a method to launch the movie playback And that s all there is to loading and playing a movie with OTKit Now we ll look at how we take this playing movie playing off in the background some where and bind its graphics content to OpenGL The reason we introduced the NSImage accessor methods first in this chapter was because we planned to revisit these techniques throughout the Cocoa API This reuse is also one of the reasons why Cocoa is so powerful for application development You learn a technique once and continue to apply
395. re for analysis These arrays of images are rasterized into large polygons for display and impose an enormous fill burden on the system It is important to approach graphics application development with a good un derstanding of the limits of your domain and to design your application its logic and its data structures accordingly Keep in mind that once you eliminate a bottleneck some other portion of the system will inevitably provide a new bottleneck It s always an iterative process and one in which you ll need to in vest some time to get the best results Know Thine OS Requirements Any modern application you write will likely have to support multiple versions of the Mac OS It s obviously easiest to support only one version but your cus tomers will likely have multiple versions which you must then accommodate If your application is expected to run on multiple Mac OSs such as Panther Tiger or Leopard each will have a different set of features capabilities and baseline requirements For your application whether based on OpenGL or not understanding these baselines will have consequences for your software For this reason each of these operating systems is published with a set of minimum system requirements Naturally the minimum configuration is the most restric tive system that you will have to support and is what your application should Data Flow and Limitations 27 be most concerned about This section explores some of t
396. rence MacHack He currently teaches OpenGL and scenegraph training courses around the world as part of his work for Blue Newt When Bob is able to be pulled away from his Mac and graphics work you ll find him either playing volleyball or sailing with his wife Please don t hesitate to email him rpk blue newt com or visit his website http www blue newt com J D Sullivan is an OpenGL driver engineer who has been writing graphics soft ware professionally for more than 15 years His experience with OpenGL began with writing IrisGL applications for a finite element modeling and broadcast animation lab in 1992 His experience developing on the Macintosh platform began in 1988 with Symantec s Think C and a 16 MHz SE 30 that boasted 4MB of RAM and 1MB of video memory After three years working on a distributed renderer for the FEM and broad cast animation lab J D joined Silicon Graphics Inc where he first focused on performance and feature differentiation of graphics applications from ISVs that were critical to SGI s business A considerable portion of this work centered xxxi on medical and GIS imaging He was one of the original four designers and implementers of SGI s Volumizer API and he earned a design patent for high performance modulation of 3D textures He then moved to SGI s Consumer Products Division where he worked as part of the OpenGL software team dur ing the bring up of both the Cobalt and Krypton gr
397. rest of the code massages the image returned so that it s readily texturable That s really all there is to using the new OTKit to get a movie ready and rendered by OpenGL But what about performance We use the same helper method we used for our NSImage example a method to download image data as a texture named downloadImageAsTexture That method does a variety of things including allocating a texture ID also known as a texture name to old school OpenGL geeks binding that name and creating a texture and a stack of mipmaps That s a lot of work and something we do for every frame Based on some things we know about movies for example that their size doesn t change 188 Chapter 10 API Interoperability e208 Window QuickTime Figure 10 2 First Frame of the Movie we can improve this program s performance significantly but we ll save that for Chapter 11 Check there for all the optimizations we can make to streamline this streaming media download For now we re focusing on functionality not trying to prematurely optimize the application What do we see if we replace our prepareOpenGL and drawRect routines in our earlier examples with the code in Example 10 10 With any luck you see something like Figures 10 2 10 3 and 10 4 If you don tsee those images likely culprits are that the baked in movie doesn t exist couldn t be found or uses a codec the QuickTime doesn t understand We ve included a statement to log w
398. ring We ll first look at your chunk of data either pixels or vertices to be rendered We ll assume that you ve not loaded your data yet so it currently lives on a disk somewhere Beginning by loading your data from disk if there is not enough system memory to hold the data resident then you must take the disk I O limit into account Once the data is in the system memory a memory bandwidth limit between the CPU and the memory itself becomes important Understanding system caching and using it efficiently is key here If the data is being streamed managing the caches becomes less significant However if you are frequently revisiting the same data keeping the CPU caches hot is critical to application performance When the data is in the primary cache of the CPU the next limitation may well be the instruction throughput which relates directly to the clock rate of the CPU itself This constraint and more loosely memory and cache access is often described as being CPU bound Being CPU bound has two forms bound by code inside the application or bound by code inside the graphics system soft ware of the Mac After being processed by the CPU the data is transferred to the GPU During this process it may encounter a bandwidth limit between CPU and GPU When your application hits this limit it is referred to as upload limited sometimes download limited depending on if you view things differently based on the const
399. rmance Flush the modified region to VRAM glFlushMappedBufferRangeAPPLE GL PIXEL PACK BUFFER 0 width height Unmap and unbind glUnmapBuffer GL PIXEL PACK BUFFER glBindBuffer GL PIXEL PACK BUFFER 0 Apple Fence Extension Fences are tokens in the OpenGL command stream that act like tracer bullets they tell you where you are Fencing is a key concept because it bridges the world of the synchronous and the asynchronous That is it s great to be as asyn chronous as possible but ultimately drawing operations still need to be done in order If your GPU and CPU get too far out of whack with their asynchronicity fences serve to bring them back in line with each other Please see the section entitled Vertex Array Range later in this chapter for more information and an example of using fences Share Data Across Contexts When Possible If you have multiple contexts and all of them can use the same OpenGL re sources be sure to share them across contexts to eliminate redundant copies of the data See Chapter 5 for more information Metrics The overview introduced the idea of considering your application performance from a variety of perspectives including the perspective of the user as well as the perspective of the system Regardless of whether you have the same applica tion style as the one described in the overview or something more demanding such as a visual flight or driving simulator or game you ultimately need t
400. rnative Rendering Destinations eese sees 109 Off Screen Surfaces seres eese ReIRi pe e pl E Eu RR pei eu 109 ISI EE RECTE EEUU o E 110 Render to Copy to Texture csse esee 114 Framebuffer Objects odsins ete ye m eset E RUR AREE RESTER 117 SUEIDIDATY 12s dihoserdetbeebladever xrv redi dad rea dad semis 120 The Cocoa API for OpenGL Configuration 121 OVEIVICW asicpoide e pRcR e aA IC IRR T IGGEUITI OOKNPTI4A 122 NSOpenGEVIew 4i ere ry RR ER PR ERI nds Hadas SERAIS 122 hl p 133 Additional Topics 1 22 2 3 pp Rp RR paced TR ERE EXER 140 Manipulating Images and Pixels in OpenGL 140 Context Sharing se reb t rp a XE CEN eee SUE AME 141 Full Screen Surfaces sis nel pe e RR RINPERFUCRRERRRINERRPF RAE 149 Contents ix Display Capture IL IRR er p i e a E 149 Event Handling senian E RE ER AE RENES 151 Alternative Rendering Destinations eese eese 152 Pramebutter ObJectsc a seisceeste t RR pr EREPURP PRPEISES PER 153 Clopy Lo Lexbure ved eiere ii PETS OT E NETS CHRUEDEE eS 158 Pbuffer Off Screen and Other Intermediate Targets 161 Sinne eR 162 Chapter 9 The GLUT API for OpenGL Configuration 163 oua MR CHPEETTI EEEE 164 Configuration and Setup esessseee eise eee ens 165 Pixel Pormal a2 due ep eL dens se daeere teeaaeedeees 167 S UEFA il ogdu setd otbedstedac teens EEEE REEE Vedere deos 171 Chapter 10 API Interoperability 173 col P drenan a e
401. rrent IONotificationPortGetRunLoopSource notify kCFRunLoopDefaultMode printf waiting n n CFRunLoopRun return 0 Two OS X frameworks are central to the handling of sleep events CoreFoun dation and IOKit In particular CoreFoundation is responsible for dispatch ing sleep and other system events IOKit is used in this case to register your application as a listener for these events The first step in the example is to write a callback routine that will handle power management events that conform to the IOServiceInterestCallback prototype e userData is data that can be sent to the handler when registering the callback with IORegisterForSystemPower e service is the IOService whose state changed and resulted in the callback being invoked e msg is the actual msg or type of power event e msgArg is qualifying information for the message that practically speaking is used to respond to the power event As far as this callback is concerned aside from any housekeeping your applica tion may want to do there are two possible responses the system is looking for allowing the power state change or disallowing the power state change This is where things get deceiving The truth is that the only time you can disallow a power state change is when an idle sleep event occurs In this case your appli cation will be sent a kIOMessageCanSystemSleep message In response to Power Management 37 this m
402. rs will result in much less plug in management under the scenario described You can toggle the renderer retention mode by setting kCGLGORetainRenderers to either true or false kCGLGOResetLibrary is the global reset button for CGL It restores CGL to its initial state destroys all contexts and releases all plug in renderers from the list Pixel format objects and renderer information objects are not destroyed If it s not obvious here s a warning Use extreme care with this option As this is Drawables 85 another action constant CGLGetOption will return false when queried with this option Using CGL Macros With OS X Apple engineers came up with a way to avoid the cost of deter mining the CGL context from the current thread The cost of this lookup is significant because it must be done for every entry point in the OpenGL API Cumulatively speaking this context determination logic adds up CGL macros allow you as the application developer to provide some valu able information to OpenGL and thereby avoid the cost of this lookup in par ticular the name of the current CGL context for the thread you are in Using such a macro requires two simple steps First you must include the header file CGLMacros h Second you must stick to a convention for the variable name you use to define the current context You may specify this context name by defining CGL MACRO CONTEXT For example define CGL MACRO CONTEXT ctx include
403. ructure use CGLError CGLDescribeRenderer CGLRendererInfoObj rendererInfoObj long rendererIndex CGLRendererProperty property long value Seeing this function begs the obvious question How do I obtain the number of renderers referenced by the renderer info object The answer to this question is the same as for the question dealing with obtaining information about the renderers themselves That is use an enumeration value from the CGLRendererProperty enumerated array typedef enum CGLRendererProperty kCGLRPOffScreen 53 kCGLRPFullScreen si kCGLRPRendererID 70 kCGLRPAccelerated 73 kCGLRPRobust m Toy kCGLRPBackingStore 7 6 kCGLRPMPSafe 78 kCGLRPWindow 80 kCGLRPMultiScreen 81 kCGLRPCompliant 83 kCGLRPDisplayMask 84 kCGLRPBufferModes 100 kCGLRPColorModes 103 kCGLRPAccumModes 104 kCGLRPDepthModes 105 kCGLRPStencilModes 106 kCGLRPMaxAuxBuffers 107 kCGLRPMaxSampleBuffers 108 kCGLRPMaxSamples 109 kCGLRPSampleModes 110 kCGLRPSampleAlpha z x11 kCGLRPVideoMemory 120 kCGLRPTextureMemory 121 kCGLRPRendererCount 128 CGLRendererProperty The renderer count is obtained using the property kCGLRendererCount Let s go through the remaining CGLRenderProperties kCGLRPOffScreen Boolean indicating whether the renderer supports off screen rendering 72 Chapter 6 The CGL API for OpenGL Configuration kCGLRPFullScreen Boolean indicating whether the
404. ry to do this chunk on your own before the walk through we encourage you to apply what we did in the last section to create a custom view This time however we ll create our subclass based on NSView Here are the steps Create a custom View in Interface Builder named to your liking Create a custom Object in your NIB using this same class name Export this code into XCode Change the class derivation to NSView this time oF WN FR Write code to create the teapot and handle the OpenGL initialization We won t say any more about how to accomplish the XCode project setup and configuration at this point but rather will leave you to try to figure it out on your own The walkthrough here will take you through all the details if you d prefer to try it this way Create a new XCode project of type Cocoa Application This action will cre ate your project set it to link properly against the Cocoa frameworks and create a sample main program from which we ll begin If you don t feel like walking through the steps or would like to see the finished product first check out the sample code from our website www macopenglbook com Open the Resources folder and double click on the MainMenu nib icon This will open the NIB file for this project in Interface Builder Now switch to Inter face Builder In the MainMenu window double click the Window icon and drag a Cus tomView from the Library palette to the window In the Inspector
405. s In this section we ve explored one of the ways to configure a Cocoa OpenGL Surface delved into the details of how to specify a pixel format and constructed a functional application This should serve as a starting point in your exploration of Cocoa pixel format selection and OpenGL rendering in these frameworks In the next section we ll examine how you cre ate a custom NSVi ew derived class for even more flexibility NSView Now that we ve seen what NSOpenGLView can do for us let s create our own NSView based application to expose some of the functionality that NSOpenGLView performed behind the scenes Why expose this extra complex ity You may want to take this path if your application features many OpenGL 294 Appendix C The Cocoa API for OpenGL Configuration in Leopard views of the same data The technique we ll demonstrate here allows you to share data between these multiple views But whatever your needs this explo ration will show you how to attach a context to an NSView getting at the guts of how contexts are created and then do some rendering If you need precise management of a context this is the way to do it in a Cocoa application We ll end up exactly where we did before with a cozy teapot on a calming blue back ground We ll also begin where we did last time as well in XCode Launch it and we ll get started We begin with the big picture an overview of where we re going in this section If you d like to t
406. s Port bus The AGP bus has been around since 1997 when it was originally developed by Intel As we discussed a bit in the prior section on memory busses there s a strong correlation between CPU type and graphics bus type Table 3 1 shows this correlation The bandwidth numbers listed in Table 3 1 describe the theoretical maximum throughput numbers None of these numbers accounts for the protocol AGP or PCI Express overhead implicit in managing the bus traffic For instance the theoretical maximum bandwidth for 16 lane PCI Express is approximately 3 4GB s when accounting for bus protocol overhead If you then include the overhead of managing and transferring OpenGL command and data packets Data Flow and Limitations 29 Table 3 1 Processor Type and Graphics Bus Pairing CPU Bus Bandwidth MB s G3 AGP 1X 256 G4 AGP 4X 1024 G5 AGP 8X 2048 G5 16 lane PCI Express 4096 CoreDuo Core2Duo 16 lane PCI Express 4096 Xeon 16 lane PCI Express 4096 the realizable data bandwidth throughput to these devices is approximately 2 2GB s on modern hardware Despite the copious amounts of bandwidth available on modern hardware the graphics bus can still become a bottleneck This problem is much less likely if proper care is used to manage data copying as described previously How ever if you re downloading or updating a movie or animating geometry you will most likely be transferring data per frame there
407. s 0 swaps are executed as early as possible without regard to the refresh rate of the monitor For any swap interval setting n that is greater than 0 buffer swaps will occur every nth refresh of the display A set ting of 1 will therefore synchronize your buffer swaps with the vertical retrace of the display This is often referred to as vertical blank synchronized or VBL sync d kCGLCPClientStorage The client storage parameter allows for associating a single 32 bit value with a context Essentially this parameter allows applications to piggy back an arbi trary pointer or other 4 byte value onto the context so as to allow logical group ing of data with a context kCGLCPSurfaceTexture Surface texturing in OS X allows texturing from a drawable object that is associated with a context Thus surface texturing is yet another mechanism to render to a texture on OS X Given the availability of pbuffer texturing and now framebuffer objects the now twice superseded surface texturing approach is the oldest least flexible and least well maintained render to texture method on the Mac If we haven t dissuaded you yet read on Surface texturing is typically done using AGL or GLUT as both of these APIs provide a direct interface to set up surface texturing aglSurfaceTexture 66 Chapter 6 The CGL API for OpenGL Configuration and glutSurfaceTexture respectively The Mac OpenGL surface texturing API requires a surface ID If you re i
408. s API has that sort of ubiquity so if 1 We re not blind to the problems mind you but Apple is very responsive on the bug fix side of things And no the Mac platform is not perfect There are plenty of legacy APIs to be had However if you decide to write a modern Mac application the development experience is hands down better than on any other platform It s quite simply a lot of fun Why OpenGL 3 you have visions of developing for multiple platforms OpenGL is really your only option Don t feel too bad about that mandate though because once you start working with OpenGL you ll see that its performance is as good as any API out there In fact from your perspective as a developer one of the key strengths of OpenGL is the way in which you can learn core techniques once and then reap ply them many times For example the way that you create and modify indi vidual and batched graphics primitives is something that you can learn once and then apply to vertices textures shaders and more In many ways OpenGL is a great match for the Mac because both allow you to learn techniques once and reapply those same techniques repeatedly to many different object types Consistency of technique is a key aspect of why it is so easy to be productive on the Mac and of why OpenGL is a great API to use Using an open standard graphics API like OpenGL means that its design today and in the future will incorporate all of the rich and diversif
409. s large it indicates that the logical path being followed for your usage of the GL function is subop timal Large percentages of time spent in GL generally indicate a great deal of intermediate processing of the vertex or pixel texel data before it is uploaded to the graphics hardware This is known as being off the fast path Trace View The Trace view allows you to record all OpenGL calls for your application on a per context basis Figure 11 5 You can then filter the trace and save these results One of the more informative exercises using the Trace view is to set a breakpoint in CGLFlushDrawable and continue to capture a single frame s Graphics Tools 231 000 Statistics Save As Text Clear GL Function of Calls Total Time usec Avg Time usec GLTime App Time glBegin 12 18260959 1521746 66 89 12 67 60 glTeximage2D 11 1236677 112425 18 6 04 4 58 glVertex2f 1 911 971 400169 0 21 1 95 1 48 glReadPixels 5 304281 60856 25 1 48 1 13 glTexCoord2f 1 911 947 106575 0 06 0 52 0 39 glEvalMesh2 160 71704 448 15 0 35 0 27 CGLFlushDrawable 6 35604 5934 06 0 17 0 13 glBitmap 50 21515 430 32 0 11 0 08 7 Total elapsed GL function time 20490519 91 usec Estimated time in GL 75 85 Show slice 9 of 9 gt Context ID All Contexts 4 Figure 11 4 OpenGL Profiler Statistics View worth of tracing data The key difference regarding what the Trace view can pro vide you relative to what the Statistics view can deli
410. s to your existing OpenGL commands For those extensions defining entry points a slightly more complex procedure is necessary first to safely determine the func tion pointers and then to use them We ll get into that issue soon First we ll look at how to pick an extension from the many choices available especially as some come in several versions even on the same platform 256 Chapter 13 OpenGL Extensions Identification Selection Query and Usage Deciding which extension to use can warrant entire books by itself The sheer number and similarity of the many extensions in existence makes this a daunt ing process In this section we ll explain how you determine which extensions are available and how you decide which one is preferred in your particular case Though there s no quick answer given all the parameters you must consider there s always the phrase you might hear running through your head when shopping for a yacht a problem the authors would love to have If you have to ask you can t afford it We re kidding again but the point is that while own ing and using a yacht may have certain benefits it s an expensive proposition Likewise using OpenGL extensions carry a variety of direct and indirect costs including development time compatibility evaluation and testing As should be obvious by now extensions can be vendor platform and driver specific and your development test and maintenance costs will inevitabl
411. sconception is the notion that because alpha is not needed the developer should use RGB pixels rather than RGBA pixels to save space This does indeed save space in host memory but it may not save any space in VRAM considering that the silicon contains pathways for all four com ponents and doesn t really care whether you are using all four as far as per formance is concerned I can t recall the last time I witnessed an application running faster with RGB pixels than with RGBA pixels The worst part of the RGB pixels is the alignment They are 3 bytes long need we say more Thinking out loud Let s see how many RGB pixels fits in a 16 byte SIMD register Answer 51 3 Not much logic works on 51 3 pixels at a time so there definitely needs to be some slower special case handling of these pixel fragments when you invoke any transformation logic that uses the vector units You can be certain that as far as vector processing is concerned it s a lot faster to handle 4 pixels atomically than it is to handle 5 pixels piecemeal The other alignment consideration is the base address of your pixel buffer to OpenGL Is it 16 byte aligned Unless you ve done something to tweak the pointer it should be Malloc on OS X always returns 16 byte aligned addresses in the worst case For allocations exceeding a page size the malloc returns page aligned addresses What else can affect alignment How about using g1PixelStore to affect the
412. second copy of the data in the second VBO As you switch between the two VBOs to modify and draw your vertex data in time you will get similar results as with double buffered vertex data using VARs Using two VBOs in this way relies on some implicit behavior of OpenGL to achieve the same asynchronous gains that you would enjoy using VAR No tice that using this method you ll encounter some copying overhead when you call g1Buf ferSubData to update the buffers as you march along To avoid this copy and to precisely mirror the VAR double buffer method using VBOs you can use the APPLE flush buffer range extension This extension gives you the most fine grained control over your double buffering strategy Dou ble buffering with APPLE flush buffer range entails using a single ver tex buffer object with a usage value of GL DYNAMIC DRAW that is passed into glBufferData Specifying GL DYNAMIC DRAW is equivalent to specifying a vertex array storage hint of GL STORAGE SHARED APPLE It maps your VBO into AGP space allowing the GPU to fetch vertex information directly from your application allocated buffer and thereby avoiding the copy described in the two VBO approach As with the VAR double buffer approach the APPLE flush buffer range extension allows you to independently flush mark as modified the two halves of your VBO each of which contains a copy of your model s vertex data 220 Chapter 1
413. sed for handheld devices OpenGL ES would be a good OpenGL SDK to develop against Second Apple s tools for development and debugging are a lot more comprehensive in Leopard XRay in particular integrates a vari ety of debugging tools in one information view making it much easier to target certain types of bottlenecks specifically those involving data transfer Finally Leopard brings a lot of bug fixes and feature enhancements We ve got informa tion on bits and pieces of the Leopard OpenGL throughout the book But you ll have to read about the final and released version in our Leopard chapter on the website So once you have this book in your hands please go to the website and get the addendum We think you ll be pleased with the detail and additional informa tion it offers on the released version of Leopard We consider it the definitive source of independent information for OpenGL on Leopard Mac OSX 10 5 Get it by going to www macopenglbook com Preface xxvii This page intentionally left blank Acknowledgments The first edition of this book owes many thanks to many people beginning with Bob s good friend Dave Shreiner Dave and Bob have taught numerous SIGGRAPH courses together over the years and worked together at SGI Dave encouraged Bob to take on this project with Addison Wesley and was instru mental in getting it off the ground and providing advice reviews and encour agement along the way The reviewers of the bo
414. self with any specific information that may affect OpenGL rendering such as anti aliasing or stencil capability The second parameter a different NSOPenGLContext is used in the case that the context passed back by this method will be shared with the context specified Sharing a context will be explained in further detail later For our example here we simply pass in nil indicating that we want a new context that does not share any resources with any other context In this case the only failure mode for this routine would be if the pixel format specified were invalid or nil This routine ends by returning a pointer to the new context The next method we will create is an overloaded method of NSView named lockFocus NSView uses this method to make the current view the focus so that it s the target of whatever drawing commands follow Quoting the Cocoa documentation lockFocus locks the focus on the receiver so sub sequent commands take effect in the receiver s window and coordinate sys tem This command essentially tells the windowing system that we will require some specific configuration to be set up and active before we render into this window Why do we need this Well every OpenGL context is essentially a snapshot of the entire OpenGL state used during rendering Thus if you ve painstakingly configured some precise combination of OpenGL data rendering paths and other information the same context in which you ve done that work is lik
415. sion of OpenGL shading existed only as extensions Because we re likely to use shaders in combination with multiple textures we look at where we can satisfy that need as well and we find that multitexture is a core capability of OpenGL 1 3 258 Chapter 13 OpenGL Extensions Thus our alternative path will be OpenGL 1 3 plus the required extensions for shading GL_ARB_shading_language_100 GL ARB program objects GL ARB vertex shader and GL ARB fragment shader For simplicity we will handle only this alternative rendering path in our appli cation Handling OpenGL 2 0 and OpenGL 1 3 requires a fair bit of API man agement as the entry points for shading are similar but different enough that there s a fair bit of confusion We could continue to use the extension even if we were using OpenGL 2 0 so we ll just present basic principles follow the 1 3 path and provide one fallback Good So far we ve chosen and figured out two of our three path elements The final step is determining a fallback visualization We will not explore the depths of OpenGL Shading Language shading nor all the ways you could pos sibly simulate versions of your shaded visualization via OpenGL techniques In stead we ll again opt for a simple solution We ll write shaders to transform the quad as the standard OpenGL pipeline would and color it with a constant color For illustration purposes we will color our quad green if no shading is avail able ou
416. sions are almost always independent of any par ticular windowing system the GLX specification in a sense becomes required reading for any developer who works on OpenGL not just those developers who are developing applications under the X11 window system If you have uncertainty about behavior regarding shared objects consult the GLX specification the architects of OpenGL do The following data can be shared across contexts Display lists Texture objects Vertex array objects Vertex buffer objects Shader objects Pixel buffer objects Framebuffer objects Sharing OpenGL resources across contexts is also a hot topic for developer dis cussion lists This concern could well originate from the fact that sharing is not currently in part of the OpenGL specification though it is in OpenGL Longs Peak As a result OpenGL implementations follow some guidelines for shared objects but do not have to adhere to any strict rules The biggest controversy seems to be the following question What happens when an OpenGL object is deleted or modified in one context while being concurrently referenced by another For modifications this question becomes When are the changes of an object in one context reflected in another context that is sharing it In the case of deletion this conversation breaks down into two questions Should the object be deleted or should the ID for the object be removed from the object namespace If the shared object ID is dele
417. some broken environment this strategy will help us catch that error early The runtime aspects are identical to the earlier code We just call the various OpenGL shading functions Simple enough so we look at the next place where we had extension information namely the method that checks whether the extension is valid found in hasShaderExtensions Example 13 11 Example 13 9 GLEW Headers include lt GL glew h gt include lt OpenGL gl h gt include lt GLUT glut h gt Example 13 10 Our Application s OpenGL Initialization Code Using GLEW void prepareOpenGL GLenum err glewInit if GLEW_OK err NSLog GLEW Error s n glewGetErrorString err NSLog Status Using GLEW s n glewGetString GLEW_VERSION glMatrixMode GL PROJECTION glLoadIdentity glOrtho 1 1 1 1 1 100 Extension Management Libraries 271 do we have shading extensions NSLog Has OpenGL Shader d n self hasShaderExtensions if TRUE self hasShaderExtensions NSBundle res NSBundle mainBundle NSString fragsource NSString stringWithContentsOfFile res pathForResource test ofType G frag J NSString vertsource NSString stringWithContentsOfFile res pathForResource test ofType vert const char fragsource c fragsource UTF8String const char vertsource c vertsource UTF8String if defined GL VERSION 1 3 amp amp defined GL A
418. some form of initialization for your new context usually along with a pixel format For two contexts to be compatible their pixel formats must be compatible as well which is why you see these two things specified together to successfully enable sharing So what makes pixel formats incompatible On the Mac usually it s one thing incompatible renderers Thus as a rule of thumb if you can choose pixel formats that use the same renderers you can share contexts created with those pixel formats As context sharing is a very simple feat to perform we ll simply look at the code first and only then discuss what s going on Example 7 6 demonstrates how we can create two contexts the first shared with the second Example 7 6 Sharing One Context with Another in AGL create first context pixelFormat aglChoosePixelFormat amp display 1 attribs context aglCreateContext pixelFormat NULL create second context sharing with first otherContext aglCreateContext pixelFormat context aglDestroyPixelFormat pixelFormat As you can see in Example 7 6 sharing a context is as simple as passing the con text to be shared into each subsequent context creation call If as in our example there are no errors the sharable contents of the first context exist for the second In Example 7 6 we share a display list of the rendered object between two win dows We clear each window to a different color to demonstrate that they are in fa
419. ss a wholesale replacement of the CPU RAM backing store of the user desk top Virtually everything displayed on your screen is rendered and stored on the GPU even individual glyphs are cached in VRAM Undoubtedly with the enormous computing potential of modern GPUs and ever larger VRAM con figurations of these GPUs the trend toward shifting the burden of the visual process to the GPU is expected to continue If it does you can expect the video card minimum specifications to rise accordingly in the future The VRAM consideration is less important for full screen applications that essentially take over the graphics hardware as they can swap out all the other visual data from the GPU However if your application runs in a window you must take care to ensure it doesn t require all of the OS s minimum VRAM requirements to run If so you ll end up competing with the OS frequently for precious GPU resources and consequently suffer poor performance RAM Beginning with Mac OS Tiger the minimum system RAM requirements were raised from 128MB to 256MB In one sense this led to a sigh of relief from application developers that is unless you had less free memory on your 256MB configured Tiger or Leopard system than was available on your 128MB configured Panther system Historically each new version of the OS has used more than the previous version Monitoring and quantifying the available Data Flow and Limitations 31 system memory in a m
420. ssary by the OpenGL ARB and have been adopted into the specification core either directly or in some other form If you wish to see an implementation of all methods Apple for submitting ver tices in the Mac OS check out Apple s VertexPerformanceTest application see http developer apple com This application provides a comprehen sive overview of different methods of submitting vertex data Try not to get too distracted by all the possibilities Just use VBOs Vertex Array Objects Vertex arrays are designed to accommodate a number of different types of vertices such as positional information colors texture coordinates and normals Often it s natural and from an OpenGL perspective efficient to group the states associated with these arrays together Consider a model that includes positional information texture coordinates and normals It s not very efficient to have to specify each of these pointers of these arrays to OpenGL anew every time you draw a different model We show this case in Example 11 7 Example 11 7 Inefficiencies of Not Using Vertex Array Objects Draw tortoise model glVertexPointer glNormalPointer glTexCoordPointer glDrawArrays Draw hare model glVertexPointer glNormalPointer glTexCoordPointer glDrawArrays To remedy all of this redundant pointer setting Apple introduced the Vertex Array Object VAO extension VAOs encapsulate all of the current vertex array 214 Chapt
421. t for later construction _context nil return self NSOpenGLContext openGLContext if _context nil if this is our first time to initialize _context NSOpenGLContext alloc EE initWithFormat _pixelformat shareContext nil _context nil NSLog No valid OpenGL context can be NSLog G created with that pixelformat we can fail a few ways 1 bogus parameters nil pixelformat invalid sharecontext etc 2 share context uses a different Renderer than the specified pixelformat recovery techniques 1 choose a different pixelformat NSView 297 2 proceed without a shared context o return context void lockFocus NSLog myView lockFocus ensure we are ready to draw super lockFocus get our context NSOpenGLContext cxt self openGLContext ensure we are pointing to ourself as the Drawable if cxt view self cxt setView self make us the current OpenGL context cxt makeCurrentContext void prepareOpenGL NSLog myView prepareOpenGL glMatrixMode GL PROJECTION glLoadIdentity glOrtho 1 1 1 1 1 100 void drawRect NSRect rect adjust viewing parameters glViewport 0 0 GLsizei rect size width GLsizei rect size height glClearColor 0 5 8 0 glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT glMatrixMode GL MODELVIEW glLoadIden
422. t isn t shared in context sharing We begin by setting up a new project as we did for the simple Cocoa context example The exact process isn t described here except to say that you du plicate the steps from before but add a new window in your MainMenu nib and create two custom NSOpenGL derived views Your results should look like Figure 8 12 Working in XCode add an OpenGL framework dependency and ensure that your frameworks and classes appear as shown in Figure 8 13 Try building and running this application knowing that we ve not yet connected up the drawing or context sharing On the off chance that you see only one window make sure you ve added the Visible at Launch flag to your Interface Builder properties as in Figure 8 14 Finally let s look at the code necessary for context sharing There are a number of techniques for deciding which context to share but one approach that is par ticularly nice from an architectural perspective is to use an external context provider In this model we configure and create a context in a separate class and then share it with any OpenGL view that needs to render using its shared objects In our example we ll use the pattern of a singleton that is an object based wrapper around a static object This code is very straightforward so we ll 142 Chapter 8 The Cocoa API for OpenGL Configuration p s do jeuoyippy MyOpenGLView OneOpenGLView QOO I MainMenu nib MyOpenGLView
423. t so you can get work done efficiently The QuickTime 7 QTKit API is a much cleaner way of doing all the Movie Toolbox work and are the best way to work with media on the Mac So what have we accomplished here We now have a technique to open any QuickTime accessible movie to manipulate and play it and to render the frames as an OpenGL texture We don t have all the kinks worked out yet however There was a fair bit of wrangling necessary with our final image and we paid a performance penalty for that effort but there are ways to avoid that work too For now we ve got function We will have more to say on ways to im prove the download later in Chapter 11 but for now we ve achieved our basic objectives 2 The NS in all the Cocoa API names such as NSMovie stands for NextStep 190 Chapter 10 API Interoperability eoo Window Figure 10 4 Final Frame of the Movie OpenGL to QuickTime In the previous section we learned how to integrate a movie into an OpenGL application as a texture which is then usable with any object Now we ll learn how to take our rendered OpenGL data and configure it into a movie Although this task has little to do with OpenGL per se it does build on our prior NSImage experience in an earlier section and it nicely rounds out the vari ous Cocoa API discussed in Chapter 8 Knowing how to write a movie from an OpenGL application is a useful feature for lots of applications and not overly difficul
424. t to accomplish QTMovie allows reading and writing of movie data Earlier we were able to export our data from our movie using an accessor returning an NSImage and now we ll do a symmetric operation We ll fill a new movie using NSImages gathered from our application The steps are relatively simple and we ll outline them here first focusing solely on the image snap and Movie pieces 1 Create an empty Movie object 2 Read a frame from OpenGL 3 Add a frame to the Movie 4 When complete write the results to disk The idea here is very basic attach a bunch of image frames together to create a Movie QTKit working through QTMovie exposes a lot of capabilities with which you can create movies using various codecs At their core however the QuickTime 191 contents of a movie are a simple sequence of images We already know how to read a frame from OpenGL into an NSImage so we re almost completely done even before we ve looked at the code Let s update that list with the code frag ments to do the actual work and we ll leave it as an exercise for you to assemble and insert these bits and pieces in the proper places in your code So that you re not flying completely blind look at the earlier example that read data from OpenGL into an NSImage and then flesh out the following pseudocode in the appropriate places myMovie QTMovie alloc init myImage myView captureGraphicsAsImage NSRect imageArea myMo
425. tFenceAPPLE drawCompleteFence void modifyData g1FinishFenceAPPLE drawCompleteFence Modify all or some portion of the data knowing that there are no pending drawing commands for the previous contents of that data glFlushVertexArrayRangeAPPLE vtxCoordCt sizeof GL FLOAT vtxCoordArray void main init while done draw modifyData In Example 11 10 g1FinishFenceAPPLE will block all operation until all drawing has completed on the vertex array In short the VAR extension allows more asynchronous behavior between CPU and GPU permitting them to be concurrently busy more often with less blocking and effectively getting more work done Historically if you were an attendee at Apple s WWDC Conference or if you have been an Apple Developer Connection member for some time you may have seen OpenGL performance talks that advocated the double buffering of vertex data using the VAR extension This method relies on VAR to provide the asynchronous behavior needed to modify one copy of the data while drawing with another Example 11 11 shows the steps and stages involved to employ this double buffering technique with the APPLE vertex array range extension Example 11 11 Double Buffering Vertex Data Using the APPLE vertex array range Extension Specify a number of VERTICES that will by 4 KB page aligned We re using 4 byte floats for the vertices below so we will be page aligned
426. te 17 Building X11 Applications on OS X Once the software is installed building your X11 applications on OS X is similar to building them on any other Unix platform By definition this means that your X11 application builds will look different from standard native OS X application builds Specifically you will be linking against libraries in usr 1lib rather than specifying frameworks Following is a sample makefile from our x11_simple example for an OpenMotif OpenGL application on OS X Tiger Object files CXXOBJS main o oglMotif o default oglMotif Compile CXXOBJS 0 c 278 Appendix A X11 APIs for OpenGL Configuration g g Wall I usr OpenMotif include I usr X11R6 include c lt o Link oglMotif CXXOBJS g g o CXXOBJS L usr X11R6 lib L usr OpenMotif lib 1GL 1GLw 1Xm 1Xt 1X11 clean rm f o oglMotif Note the I and L options of the compile and link lines respectively They refer to the default installation directories for both X11 and OpenMotif Also note the lack of any framework options You cannot mix and match references to the Mac OS X OpenGL libraries for an X11 application As far as the build process goes X11 on OS X is quite straightforward It proba bly will not require many changes for the Mac when bringing applications from other platforms running Unix X11 Color Models X11 shows its age or seniority if you prefer with the preval
427. ted from the namespace in one context but another context continues to reference the object what happens when a new object ID is then requested in either context Configuration API Relationships 51 The Apple OpenGL implementation maintains a reference count for shared objects For most shared objects this count is kept according to bind calls to those objects In the vertex array object and framebuffer object cases the ref erence counts are kept according to the attachment state of these objects For display lists the reference count is maintained with respect to the glEndList call Thus if context A is using a certain display list while context B is concur rently redefining the contents of that display list the change made by context B will not be visible to context A until context B commits the changes with a call to glEndList When a shared object is deleted the Mac OpenGL implementation internally tags it for deletion and the object s ID is immediately made free in the namespace When the reference count for this tagged object reaches zero the object itself is deleted from memory If the reference count of a shared object tagged for deletion has not reached zero and the now freed object ID is reused things get more complicated If context A deletes shared texture 2 binds shared texture 2 again and then redefines its contents the share context B which is still bound to texture 2 will be referring to the original text
428. ted the error solid time saver indeed Graphics Tools 229 000 Breakpoints Breakpoints GL Function Before After Execute Call Stack State CGLChoosePixelFormat e 0 CGLClearDrawable e CGLComment CGLCopyContext CGLCreateContext CGLCreatePBuffer e CGLDescribePBuffer e CGLDescribePixelFormat CGLDescribeRenderer CGLDestroyContext CGLDestroyPBuffer CGLDestroyPixelFormat CGLDestroyRendererinfo e CGLDisable CGLEnable CGLFlushDrawable CGLGetCurrentContext CGLGetFullScreen CGLGetOffScreen e CGLGetOption e OOA cannes Mv Break on error Actions C Break on thread conflict L Break on VAR error Idle Continue C Ignore all breakpoints Figure 11 3 OpenGL Profiler Breakpoints View The next most useful thing in the authors opinion is the ability to delimit frames of rendering with breakpoints Most OpenGL applications follow a cycle in making GL state changes that starts at the beginning of a rendered frame and ends at the end of the rendered frame Very often all state changes that need to be evaluated when debugging or doing performance evaluation will occur in a single frame If you look at the Breakpoints view you ll notice that CGLFlushDrawable is set in a bold font This is because it is so special CGLFlushDrawable is the OS X version of swapping buffers and indicates that a frame has completed rendering Here s where the combination of view usage becomes useful By set ting
429. texdim 64 const unsigned int nbytes 3 char data texdim texdim nbytes memset data Oxff texdim texdim nbytes unsigned int ii for ii 0 ii texdim texdim ii data ii nbytes 0 Oxff luBuild2DMipmaps GL TEXTURE 2D 0 GL RGB texdim texdim 0 GL RGB GL UNSIGNED BYTE data ITexEnvi GL TEXTURE ENV GL TEXTURE ENV MODE GL REPLACE Q Q generate amp bind our framebuffer object to our texture object glGenFramebuffersEXT 1 amp fboID glBindFramebufferEXT GL FRAMEBUFFER EXT fboID glFramebufferTexture2DEXT GL FRAMEBUFFER EXT GL COLOR ATTACHMENTO EXT GL TEXTURE 2D textureID 0 glTexEnvi GL TEXTURE ENV GL TEXTURE ENV MODE GL DECAL glBindFramebufferEXT GL FRAMEBUFFER EXT 0 unbind fbo add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES The OpenGL designers did a pretty good job of keeping the design clean and consistent with that of other objects in the OpenGL system Specifically note the parallels in the setup and configuration of FBOs and texture objects In essence you simply bind the FBO do some rendering and unbind the FBO At that point the texture bound to that FBO is ready to be used We ll demon strate this usage of the FBO next even though we ve really covered it all in the set
430. th a focus on Leopard Though all the basic concepts from that chapter still apply Leopard does it a bit differently Because of that rather than trying to integrate the two we ve broken them into two tracks If you re on Tiger or earlier read Chapter 8 but if you re using Leopard check out this appendix 283 NSGL AGL CGL CoreGraphics Figure C 1 AppKit API and Framework in Overall OpenGL Infrastructure on the Mac Overview The AppKit OpenGL API is part of the overall Apple OpenGL infrastructure It constitutes a layer above CGL but also has the ability to reach down into both CGL and lower layers Figure C 1 shows where the AppKit also known as Cocoa or NSGL API and framework reside relative to other API layers The AppKit framework is typically found at System Library Frameworks but may also be in a path specific to your SDK installation As with other APIs linking against AppKit requires specification of this framework path Table C 1 NSOpenGLView In this section we will create an XCode project showing how to create a cus tom view to handle OpenGL rendering using a Cocoa UI element This project will be a foundation project that we will return to when we create other exam ples with increased functionality throughout this appendix We ll begin with the overall project setup and creation so launch XCode and we ll get started Create a new XCode project of type Cocoa Application This action wil
431. th what it takes to download an image to the hardware so let s present that method in Example 10 6 and walk through it Example 10 6 Downloading an NSImage as an OpenGL Texture unsigned int downloadImageAsTexture NSImage image unsigned int tid 0 int texformat GL_RGB convert our NSImage to a NSBitmapImageRep NSBitmapImageRep imgBitmap NSBitmapImageRep alloc initWithData image TIFFRepresentation imgBitmap retain examine amp remap format switch imgBitmap samplesPerPixel 180 Chapter 10 API Interoperability case 4 texformat GL_RGBA break case 3 texformat GL_RGB break case 2 texformat GL_LUMINANCE_ALPHA break case 1 texformat GL_LUMINANCE break default break generate a texture object glGenTextures 1 GLuint amp tid glBindTexture GL TEXTURE 2D tid download the pixels gluBuild2DMipmaps GL TEXTURE 2D GL RGBA imgBitmap pixelsWide imgBitmap pixelsHigh texformat GL UNSIGNED BYTE imgBitmap bitmapData unregister interest in the bitmap OpenGL has already downloaded the image imgBitmap release return tid While there s a bit of code here it s mostly focused on extracting data from our NSBitmapImageRep object and formatting it into the traditional g1Tex Image2D style We begin by extracting a bitmap image representation from our NSImage as we demonstrated in earlie
432. thStencil by kCGLPFAColorFloat 58 kCGLPFASupersample 60 kCGLPFASampleAlpha 61 kCGLPFARendererID 70 kCGLPFASingleRenderer XN kCGLPFANoRecovery 2 kCGLPFAAccelerated 73 kCGLPFARobust 15 kCGLPFABackingStore 76 kCGLPFAMPSafe 78 kCGLPFAWindow 80 kCGLPFAMultiScreen 61 kCGLPFACompliant 63 kCGLPFADisplayMask 84 kCGLPFAPBuf fer 90 kCGLPFARemotePBuf fer 91 kCGLPFAVirtualScreenCount 128 CGLPixelFormatAttribute Policies and Buffer Sizing Each of the policies used in pixel format selection is a scoring system to nomi nate matching pixel format candidates The policy attributes kKCGLPFAMinimumPolicyandkCGLPFAMaximumPolicy are applicable only to the color depth and accumulation buffer sizes If you specify the minimum policy then these attributes must have at least the value specified with the attribute In our example we ve requested that the pixel for mat be chosen using only pixel formats that are double buffered have at least 24 bits for the R G B color channels and that there be at least 16 bits for the depth buffer Here is the set of policy attributes kCGLPFAMinimumPolicy kCGLPFAMaximumPolicy kCGLPFAClosestPolicy Pixel Format Selection 59 The minimum policy sets the low bar for acceptance but there is another asymmetry here kCGLPFAMaximumPolicy doesn t set the high bar for ac ceptance Instead it means that if KCGLPFAColorSize kCGLPFADepthSize
433. the CPU activity of your ap plication One favorite feature in this tool is the ability to switch the icon view in the dock to CPU history You ll notice that both bars show activity on single threaded applications that use the multithreaded OpenGL engine In fact Activity Monitor is a good tool to verify that you ve successfully enabled this engine Activity Monitor is also useful for sampling applications In particular if you see an application hang and wish to report it to Apple use Activity Monitor to sample the hung process and submit your sample to Apple in the bug report Tools 227 Quartz Debug Quartz Debug allows for configuration and debugging of settings for the Quartz window server Some of the more interesting features you ll want to check out are the Window List tool and the User Interface Resolution tool The User Interface Resolution tool allows you to emulate displays having different resolutions As resolution independence is a standard feature of Leopard it is very important to qualify your application Graphics Tools OpenGL Profiler The OpenGL Profiler is probably the best thing about developing OpenGL ap plications on Mac OS X This diagnostic tool is best in class for evaluating the OpenGL state behavior of your application or perhaps even better for analyz ing another OpenGL application that you have to debug When OpenGL Profiler reached version 3 0 it really hit its stride This marked improvement
434. the blue cube and look in the Inspector window Type in the C1ass entry the name of our custom view MyOpenGLView This creates a custom object of our custom view type in the NIB and will recreate that when the NIB gets instantiated at runtime You should see something like Figure C 4 Now let s create the actual headers and code In Interface Builder go to the File menu and choose Write Class Files This will prompt you to create files for both the header and the source for this view Accept the defaults placed within your project directory Finally drag those files into your XCode project and we re set to start coding The final step in this setup operation is to change the CustomView to derive from NSOpenGLVi ew the base Cocoa View class for ren dering OpenGL content To do so open the code you ve just generated within XCode and change the MyOpenGLView h header so your project and code look like Figure C 5 We could have handled all of this setup configuration and routing programmatically but this book isn t about Cocoa plumbing so we ll stay at this level for now In a later section we ll explore Cocoa configuration of a 286 Appendix C The Cocoa API for OpenGL Configuration in Leopard NewApplication File Edit Format View Window Help Eo 4 e 8 Fides Owner First Respender Applicaton MaieMesu Window Wind QD Gee Grae 5 Figure C 4 Create and Bind an Instance of our CustomView Q7
435. the interface will update to return you to the Instances tab in the MainMenu nib window You should see something like Figure 8 4 Now let s create the actual headers and code In the MainMenu nib win dow click on the Classes tab If you re lucky MyOpenGLView will still be selected if not navigate to it and select it Click on the Classes menu and Create Files for MyOpenGLView item This will prompt you to create files for both the header and the source for this view Accept the defaults and we ll begin laying out the view in a window eoo Ei MainMenu nib Classes Images Sounds Nib cem 99 a EL amp o amp j File s Owner First Responder MainMenu Window MyOpenGLView Figure 8 4 Instantiated OpenGL View Object in Interface Builder 124 Chapter 8 The Cocoa API for OpenGL Configuration Figure 8 5 Custom View Palette in Interface Builder At this point we ve created the necessary infrastructure but we still have to place our view in our window As with most Interface Builder tasks we accom plish this by dragging and dropping and by applying a little customization We begin by dragging a Custom View into the window named Window Go to the Cocoa Interfaces window if it s not visible get there by clicking the menu Tools the submenu Palettes and then the item Show Palettes and navigate to the Custom View pane This palette can be seen in Figure 8 5 Drag the CustomView icon from the palett
436. the texture type problem by replacing GL_UNSIGNED_SHORT_4_4_4_4 with GL_UNSIGNED_BYTE Again we have twice the storage requirements but the type is hardware native Running ptm2 on our test system we see more than one frame per second Not earth shattering but a 200 percent improvement at least over the performance of ptm1 If we re going to shatter earths we need to keep tuning Figure 11 14 shows an OpenGL Profiler look at ptm2 Notice that the landscape has changed profoundly As you improve certain areas of the code other areas that were previously minor such as the glTexImage2D call at 6 percent become significant We ve reduced our glBegin hit to 39 percent but now our g1TexImage2D call has ballooned to 39 percent We also have a new player in the list g1Vertex2f is weighing in at 17 percent OpenGL time Please Tune Me 3 To address the g1TexImage2D problem we saw in ptm2 c ptm3 c moves the texture definition logic out of the rendering loop and into the initialization routine In its place we use texture binding In effect we ve replaced immediate mode logic with retained mode logic Making this retained mode change gave us a nice performance boost of 100 percent moving us to nearly two frames per second Still not a galactic contender but we can now see the teapot tumbling Let s see what Profiler has to say about ptm3 in Figure 11 15 With ptm3 we re seeing a nic
437. ting an application up and running and has its uses when you are submitting limited amounts of data to OpenGL Generally speaking though with a com bined 25 years of looking at this stuff your authors have definitely seen egre gious overuse of this capability within OpenGL and it definitely leads to slow applications The simplicity of this mode of rendering is in that data are submitted through OpenGL commands at the precise moment they are needed for rendering hence the immediate in immediate mode Because of this and knowing that commands are executed in order in OpenGL following this sort of OpenGL logic is easiest You do not need to keep any timing tables in your head nor do you need to worry about any asynchronicity between the CPU and the GPU Because of this simplicity as you probably well know immediate mode render ing is the first thing taught to developers who are new to OpenGL Our guess is that the pervasive use of this style of code may be simply a matter of habit At some point to prevent abuses and save all our companies a lot of money imme diate mode rendering may even be removed from OpenGL entirely or perhaps relinquished to some layered API just to give it a scarlet letter 198 Chapter 11 Performance With immediate mode rendering data are downloaded from host memory to VRAM for every frame of rendering whether its vertices between a glBegin glEnd pair textures images or shaders This redu
438. tion 11 power management in 34 38 tools 226 28 version history 17t 33 34 34t P Panther see also OS X improvements of 246 OTKit in 185 renderer support 12t parallel extensions 8 Pascal programming language 2 pbuffers 78 81 79t 110 13 110t 113f 161 62 208t 321 22 PCI Express 29 30 30t pixel buffer objects 11t 241 42 pixel buffers 78 81 79t 110 13 110t 113f pixel data from NSImage 178 79 179t pixel data alignment 224 25 pixel data processing 26 pixel format and texture data handling 221 23 in AGL 91 109 in CGL 57 63 in GLUT 167 70 167f 169t 170t Pixel Format view 234 234f pixel manipulation 140 41 pixel pipeline 223 24 pixel types 221 23 Pixie 235 236f Please Tune Me 237 43 239f 240f 241f 242f 243f plug in architecture 17 18 18f point parameters 10t polygon offset 9t power management 34 38 PowerPC 42 43 Profiler 228 34 229f 230f 232f 233f 234f 235f programmable shading 11t ptm1 c 238 39 239f ptm2 c 240 240f ptm3 c 240 41 241f ptm4 c 241 ptm5 c 241 42 242f Puma see also OS X release of 17t Q OTKit 184 88 191 92 OTMovie 186 87 191 92 quad buffering 61 Quartz 15 16 46 47 Quartz 2D 31 Quartz Debug 228 QuickTime 184 92 R range extensions 205 7 read only parameters 68 read write parameters 66 67 render targets 60 61 render to texture 114 17 158 61 renderer support 12t 13t 13 14 renderers 18 21 and intermediat
439. tion y NSDrawer NSWindow NSWindowController Search 0 O java lang Object NSFormatter gt NSImage NSMenu NSMenultem NSMovie NSBox NSClipView NSControl gt NSMovieView NSOpenGLView NSProgressIndicator NSQuickDrawView NSRulerView NSScrollView NSSplitView NSTableColumn NSTabViewltem SCNibObjectinfo 1 SCNibObjectinfoManage Figure 8 10 Subclassed NSOpenGLVi ew in Interface Builder create files for both the header and the source for this view Accept the defaults and we ll begin laying out the view in a window We now need to place our view in our window and designate it to be our MyView object Drag a Custom View into the window named Window Go to the Cocoa Interfaces window as before and navigate to the Custom View pane Drag one of those icons into your Window and arrange it as in Figure 8 6 Finally modify the CustomView to be your MyView object by opening the Inspector as before Choose the Custom Class pop up menu entry in the Inspector window and navigate and choose MyView from the list You should see the results shown in Figure 8 11 MyView Figure 8 11 Myview Binding in Interface Builder NSView 135 With that configuration out of the way we move straight into the code phase Save your MainMenu nib and switch to XCode As before with the NSOpenGLView derived project we ll do many of the same things includ
440. tion context The call to CGLUpdateContext or aglUpdateContext must be done explicitly with Carbon applications but is done implicitly on your behalf with Cocoa applications A word of caution here Because implicit calls are made by the AppKit classes that modify the internal graphics context state of a renderer serious thread safety issues arise that must be considered If for instance your application has a drawing thread that is modifying your application context while in another thread your NSOpenGLView instance is implicitly issuing calls to synchronize your application context with that of the renderer memory corruption and a crash will likely result To avoid these thread safety issues CGLLockContext and CGLUnlockContext can be called to resolve thread contention issues You can find out more about these functions in Chapter 6 In addition to context synchronization there is another key aspect to handling virtual screen changes If you plan to allow your application to move between virtual screens that is between different graphics devices you must create a pixel format that is compatible with all graphics cards installed on the sys tem In CGL this is done by using a display mask the kCGLPFADisplayMask attribute You ll find more information on display masks in Chapter 6 So we now must consider this common question What happens when my application is straddling two different renderers In this case whichever ren der
441. tity glTranslatef 0 0 1 GLfloat green 4 0 1 0 0 glMaterialfv GL_FRONT_AND_BACK GL_AMBIENT_AND_DIFFUSE green glutSolidTeapot 5 298 Appendix C The Cocoa API for OpenGL Configuration in Leopard self openGLContext flushBuffer end In our MyView m file we start by looking at our initWithFrame overloaded method This method is called when our object is getting constructed with the desired layout of this particular view As with our MyNSOpenGLVi ew class this method is where we set up our pixel format and prepare the rest of our class for subsequent use In fact the majority of the code in this method is identical to the code given earlier with a slight inversion We initialize the parent first and then based on success there create a pixel format We end this method by initializing our context member to nil in preparation for configuring it later The next method openGLContext is the body of what we declared in the header This method s intent is to hand the caller a pointer to the context used by this view It begins by checking whether the existing context is empty if so it creates a context using the existing pixel format we created earlier and calls the NSOpenGLContext constructor initWithFormat NSOpenGLContext This constructor takes two parameters a pixel format and either another NSOpenGLContext pointer or nil The pixel format parameter is used by the context to configure it
442. tly Closest Choose a match closest to the size specified but not necessarily an exact match Minimum Require a match of at least this size Can choose larger sizes Maximum Require a match of at most this size Prefers larger sizes NSOpenGLView 289 Table C 3 Common Pixel Format Qualifiers for Use with NSOpenGLPixelFormat Token Description NSOpenGLPFAAllRenderers Look in entire set of renderers to find a match Type Boolean YES Search entire set of available renderers including those that are potentially non OpenGL compliant Default YES Policy Any NSOpenGLPFADoubleBuffer Double buffer requirements Type Boolean YES Search only for a double buffered pixel format NO Require a single buffered pixel format Default NO Policy Any NSOpenGLPFAStereo Stereo requirements Type Boolean YES Require a stereo pixel format NO Require a monoscopic pixel format Default NO Policy Any NSOpenGLPFAAuxBuffers Auxiliary buffer requirements Type Unsigned integer Number of auxiliary buffers required by this pixel format Default NA Policy Smallest NSOpenGLPFAColorSize Color bits requirements Type Unsigned integer Number of color buffer bits required by all color components together Default If this token is not specified a ColorSize that matches the screen is implied
443. to keep track of throughout our view class We then look at the initialization code which is again very similar to the FBO example but now without the FBO configuration Example C 15 Example C 15 OpenGL Setup for Copy to Texture Rendering void prepareOpenGL lMatrixMode GL_PROJECTION ILoadIdentity lOortho 1 1 1 1 1 100 IMatrixMode GL MODELVIEW Q Q QQ enable generate and bind our texture objects lEnable GL TEXTURE 2D lGenTextures GLsizei 1 amp textureID IBindTexture GL TEXTURE 2D textureID const unsigned int texdim 64 const unsigned int nbytes 3 unsigned char data texdim texdim nbytes memset data 0 texdim texdim nbytes unsigned int ii for ii 0 ii texdim texdim ii Q OQ OQ data ii nbytes 0 Oxff H gluBuild2DMipmaps GL TEXTURE 2D 0 GL RGB texdim texdim 0 GL RGB GL UNSIGNED BYTE data glTexEnvf GL TEXTURE ENV GL TEXTURE ENV MODE GL REPLACE Alternative Rendering Destinations 319 add a timer to oscillate the modelview NSTimeInterval ti 1 NSTimer scheduledTimerWithTimeInterval ti target self selector selector angleUpdate userinfo nil repeats YES As before our main drawRect routine does the bulk of the work but here is where the code differs from the FBO version Let s look at it now in Example C 16 and talk about the differences and caveats to this technique Exa
444. ts or exceed reqs 0 ub _pixelformat NSOpenGLPixelFormat alloc initWithAttributes NSOpenGLPixelFormatAttribute attributes if _pixelformat nil NSLog SharedContext No valid OpenGL pixel format matching attributes specified at this point we d want to try different sets of pixelformat attributes until we got a match or decided we couldn t create a proper working environment for our application else _context NSOpenGLContext alloc initWithFormat _pixelformat shareContext nil return self NSOpenGLPixelFormat pixelFormat return _pixelformat Additional Topics 305 NSOpenGLContext context return context SharedContext instance if sharedContext nil _sharedContext SharedContext alloc init return _sharedContext end If you re familiar with the singleton pattern the instance method and idea should be familiar to you If not consult the classic Design Patterns book by the notorious Gang of Four 16 Essentially instance provides a handle to our static context manager object Upon its creation this object allocates a pixel for mat and a context based on that pixel format This code should look familiar as we ve written code similar to it earlier in this book The only caveat when writ ing context sharing code of your own is to keep in mind that any context that is meant to be shared must be
445. tutions of the type of data created and the target parameter of the buffer object OpenGL calls i e GL ARRAY_BUFFER or GL ELEMENT ARRAY BUFFER instead of GL PIXEL PACK BUFFER Example 11 3 Partial Buffer Object Flushing GLuint pboID GLint width height channels GLubyte textureData 2048x2048 image GL RGBA width 2048 height 2048 channels 4 textureData GLubyte malloc width height channels Generate ID for PBO glGenBuffers 1 amp pboID Bind PBO dimension it and supply it data glBindBuffer GL PIXEL PACK BUFFER pboID glBufferData GL PIXEL PACK BUFFER width height channels textureData GL DYNAMIC DRAW Tell GL we want to do partial flushing on this object Setting GL BUFFER FLUSHING UNMAP APPLE to false tells OpenGL not to flush the contents of the PBO to VRAM when the PBO is unmapped glBufferParameteriAPPLE GL PIXEL PACK BUFFER GL BUFFER FLUSHING UNMAP APPLE GL FALSE We re done with the PBO for now so unbind it glBindBuffer GL PIXEL PACK BUFFER 0 Don t need to keep the malloc d texture data buffer around now that the PBO has it free textureData later modify the texture stored in the PBO GLubyte texturePtr glBindBuffer GL PIXEL PACK BUFFER pboID texturePtr glMapBuffer GL PIXEL PACK BUFFER GL READ WRITE Use texturePtr to modify a portion of the texture 206 Chapter 11 Perfo
446. u to the OpenGL framebuffer object extension for complete details Before we leave the topic of FBOs we d like to point out a few more reasons why FBOs are superior to other forms of off screen rendering First FBOs con sist of memory allocated on the graphics card itself that is directly usable in its target form for example as a texture As a consequence you avoid any off card copies to and from the host You can even avoid on card copies in good implementations of the extension Second FBOs present a consistent platform agnostic interface There just isn t a simpler interface to intermediate render ing than FBO largely due to the evolutionary process by which OpenGL is developed A variety of intermediate target rendering APIs and implementa tions were explored over the years culminating in the design and implemen tation that exists today FBOs are the best choice for modern rendering on the Mac Third FBOs avoid expensive context switching that can cost you a great deal of performance Copy to Texture In this section we describe a very common and widely available technique known as render to texture Render to texture is as simple as it sounds You simply render your intermediate scene copy it to a texture and then use that texture in your final render Elegant simple and concise There are of course details to deal with concerning how you target the texture into which you want to render and in some cases how you mo
447. uerying renderers prior to their use is sometimes help ful if you have specific needs say pbuffers and need to ensure that your renderer can support them Most commonly however you ll want to use an AGL ACCELERATED renderer and keep within its capabilities to have the best performance possible On systems with multiple graphics cards you might 106 Chapter 7 The AGL API for OpenGL Configuration Table 7 3 Tokens for Use with agl1DescribeRenderer Token Description AGL_FULLSCREEN Supports full screen applications AGL_RENDERER_ID Renderer ID value AGL_ACCELERATED Supports hardware acceleration AGL_ROBUST Has no failure mode for lack of resources AGL_BACKING_STORE Has copy on swap back buffer AGL_WINDOW Supports render to window AGL_MULTISCREEN Can support multiple screens with the same AGL context AGL_COMPLIANT Supports offline pixel buffer rendering AGL_PBUFFER Supports pbuffer rendering AGL_BUFFER_MODES Supports bitwise OR of mono stereo single and double constants from AGL agl h AGL MIN LEVEL Minimum overlay or maximum underlay if negative plane value AGL MAX LEVEL Maximum overlay plane value AGL COLOR MODES Supports bitwise OR of color mode constants from AGL agl h color buffers AGL ACCUM MODES Supports bitwise OR of color mode constants from AGL agl h
448. uffer objects VBOs PBOs e Texture objects e Vertex and fragment programs and shaders e Frame buffer objects FBOs Now that we have an overview of how context sharing works let s walk through some code For purposes of this example we will build a two windowed version of our earlier Cocoa example in which we created a custom context In this case we ll modify the example to share the context between the two views and surfaces render some shared data a display list and visualize the data in two views each with a different color background color The plan is to demonstrate what is and what isn t shared in context sharing We begin by setting up a new project as we did for the simple Cocoa context example The exact process isn t described here except to say that you duplicate the steps from before but add a new window in your MainMenu nib and create two custom NSOpenGL derived views Your results should look like Figure C 7 Working in XCode add an OpenGL framework dependency and ensure that your frameworks and classes appear as shown in Figure C 8 Try building and running this application knowing that we ve not yet connected up the drawing or context sharing On the off chance that you see only one window make sure you ve added the Visible at Launch flag to your Interface Builder properties as in Figure C 9 Finally let s look at the code necessary for context sharing There are a number of techniques for deciding which co
449. unrelated tasks the bigger your gains from threading will be Gains in performance of 50 percent for properly threaded applications are not unusual When threading your OpenGL application on Mac OS X you must remember to use the CGLLockContext and CGLUnlockContext calls to bracket your OpenGL calls for each thread This guarantees that you will not experience state change collisions and bizarre unanticipated behavior when rendering with multiple threads To relieve application developers of the burden and complexity of threading their applications the Apple OpenGL engineering team decided to thread OpenGL with the first release being on the Mac Pro system and its initial installed software 10 4 8 The complete form of the threaded engine will be released with Mac OS 10 5 Leopard Threading done within OpenGL itself ef fectively achieves the same goal as threading your application namely rapid return of control to the application after a function call into the OpenGL API 202 Chapter 11 Performance By minimizing the time needed to return control to the application the threaded OpenGL engine in the Mac OS allows more processing cycles for the application logic The threaded OpenGL engine fundamentally does more work than the stan dard serial engine It relies on an additional processor to handle this extra work The good news is that you don t have to detect the number of processors on the system to use it If you attem
450. up It couldn t be much simpler Example C 12 shows our drawRect routine Alternative Rendering Destinations 315 Example C 12 Cocoa drawRect Routine for FBOs void drawRect NSRect rect render to offscreen glBindFramebufferEXT GL FRAMEBUFFER EXT fboID self drawIntermediateContents glBindFramebufferEXT GL FRAMEBUFFER EXT 0 render to final self drawFinalContents complete rendering amp swap glFlush self openGLContext flushBuffer H Finally for interest we present the code we actually draw with in those routines in Example C 13 Example C 13 Cocoa Draw Methods for Contents of the FBO and the Final Render void drawIntermediateContents lClearColor 1 1 0 1 IClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT IMatrixMode GL MODELVIEW ILoadIdentity ITranslatef 0 0 1 IColoEg3f 0 1 l lBegin GL QUADS loat ww 9 loat hh 9 loat zz 0 0 IDisable GL TEXTURE 2D lVertex3f ww hh zz lVertex3f ww hh zz lVertex3f ww hh zz lVertex3f ww hh zz LEnd Q Q Q 0 Eh Fh Fn 0 I Q1 Q 0 0 void drawFinalContents glClearColor 0 5 8 1 glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT glMatrixMode GL MODELVIEW glLoadIdentity glRotatef angle 0 0 1 glTranslatef 0 0 1 giCcolor3f 0 1 0 glBindTexture GL TEXTURE 2D textureID 316 Ap
451. urce file We also declare two methods openGLCon text and prepareOpenGL named to emulate the behavior of the Cocoa supplied NSOpenGLView openGLContext will be used to return the current context or to create one if none exists prepareOpenGL will be used as our first call to our OpenGL context to initialize the basic OpenGL functionality as we did before for our MyNSOpenGLView class That s all there is to do in the header so let s look at the source see which other methods we ve overloaded from NSView and see how the code behind these signatures works Example C 4 Myview m Final Code include lt OpenGL gl h gt include lt GLUT glut h gt import MyView h implementation MyView id initWithFrame NSRect frameRect 296 Appendix C The Cocoa API for OpenGL Configuration in Leopard NSLog myView initWithFrame if self super initWithFrame frameRect nil GLuint attributes NSOpenGLPFAWindow NSOpenGLPFAAccelerated NSOpenGLPFADoubleBuffer NSOpenGLPFAColorSize 24 NSOpenGLPFAAlphaSize 8 NSOpenGLPFADepthSize 24 NSOpenGLPFAMinimumPolicy select a pixelformat which meets or exceeds these requirements 0 _pixelformat NSOpenGLPixelFormat alloc if initWithAttributes NSOpenGLPixelFormatAttribute attributes _pixelformat nil NSLog No valid OpenGL pixel format NSLog matching attributes specified init the contex
452. ure 8 1 shows where the AppKit also known as Cocoa or NSGL API and framework reside relative to other API layers The AppKit framework is typically found at System Library Frameworks but may also be in a path specific to your SDK installation As with other APIs linking against AppKit requires specification of this framework path Table 8 1 NSOpenGLView In this section we will create an XCode project showing how to create a cus tom view to handle OpenGL rendering using a Cocoa UI element This project will be a foundation project that we will return to when we create other exam ples with increased functionality later in the book We ll begin with the overall project setup and creation so launch XCode and we ll get started Create a new XCode project of type Cocoa Application This action will cre ate your project set it to link properly against the Cocoa frameworks and create a sample main program from which we ll begin If you do not feel like walking through the steps or would like to see the finished product first check out the sample code from our website www macopenglbook com Table 8 1 AppKit Cocoa Headers Frameworks and Overview Framework path System Library Frameworks AppKit framework Build flag framework AppKit Header include lt AppKit NSOpenGL h gt 122 Chapter 8 The Cocoa API for OpenGL Configuration eoo MainMenu nib instances Classes Images Sounds Nib
453. ure object that was backing texture ID 2 If share context B then rebinds that same texture 2 because the binds are the reconciliation point it will now refer to the new texture that was defined for texture ID 2 back in context A Things get really complicated if the shared object state is queried in the midst of all of these concurrent operations Again this isn t a problem unique to the Mac OpenGL implementation but consider this scenario Context A and context B share texture object 2 Context B is currently bound to texture object 2 Context A calls g1DeleteTexture 2 Context B calls g1Get GL TEXTURE BINDING the return value is 2 If context A and context B now check the contents of texture object 2 they get different answers Lj e Context B calls g1IsTexture 2 the return value is GL FALSI Now if context B rebinds to that same texture object 2 it will no longer be refer ring to the original texture object because context A deleted it and the binds are the reconciliation point So rebinding to the same object ID gives you a different object To avoid ever confronting the confusion of the preceding scenario it s a good idea to strictly conform to the OpenGL specification when it comes to shared ob ject management OpenGL applications are solely responsible for maintaining 52 Chapter 5 OpenGL Configuration and Integration the integrity of shared objects across contexts This is n
454. ure the display 2 Configure and display a full screen window 3 Handle events 4 Release the display It s important to ensure that both event handling and teardown or display release occur If they do not you ll probably get into a deadlock of some sort one in which either you can t do anything with your application or other ap plications move to the foreground respectively You re almost guaranteed to experience this problem once unless you re really listening to me here and you ll never repeat the mistake rebooting in the middle of your development cycle is a pretty good deterrent The specifics of display capture and release are sketched out in Example C 8 Please read Apple s developer documentation on the methods described here for additional information Because these methods are so fundamentally simple we will just show you the code and have you use it without further discussion Additional Topics 309 Example C 8 Capturing and Releasing the Display AE Captures all displays returning true false for success failure So bool capturedDisplaysLoop bool error false CGDisplayErr err CGCaptureAllDisplays if err CGDisplayNoErr failure maybe another application is already fullscreen error true else your code here open fullscreen window your code here event handler loop stay here until no longer in fullscreen mode upon exit we transition back to windowed m
455. use In fact the majority of the code in this method is identical to the code given earlier with a slight inversion We initialize the parent first and then based on success there create a pixel format We end this method by initializing our context member to nil in preparation for configuring it later The next method openGLContext is the body of what we declared in the header This method s intent is to hand the caller a pointer to the context used by this view It begins by checking whether the existing context is empty if so it creates a context using the existing pixel format we created earlier and calls the NSOpenGLContext constructor initWithFormat NSOpenGLContext This constructor takes two parameters a pixel format and either another NSOpenGLContext pointer or nil The pixel format parameter is used by the context to configure itself with any specific information that may affect OpenGL rendering such as anti aliasing or stencil capability The second parameter a different NSOpenGLContext is used in the case that the context passed back by this method will be shared with the context specified Sharing a context will be explained in further detail later For our example here we simply pass in nil indicating that we want a new context that does not share any resources with any other context In this case the only failure mode for this routine would be if the pixel format specified were invalid or nil This routine ends by return
456. ust viewing parameters glViewport 0 0 GLsizei rect size width GLsizei rect size height 132 Chapter 8 The Cocoa API for OpenGL Configuration glClearColor 0 5 8 0 glClear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT glMatrixMode GL MODELVIEW glLoadIdentity glTranslatef 0 0 1 GLfloat green 4 0 1 0 0 glMaterialfv GL FRONT AND BACK GL AMBIENT AND DIFFUSE green glutSolidTeapot 5 self openGLContext flushBuffer end If you see a teapot success In this section we ve explored one of the ways to configure a Cocoa OpenGL Surface delved into the details of how to specify a pixel format and constructed a functional application This should serve as a starting point in your exploration of Cocoa pixel format selection and OpenGL rendering in these frameworks In the next section we ll examine how you cre ate a custom NSVi ew derived class for even more flexibility NSView Now that we ve seen what NSOpenGLView can do for us let s create our own NSView based application to expose some of the functionality that NSOpenGLView performed behind the scenes Why expose this extra complex ity You may want to take this path if your application features many OpenGL views of the same data The technique we ll demonstrate here allows you to share data between these multiple views But whatever your needs this explo ration will show you how to attach a context to an
457. values includes e kCGLOBit e kCGL12Bit e kCGL1Bit e kCGL16Bit e kCGL2Bit e kCGL24Bit e kCGL3Bit e kCGL32Bit e kCGL4Bit e kCGLA8Bit e kCGL5Bit e kCGL64Bit e kCGL6Bit e kCGL96Bit e kCGL8Bit e kCGL128Bit e kCGL10Bit Context Management 75 kCGLRPMaxAuxBuffers The maximum number of auxiliary buffers supported by the renderer kCGLRPMaxSampleBuffers The maximum number of independent sample buffers supported by the ren derer This renderer property generally reduces to a Boolean value If a multi sample buffer exists for the renderer KCGLRPMaxSampleBuffers will be set to 1 otherwise it is set to 0 kCGLRPMaxSamples For multisampling kCGLRPMaxSamples indicates the maximum number of samples per pixel that are supported by the renderer kCGLRPSampleModes Bitwise OR of sampling modes supported by the renderer The constants avail able for kKCGLRPSampleModes include kCGLPFAMultisample kCGLPFASu persample and kCGLPFASampleAlpha kCGLRPSampleAlpha When multisampling this Boolean indicates whether the alpha component along with the color components is multisampled kCGLRPVideoMemory Indicates the number of bytes of video memory on the graphics card associated with the renderer For software renderers where host memory is used for video memory 0 is reported as this attribute s value kCGLRPTextureMemory Indicates the number of bytes of texture memory configur
458. ve pixels around the sys tem into your final texture Nevertheless the process is largely as simple as described Render to texture is interesting because it s a widely available tech nique and offers relatively high performance There are problems with it too It s not as clean as the most modern OpenGL technique of FBOs and there may be extra data copies Overall however it works pretty well Performance is pretty good though not as consistently good as using FBOs Even so you may sometimes run into problems when using cards from different vendors on which this technique is actually moderately expensive But if you can t use FBOs and this is the best alternative available you gotta do what you gotta do The essence of the render to texture technique is actually a bit simpler than the FBO example presented earlier The code is virtually the same but we omit the pieces of the rendering that relate to the FBO We begin by looking at the header for our custom view Example C 14 318 Appendix C The Cocoa API for OpenGL Configuration in Leopard Example C 14 Custom View Header for Copy to Texture Example Code import lt AppKit NSOpenGL h gt import lt Cocoa Cocoa h gt interface MyOpenGLView NSOpenGLView GLuint textureID float time float angle void angleUpdate NSTimer tt void reshape end Because we re only going to render and copy into a texture that s the extent of the information we need
459. ver take pains to validate that the results of each of these alloc init pairs succeeds Each init method will return ni 1 if it fails to find or acquire the resource specified either a file or a URL A third technique commonly used to create an NSImage is initWithData but we ll explore it later For now let s move on to extracting the data from our NSImage and using it with OpenGL Cocoa Image NSImage 175 NSImage to OpenGL Assuming we ve got a valid NS Image from some source either from initializ ing one from a file or URL or from another Cocoa API somewhere we poten tially need to do some data massaging and conversion to transform the image data into a form that is compatible with OpenGL The major phases of this pro cess are as follows 1 Determine the basic NSImage parameters such as format data size and im age size 2 Ensure that the NSImage is sized for use with OpenGL 3 Extract the pixel data 4 Download the pixel data as a texture We ll begin by looking at what s necessary to use any formatted image data with OpenGL We assume that you have a basic familiarity with the basics of OpenGL texturing and refer other questions to 22 As a quick refresher recall that unextended OpenGL that is any OpenGL version prior to 2 0 without non power of two extensions requires textures to be sized as a power of two If your input image is not a power of two initially and your OpenGL implement
460. ver is the order of OpenGL calls which of course can make all the difference when it comes to performance tuning O00 Trace ce ES Save As Text B8 us B8 us 88 us 68 us B8 us 5 us 94 us B8 us 48 us HS 31 us 83 us 76 ps 56 ps 56 us 25 us 14 us 34 us 68 us 49 ps 41 59 ys 375 82 us T Be m 60 C C CO Co C C a CO C0 CO o 0 9 9 in ES Show call sample filter i D wy Open Browse Filter RS Save Using Filter Trace Refresh Clear CGLDescribePixelFormat Bx88426c20 2147483648 CGLCreateContext 6x80426c20 x 8000000 Ox01815408 CGLSetParameter Bx84815400 4329856 CGLSetParameter 8x861815488 8 8 CGLSetSurface Bx8181548080 180 78 1024 534 0 22 1024 5121 glScissor 8 8 1824 512 glViewport B 8 1024 512 CGLDestroyPixelFormat 8x88426c28 glClearColor 80 6 glEnab le GL_BLEND glClear GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT glGet Integerv GL_MAX_TEXTURE_SIZE Exbffffe3c glMatrixMode GL_PROJECTION glLoadIdentity gl rtho B 3 03865e 319 8 3 03865e 319 3 04498e 319 3 83865e 319 glMatrixMode GL MODELVIEW glLoadIdentity glTexGeni GL S GL TEXTURE GEN MODE 92185 glTexGeni GL T GL TEXTURE GEN MODE 9218 glViewport 0 B 1824 5125 0 e glCLear GL COLOR BUFFER BIT GL DEPTH BUFFER BIT 4 CGLF LushDrawab Le a KIT Tol Call Stack Function calls
461. vie addImage myImage forDuration duration withAttributes attr myMovie writeToFile filename mov withAttributes attr This pseudocode is all we ll provide in the book The technique is really just as simple as we ve described here and we re confident that you ve got what you need to proceed If you d like to see build and compile a complete example of this technique please check our website www macopenglbook com for an up to date example High Performance QuickTime in OpenGL This chapter has described how to get the contents of a movie to play and be read by OpenGL A quick running of this example will make it clear that the image data path is not the most optimized however In fact it s downright slow We ve chosen to follow the NSImage path because it s so nicely symmet ric across a variety of Mac OS X APIs Unfortunately it s not the most perfor mance oriented and it s not suitable at this point for real time use So what s a developer to do Apple provides an excellent instructive example on its website in the OTCoreVideo101 example 10 The short version of this demo s action is pretty simple Let Core Video handle the entire process from loading and playing the movie to downloading those images as textures This may sound like delegating a lot to an API In reality underneath all the fancy UI goodness that the Mac provides it s all OpenGL already so doing this does not present any extra work for the API I
462. view m Final Code include lt OpenGL gl h gt include lt GLUT glut h gt import MyView h implementation MyView id initWithFrame NSRect frameRect 136 Chapter 8 The Cocoa API for OpenGL Configuration NSLog myView initWithFrame if self super initWithFrame frameRect nil GLuint attributes NSOpenGLPFAWindow NSOpenGLPFAAccelerated NSOpenGLPFADoubleBuffer NSOpenGLPFAColorSize 24 NSOpenGLPFAAlphaSize 8 NSOpenGLPFADepthSize 24 NSOpenGLPFAMinimumPolicy select a pixelformat which meets or exceeds these requirements 0 _pixelformat NSOpenGLPixelFormat alloc if initWithAttributes NSOpenGLPixelFormatAttribute attributes _pixelformat nil NSLog No valid OpenGL pixel format NSLog matching attributes specified init the context for later construction _context nil return self NSOpenGLContext openGLContext if _context nil if this is our first time to initialize _context NSOpenGLContext alloc EE initWithFormat _pixelformat shareContext nil _context nil NSLog No valid OpenGL context can be NSLog G created with that pixelformat we can fail a few ways 1 bogus parameters nil pixelformat invalid sharecontext etc 2 share context uses a different Renderer than the specified pixelformat recovery techniques 1 choose a di
463. w We ll explore the OTKit API the Movie Toolbox and the existing Cocoa NSMovie API here starting with the core Cocoa functionality for movie manipulation NSMovie is the Cocoa representation of a movie as managed by the Quick lime engine NSMovieView is the visual representation or view of that NSMovie QuickTime data Both are legacy classes and for new applications are not the best way of approaching the QuickTime rendering problem They are sufficient if you want to put video in a portion of a Cocoa application but these classes don t have the depth and complexity necessary to get your data into OpenGL okay it s possible but we don t really want to encourage you to follow this path As another disincentive to use these classes Apple has publicly stated that it intends to deprecate them so using these classes now would be something of a poor choice We won t really focus on NSMovie and NSMovieView any further other than to say that they exist and that there s a lot of information available in the Apple developer documentation and website if you really must know more However the modern way of doing this stuff is the new OTKit so we will focus on it for the central element of this section OTKit is Apple s replacement for its other Cocoa NSMovie APIs It supports all of what was possible before with NSMovie APIs but adds numerous edit ing and movie manipulation capabilities QTKit became available with Quick Time 7 and is part of T
464. w with a Shared Context 306 Capturing and Releasing the Display 310 Custom Controller Event Handling Loop in a Full Screen Context st 2cnuentee vet ROTE ERUPE neon 311 Custom View Header for FBO Example Code 314 OpenGL Setup for FBO Rendering useuuuesn 315 Cocoa drawRect Routine for FBOs suusuue 316 Cocoa Draw Methods for Contents of the FBO and the Final Render rsrsrsr Eee Ree ERE REY ees 316 Custom View Header for Copy to Texture Example Code o2osoctentiasthe eR een Red nauem itai 319 OpenGL Setup for Copy to Texture Rendering 319 Cocoa drawRect Routine for Copy to Texture REMOTING is s cundo ucenetecc nieder ined diede 320 Examples xxiii This page intentionally left blank Preface The Mac is a computing platform that virtually defines ease of use consistency and effortless computing The story of OpenGL on the Mac has been shall we Say a bit more complex With the arrival of OS X the Mac platform sup ports even more ways of constructing OpenGL applications for the Mac While there has been an apparent proliferation of OpenGL interfaces for the Mac the platform itself has stabilized architecturally and programmatically and now offers the best developer and user experience in the industry for develop ment of graphics applications This is not just a statement of preference but an observation that in many ways the Mac is an OpenGL platform with
465. way at other barriers such as conditionals loops rendering to multiple surfaces simultaneously and entirely virtualized shading engines General purpose computing on GPUs GPGPU is a growing topic of importance in the graphics world The overall hardware architecture of today s Macs consists of one or more CPUs with memory a GPU with memory and a bus over which the two communicate Macs like PCs have a CPU northbridge and southbridge The northbridge is the 23 PCle Link GPU o Northbridge CPU E Memory Bus Front side Bus PCle Card 0 Southbridge ATAG AS us EL pcie Links PCle Card n Figure 3 1 Prototypical System Architecture Diagram pathway to the memory controller and memory The southbridge is the pathway to all other devices installed in the system including PCI AGP and PCI Express Peripheral Component Interconnect devices such as graphics cards In this chapter we ll dig into the hardware architecture of modern and histori cal Macintoshes to provide context relevant to graphics developers We ll point out some obvious bottlenecks and some ways of considering data flow within a system so as to maximize graphics performance Armed with a few observa tions about hardware and how your software interacts with it you ll be much better prepared for developing high performance applications now and in the future Figure 3 1 pres
466. will be considered and kCGLPFASingleRenderer is implied Mutually exclusive to kKCGLPFAFullScreen are the kCGLPFAO fScreen and kCGLPFAWindow attributes On some platforms the term hidden window or invisible window is used when describing an off screen destination On the Mac OS if you re rendering off screen according to this mutual exclusivity you re not rendering to a window If you wish to restrict the list of renderers that will match your format to those that can render off screen specify the KCGLPFAOf f Screen attribute However be wary of this attribute if you are at all concerned about the performance of your off screen rendering There are three ways to do off screen rendering on the Mac OS If that s not confusing enough with the introduction of the frame buffer object specification in OpenGL there are now four See Chapter 5 for more information 60 Chapter 6 The CGL API for OpenGL Configuration Finally if you wish to restrict the renderer list to only those renderers that can render on screen in a window specify the kCGLPFAWindow attribute in your format array Multisampling If multisampling is desired set the kCGLPFASampleBuffers attribute to 1 to indicate a preference for a multisample buffer Set the kCGLPFASamples attribute to the number of samples desired for each pixel The policy attributes are not applicable to these two multisampling attributes Stereo For stereo rendering also known as quad bu
467. x pch Ks Foundation framework f GLUT framework E Info plist E InfoPlist strings English M main m ej MainMenu nib English MyOtherView h M MyOtherView m 8j MyView h MyView m p OpenGL framework SharedContext h M SharedContext m Figure C 8 Final Two Window XCode Contents Controls Appearance Textured Memory M Close M Minimize M Shadow O Always Display Tooltips Unified Title And Toolbar M Shows Toolbar Button Release When Closed Hide On Deactivate M visible At Launch Auto Recalculates View Loop M Deferred ja Qy String Mat One Shot Figure C 9 Visible at Launch Enabled Ggace aq aaa gg AAAA 304 Appendix C The Cocoa API for OpenGL Configuration in Leopard Example C 6 Singleton Class Implementation for Managing a Shared Context import lt AppKit NSOpenGL h gt import lt OpenGL gl h gt import SharedContext h SharedContext _sharedContext nil implementation SharedContext id init if self super init _pixelformat nil _context nil GLuint attributes NSOpenGLPFAWindow windowed pixelformats NSOpenGLPFAAccelerated hw accel pixelformat NSOpenGLPFADoubleBuffer double buffered pixelformat NSOpenGLPFAColorSize 24 24 bits for color channels NSOpenGLPFAAlphaSize 8 8 bit alpha channel NSOpenGLPFADepthSize 24 24 bit depth buffer NSOpenGLPFAMinimumPolicy mee
468. xtension goes through from concept to core OpenGL what happens in the middle That is what does an extension define and provide how do you determine what s available and how do you implement an extension Let s look at these issues in order Extension Styles and Types OpenGL extensions have many different forms and usage patterns Some extensions define new tokens for use with existing functions One exam ple is GL ARB texture mirrored repeat which defines a new token for use with the glTexParameter suite of calls allowing a new type of GL TEXTURE WRAP style GL MIRRORED REPEAT ARB Other extensions define new API functions A good but complex example is the extensions for the OpenGL Shading Language GLSL This language actually consists of a suite of extensions including GL ARB shader objects GL ARB vertex shader GL ARB fragment shader and GL ARB shading language 120 These ex tensions define both tokens e g GL OBJECT COMPILE STATUS ARB and API entry points e g gICompileShaderARB glLinkProgramARB In essence then there are two styles of extensions e Extensions that define only tokens e Extensions that define API entry points and optionally tokens This classification is important to understanding how to use particular ex tensions Token only extensions are a bit easier to use as no special runtime function binding needs to occur and you can simply pass these token
469. y a single renderer and drives both the built in display of the computer and any external mon itor attached to the laptop In this scenario there would be exactly one vir tual screen Thus regardless of the number of physical displays attached to the computer there is one virtual screen for each hardware device that drives them Now that we have the terminology defined consider that there are two types of virtual screen changes as far as the OpenGL application programmer is con cerned implicit and explicit An implicit virtual screen change occurs when the user of the application drags an application window used for OpenGL render ing from a display being driven by one hardware renderer to a different dis play being driven by a different hardware renderer The implicit virtual screen change that occurs is the reason your application should call CGLUpdateCon text whenever your application windows are moved This behavior allows CGL to update your context with the renderer information it needs to drive the application on the new display Drawables 83 Explicit virtual screen changes are done with CGLError CGLSetVirtualScreen CGLContextObj ctx long virtualScreen Such explicit virtual screen changes are a much less common occurrence than implicit changes Consider what happens when you force a virtual screen change in your application First you re changing the renderer from one hard ware renderer to another without regard to the
470. y increase as you try to manage that complexity Thus the first rule of thumb is to be very thorough in your exploration of the core OpenGL API to determine whether there s a way to meet your needs using just the base API If you must use extensions however you must then choose among the many options that exist To guide you in this process we ll explore some of the criteria to decide which extension to use We typically begin by deciding what our priority for using this particular exten sion will be For example are we most interested in performance cross platform availability or ease of development Each of these tacks if we may be allowed to continue the sailing metaphor implies a different priority regarding which extensions to investigate We ll focus on each in turn and suggest strategies for choosing among the various options Selecting Extensions Whether your application is to be deployed on a single Mac platform for exam ple a desktop system only across the entire Mac line or even on multiple plat forms your deployment target will most likely evolve over time Making any assumptions about what s available in OpenGL at the moment you build and ship your software is a poor idea As the saying goes Trust but verify Proba bly the safest best and easiest way to deploy a cross platform application is to rely solely on a baseline version of OpenGL to provide all of the application s functionality For example choose
471. y of the Mac would be a book by itself but there s one key trend that the Mac has been tracking on the development side as well as the userside style The latest Mac APIs for user interface UI development for core application development and of course for graphics development are really quite sane well integrated and fun to use The intuitive user experience for which the Mac has always been known is for now a cornerstone of the development experience as well The developer tools 2 Chapter 1 Mac OpenGL Introduction such as XCode Shark and the various OpenGL debuggers and analyzers bring a sense of efficiency fun continuity and style to today s Mac developers So back to the question of this section Why the Mac The authors of this book have developed applications for numerous platforms over the years from Windows boxes to generic Unix boxes to SGI machines Apple IIs embed ded systems and many others It s been our experience that regardless of which platform you develop for great tools and a great user experience make for great software The answer to Why the Mac is simple the platform Both elegant hardware and solid software make the goal of creating great software much easier to achieve Once you ve developed on the Mac you ll probably want to develop all of your applications there first You can get results so much more quickly and with so much better overall quality that it s truly eye opening
472. y transformation is happening at gll Save As Text Clear GL Function of Calls glBegin 12 glTexlmage2D 11 glVertex2f 1 911 971 glReadPixels 5 glTexCoord2f 1 911 947 glEvalMesh2 160 CGLFlushDrawable 6 glBitmap 50 Total Time usec Begin time because that is when you first use the texture Statistics Total elapsed GL function time 20490519 91 usec Estimated time in GL 75 85 Show slice 9 of 9 18260959 1521746 66 89 12 1236677 112425 18 6 04 400169 0 21 1 95 304281 60856 25 1 48 106575 0 06 0 52 71704 448 15 0 35 35604 5934 06 0 17 21515 430 32 0 11 Context ID All Contexts Figure 11 13 ptm1 OpenGL Statistics Avg Time usec GLTime App Time Putting It All Together 239 000 Statistics Se Save As Text Clear GL Function of Calls Total Time usec Avg Time usec 9 GL Time App Time glBegin 38 3218194 84689 33 39 07 18 64 glTeximage2D 37 2741139 74084 86 33 28 15 87 glVertex2f 5 954 770 1428322 0 24 17 34 8 27 glTexCoord2f 5 954 694 340812 0 06 4 14 1 97 glEvalMesh2 576 329454 571 97 4 00 1 91 glReadPixels 18 168270 9348 35 2 04 0 97 amp CGLFlushDrawable 19 6596 347 21 0 08 0 04 glBitmap 180 1276 7 09 0 02 0 01 7 Total elapsed GL function time 8236644 47 usec Estimated time in GL 47 70 Show slice lt 25 of 25 gt Context ID All Contexts Figure 11 14 ptm2 OpenGL Statistics Please Tune Me 2 Moving on to ptm2 c we ve remedied
473. yMask These rou tines use OpenGL display masks to obtain display IDs OpenGL display masks are created using display IDs and work in the same manner as the other display ID retrieval entry points Their signatures are as follows CGDirectDisplayID CGOpenGLDisplayMaskToDisplayID CGOpenGLDisplayMask mask CGDisplayErr CGGetDisplaysWithOpenGLDisplayMask CGOpenGLDisplayMask mask CGDisplayCount displayArraySize CGDirectDisplayID displayArray CGDisplay Count displayReturnCount Step 3 Obtain Renderer Info Objects Step 3 takes us from the Quartz Services API back to CGL You must now re trieve a CGLRendererInfoObj from CGL This is done with a call to CGLError CGLQueryRendererInfo CGOpenGLDisplayMask displayMask CGLRenderer InfoObj rendererInfoObj long rendererCount Note that in the case of CGLQueryRendererInfo despite the presence of the rendererCount the rendererInfoObj parameter is not an array Instead rendererInfoObj upon return from this function will contain information about all of the renderers matching the OpenGL display mask Context Management 71 The displayMask parameter is a 32 bit quantity To obtain renderer informa tion about all renderers in the system set all bits in displayMask to 1 or OxFFFFFFFF Step 4 Probing the Renderer Information Object for Information The CGLRendererInfoObj data type is an opaque pointer to a structure To extract information from this st
474. ze OpenGL process events and clean up We do this through two calls to code from our earlier example fol lowed by a hand crafted main loop As before we won t go into detail about the guts of processEvent except to say that this is how for our example ap plication we handle Carbon events from the mouse keyboard and so on You can see this code in our code archive online Finally as in our full screen example we unbind our context clean it up and exit If you were to compile and build that code you d see something that looked like Figure 7 3 Windowed AGL is essentially as simple as full screen AGL but with a little more setup when binding the context Summary So far we ve seen how to create and destroy pixel formats and contexts using AGL We ve demonstrated how to use them together to create full screen and windowed AGL applications With this knowledge you should be ready to cre ate AGL based applications if you choose to do so However for those of you with the opportunity to write new applications from scratch we strongly rec ommend investigating the Cocoa options first Additional Topics Renderers AGL provides a few methods to access renderers directly in addition to basic pixel format and context handling Why might you want to access a renderer Perhaps you re curious about the theoretical memory made available to you by your renderer of choice or maybe you d like to see how many overlay planes 104 Chapte
Download Pdf Manuals
Related Search
Related Contents
Bedienungsanleitung CIAO Green CSI - Beretta Konica Revio KD-220Z Digital Camera PowerS. personal XT-USB 仕 様 書 - UR都市機構 USER MANUAL Formale Fehlermodellierung fuer verteilte reaktive Sony VGN-BX740N User's Guide Université d`Orléans ZyXEL Communications 128IMH Network Router User Manual Copyright © All rights reserved.
Failed to retrieve file