OpenGLProg_MacOSX

182
OpenGL Programming Guide for Mac

description

Open GL for Mac

Transcript of OpenGLProg_MacOSX

  • OpenGL ProgrammingGuide for Mac

  • Contents

    About OpenGL for OS X 11At a Glance 11

    OpenGL Is a C-based, Platform-Neutral API 12Different Rendering Destinations Require Different Setup Commands 12OpenGL on Macs Exists in a Heterogenous Environment 12OpenGL Helps Applications Harness the Power of Graphics Processors 13Concurrency in OpenGL Applications Requires Additional Effort 13Performance Tuning Allows Your Application to Provide an Exceptional User Experience 14

    How to Use This Document 14Prerequisites 15See Also 15

    OpenGL on the Mac Platform 17OpenGL Concepts 17

    OpenGL Implements a Client-Server Model 18OpenGL Commands Can Be Executed Asynchronously 18OpenGL Commands Are Executed In Order 19OpenGL Copies Client Data at Call-Time 19OpenGL Relies on Platform-Specific Libraries For Critical Functionality 19

    OpenGL in OS X 20Accessing OpenGL Within Your Application 21

    OpenGL APIs Specific to OS X 22Apple-Implemented OpenGL Libraries 23

    Terminology 24Renderer 24Renderer and Buffer Attributes 24Pixel Format Objects 24OpenGL Profiles 25Rendering Contexts 25Drawable Objects 25Virtual Screens 26Offline Renderer 31

    Running an OpenGL Program in OS X 31Making Great OpenGL Applications on the Macintosh 33

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    2

  • Drawing to a Window or View 35General Approach 35Drawing to a Cocoa View 36

    Drawing to an NSOpenGLView Class: A Tutorial 37Drawing OpenGL Content to a Custom View 40

    Optimizing OpenGL for High Resolution 44Enable High-Resolution Backing for an OpenGL View 44Set Up the Viewport to Support High Resolution 45Adjust Model and Texture Assets 46Check for Calls Defined in Pixel Dimensions 46Tune OpenGL Performance for High Resolution 47Use a Layer-Backed View to Overlay Text on OpenGL Content 48Use an Application Window for Fullscreen Operation 49Convert the Coordinate Space When Hit Testing 49

    Drawing to the Full Screen 50Creating a Full-Screen Application 50

    Drawing Offscreen 53Rendering to a Framebuffer Object 53

    Using a Framebuffer Object as a Texture 54Using a Framebuffer Object as an Image 58

    Rendering to a Pixel Buffer 60Setting Up a Pixel Buffer for Offscreen Drawing 61Using a Pixel Buffer as a Texture Source 61Rendering to a Pixel Buffer on a Remote System 63

    Choosing Renderer and Buffer Attributes 64OpenGL Profiles (OS X v10.7) 64Buffer Size Attribute Selection Tips 65Ensuring That Back Buffer Contents Remain the Same 66Ensuring a Valid Pixel Format Object 66Ensuring a Specific Type of Renderer 67Ensuring a Single Renderer for a Display 68Allowing Offline Renderers 69OpenCL 70Deprecated Attributes 70

    Working with Rendering Contexts 72

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    3

    Contents

  • Update the Rendering Context When the Renderer or Geometry Changes 72Tracking Renderer Changes 73Updating a Rendering Context for a Custom Cocoa View 73

    Context Parameters Alter the Contexts Behavior 76Swap Interval Allows an Application to Synchronize Updates to the Screen Refresh 76Surface Opacity Specifies How the OpenGL Surface Blends with Surfaces Behind It 77Surface Drawing Order Specifies the Position of the OpenGL Surface Relative to the Window 77Determining Whether Vertex and Fragment Processing Happens on the GPU 78Controlling the Back Buffer Size 78

    Sharing Rendering Context Resources 79

    Determining the OpenGL Capabilities Supported by the Renderer 83Detecting Functionality 83Guidelines for Code That Checks for Functionality 87OpenGL Renderer Implementation-Dependent Values 88

    OpenGL Application Design Strategies 89Visualizing OpenGL 89Designing a High-Performance OpenGL Application 91Update OpenGL Content Only When Your Data Changes 94

    Synchronize with the Screen Refresh Rate 96Avoid Synchronizing and Flushing Operations 96

    Using glFlush Effectively 97Avoid Querying OpenGL State 98Use Fences for Finer-Grained Synchronization 98

    Allow OpenGL to Manage Your Resources 99Use Double Buffering to Avoid Resource Conflicts 100Be Mindful of OpenGL State Variables 101Replace State Changes with OpenGL Objects 102Use Optimal Data Types and Formats 102Use OpenGL Macros 103

    Best Practices for Working with Vertex Data 104Understand How Vertex Data Flows Through OpenGL 105Techniques for Handling Vertex Data 107Vertex Buffers 107

    Using Vertex Buffers 108Buffer Usage Hints 110Flush Buffer Range Extension 113

    Vertex Array Range Extension 113

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    4

    Contents

  • Vertex Array Object 116

    Best Practices for Working with Texture Data 118Using Extensions to Improve Texture Performance 119

    Pixel Buffer Objects 121Apple Client Storage 124Apple Texture Range and Rectangle Texture 125Combining Client Storage with Texture Ranges 127

    Optimal Data Formats and Types 128Working with NonPower-of-Two Textures 129Creating Textures from Image Data 131

    Creating a Texture from a Cocoa View 131Creating a Texture from a Quartz Image Source 133Getting Decompressed Raw Pixel Data from a Source Image 135

    Downloading Texture Data 136Double Buffering Texture Data 137

    Customizing the OpenGL Pipeline with Shaders 139Shader Basics 141Advanced Shading Extensions 142

    Transform Feedback 142GPU Shader 4 143Geometry Shaders 143Uniform Buffers 143

    Techniques for Scene Antialiasing 144Guidelines 145General Approach 145Hinting for a Specific Antialiasing Technique 147

    Concurrency and OpenGL 148Identifying Whether an OpenGL Application Can Benefit from Concurrency 149OpenGL Restricts Each Context to a Single Thread 149Strategies for Implementing Concurrency in OpenGL Applications 150Multithreaded OpenGL 150Perform OpenGL Computations in a Worker Task 151Use Multiple OpenGL Contexts 153Guidelines for Threading OpenGL Applications 154

    Tuning Your OpenGL Application 155

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    5

    Contents

  • Gathering and Analyzing Baseline Performance Data 156Using OpenGL Driver Monitor to Measure Stalls 161

    Legacy OpenGL Functionality by Version 162Version 1.1 162Version 1.2 163Version 1.3 164Version 1.4 164Version 1.5 165Version 2.0 166Version 2.1 166

    Updating an Application to Support the OpenGL 3.2 Core Specification 167Removed Functionality 167Extension Changes on OS X 168

    Setting Up Function Pointers to OpenGL Routines 170Obtaining a Function Pointer to an Arbitrary OpenGL Entry Point 170Initializing Entry Points 171

    Document Revision History 174

    Glossary 178

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    6

    Contents

  • Figures, Tables, and Listings

    OpenGL on the Mac Platform 17Figure 1-1 OpenGL provides the reflections in iChat 17Figure 1-2 OpenGL client-server model 18Figure 1-3 Graphics platform model 18Figure 1-4 MacOS X OpenGL driver model 20Figure 1-5 Layers of OpenGL for OS X 21Figure 1-6 The programing interfaces used for OpenGL content 22Figure 1-7 Data flow through OpenGL 26Figure 1-8 A virtual screen displays what the user sees 27Figure 1-9 Two virtual screens 28Figure 1-10 A virtual screen can represent more than one physical screen 29Figure 1-11 Two virtual screens and two graphics cards 30Figure 1-12 The flow of data through OpenGL 31

    Drawing to a Window or View 35Figure 2-1 OpenGL content in a Cocoa view 35Figure 2-2 The output from the Golden Triangle program 39Listing 2-1 The interface for MyOpenGLView 37Listing 2-2 Include OpenGL/gl.h 38Listing 2-3 The drawRect: method for MyOpenGLView 38Listing 2-4 Code that draws a triangle using OpenGL commands 38Listing 2-5 The interface for a custom OpenGL view 40Listing 2-6 The initWithFrame:pixelFormat: method 41Listing 2-7 The lockFocus method 42Listing 2-8 The drawRect method for a custom view 42Listing 2-9 Detaching the context from a drawable object 43

    Optimizing OpenGL for High Resolution 44Figure 3-1 Enabling high-resolution backing for an OpenGL view 45Figure 3-2 A text overlay scales automatically for standard resolution (left) and high resolution (right)

    48Listing 3-1 Setting up the viewport for drawing 45

    Drawing to the Full Screen 50

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    7

  • Figure 4-1 Drawing OpenGL content to the full screen 50

    Drawing Offscreen 53Listing 5-1 Setting up a framebuffer for texturing 57Listing 5-2 Setting up a renderbuffer for drawing images 59

    Choosing Renderer and Buffer Attributes 64Table 6-1 Renderer types and pixel format attributes 67Listing 6-1 Using the CGL API to create a pixel format object 66Listing 6-2 Setting an NSOpenGLContext object to use a specific display 68Listing 6-3 Setting a CGL context to use a specific display 69

    Working with Rendering Contexts 72Figure 7-1 A fixed size back buffer and variable size front buffer 79Figure 7-2 Shared contexts attached to the same drawable object 80Figure 7-3 Shared contexts and more than one drawable object 80Listing 7-1 Handling context updates for a custom view 74Listing 7-2 Using CGL to set up synchronization 76Listing 7-3 Using CGL to set surface opacity 77Listing 7-4 Using CGL to set surface drawing order 77Listing 7-5 Using CGL to check whether the GPU is processing vertices and fragments 78Listing 7-6 Using CGL to set up back buffer size control 79Listing 7-7 Setting up an NSOpenGLContext object for sharing 81Listing 7-8 Setting up a CGL context for sharing 82

    Determining the OpenGL Capabilities Supported by the Renderer 83Table 8-1 Common OpenGL renderer limitations 88Table 8-2 OpenGL shader limitations 88Listing 8-1 Checking for OpenGL functionality 84Listing 8-2 Setting up a valid rendering context to get renderer functionality information 86

    OpenGL Application Design Strategies 89Figure 9-1 OpenGL graphics pipeline 90Figure 9-2 OpenGL client-server architecture 91Figure 9-3 Application model for managing resources 92Figure 9-4 Single-buffered vertex array data 100Figure 9-5 Double-buffered vertex array data 101Listing 9-1 Setting up a Core Video display link 94Listing 9-2 Setting up synchronization 96Listing 9-3 Disabling state variables 102

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    8

    Figures, Tables, and Listings

  • Listing 9-4 Using CGL macros 103

    Best Practices for Working with Vertex Data 104Figure 10-1 Vertex data sets can be quite large 104Figure 10-2 Vertex data path 105Figure 10-3 Immediate mode requires a copy of the current vertex data 105Listing 10-1 Submitting vertex data using glDrawElements. 106Listing 10-2 Using the vertex buffer object extension with dynamic data 109Listing 10-3 Using the vertex buffer object extension with static data 110Listing 10-4 Geometry with different usage patterns 111Listing 10-5 Using the vertex array range extension with dynamic data 115Listing 10-6 Using the vertex array range extension with static data 116

    Best Practices for Working with Texture Data 118Figure 11-1 Textures add realism to a scene 118Figure 11-2 Texture data path 119Figure 11-3 Data copies in an OpenGL program 120Figure 11-4 The client storage extension eliminates a data copy 124Figure 11-5 The texture range extension eliminates a data copy 126Figure 11-6 Combining extensions to eliminate data copies 127Figure 11-7 Normalized and non-normalized coordinates 129Figure 11-8 An image segmented into power-of-two tiles 130Figure 11-9 Using an image as a texture for a cube 131Figure 11-10 Single-buffered data 137Figure 11-11 Double-buffered data 138Listing 11-1 Using texture extensions for a rectangular texture 127Listing 11-2 Using texture extensions for a power-of-two texture 128Listing 11-3 Building an OpenGL texture from an NSView object 132Listing 11-4 Using a Quartz image as a texture source 134Listing 11-5 Getting pixel data from a source image 135Listing 11-6 Code that downloads texture data 136

    Customizing the OpenGL Pipeline with Shaders 139Figure 12-1 OpenGL fixed-function pipeline 139Figure 12-2 OpenGL shader pipeline 140Listing 12-1 Loading a Shader 141

    Techniques for Scene Antialiasing 144Table 13-1 Antialiasing hints 147

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    9

    Figures, Tables, and Listings

  • Concurrency and OpenGL 148Figure 14-1 CPU processing and OpenGL on separate threads 152Figure 14-2 Two contexts on separate threads 153Listing 14-1 Enabling the multithreaded OpenGL engine 151

    Tuning Your OpenGL Application 155Figure 15-1 Output produced by the top application 157Figure 15-2 The OpenGL Profiler window 158Figure 15-3 A statistics window 159Figure 15-4 A Trace window 160Figure 15-5 The graph view in OpenGL Driver Monitor 161

    Legacy OpenGL Functionality by Version 162Table A-1 Functionality added in OpenGL 1.1 162Table A-2 Functionality added in OpenGL 1.2 163Table A-3 Functionality added in OpenGL 1.3 164Table A-4 Functionality added in OpenGL 1.4 164Table A-5 Functionality added in OpenGL 1.5 165Table A-6 Functionality added in OpenGL 2.0 166Table A-7 Functionality added in OpenGL 2.1 166

    Updating an Application to Support the OpenGL 3.2 Core Specification 167Table B-1 Extensions described in this guide 168

    Setting Up Function Pointers to OpenGL Routines 170Listing C-1 Using NSLookupAndBindSymbol to obtain a symbol for a symbol name 171Listing C-2 Using NSGLGetProcAddress to obtain an OpenGL entry point 172

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    10

    Figures, Tables, and Listings

  • OpenGL is an open, cross-platform graphics standard with broad industry support. OpenGL greatly eases thetask of writing real-time 2D or 3D graphics applications by providing a mature, well-documented graphicsprocessing pipeline that supports the abstraction of current and future hardware accelerators.

    OpenGL client

    OpenGL server

    Graphics hardware

    Application

    OpenGL framework

    OpenGL driver

    Runs on GPU

    Runs on CPU

    At a GlanceOpenGL is an excellent choice for graphics development on the Macintosh platform because it offers thefollowing advantages:

    Reliable Implementation. The OpenGL client-server model abstracts hardware details and guaranteesconsistent presentation on any compliant hardware and software configuration. Every implementation ofOpenGL adheres to the OpenGL specification and must pass a set of conformance tests.

    Performance. Applications can harness the considerable power of the graphics hardware to improverendering speeds and quality.

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    11

    About OpenGL for OS X

    Fabio Mainardi

    Fabio Mainardi

  • Industry acceptance. The specification for OpenGL is controlled by the Khronos Group, an industryconsortium whose members include many of the major companies in the computer graphics industry,including Apple. In addition to OpenGL for OS X, there are OpenGL implementations for Windows, Linux,Irix, Solaris, and many game consoles.

    OpenGL Is a C-based, Platform-Neutral APIBecause OpenGL is a C-based API, it is extremely portable and widely supported. As a C API, it integratesseamlessly with Objective-C based Cocoa applications. OpenGL provides functions your application uses togenerate 2D or 3D images. Your application presents the rendered images to the screen or copies them backto its own memory.

    The OpenGL specification does not provide a windowing layer of its own. It relies on functions defined by OSX to integrate OpenGL drawing with the windowing system. Your application creates an OS X OpenGL renderingcontext and attaches a rendering target to it (known as a drawable object). The rendering context managesOpenGL state changes and objects created by calls to the OpenGL API. The drawable object is the finaldestination for OpenGL drawing commands and is typically associated with a Cocoa window or view.

    Relevant Chapters: OpenGL on the Mac Platform (page 17)

    Different Rendering Destinations Require Different Setup CommandsDepending on whether your application intends to draw OpenGL content to a window, to draw to the entirescreen, or to perform offscreen image processing, it takes different steps to create the rendering context andassociate it with a drawable object.

    Relevant Chapters: Drawing to a Window or View (page 35), Drawing to the Full Screen (page 50)and Drawing Offscreen (page 53)

    OpenGL on Macs Exists in a Heterogenous EnvironmentMacs support different types of graphics processors, each with different rendering capabilities, supportingversions of OpenGL from 1.x through OpenGL 3.2. When creating a rendering context, your application canaccept a broad range of renderers or it can restrict itself to devices with specific capabilities. Once you have acontext, you can configure how that context executes OpenGL commands.

    About OpenGL for OS XAt a Glance

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    12

    Fabio Mainardi

    Fabio Mainardi

    Fabio Mainardi

  • OpenGL on the Mac is not only a heterogenous environment, but it is also a dynamic environment. Users canadd or remove displays, or take a laptop running on battery power and plug it into a wall. When the graphicsenvironment on the Mac changes, the renderer associated with the context may change. Your applicationmust handle these changes and adjust how it uses OpenGL.

    Relevant Chapters: Choosing Renderer and Buffer Attributes (page 64), Working with RenderingContexts (page 72), and Determining the OpenGL Capabilities Supported by the Renderer (page83)

    OpenGL Helps Applications Harness the Power of Graphics ProcessorsGraphics processors are massively parallelized devices optimized for graphics operations. To access thatcomputing power adds additional overhead because data must move from your application to the GPU overslower internal buses. Accessing the same data simultaneously from both your application and OpenGL isusually restricted. To get great performance in your application, you must carefully design your application tofeed data and commands to OpenGL so that the graphics hardware runs in parallel with your application. Apoorly tuned application may stall either on the CPU or the GPU waiting for the other to finish processing.

    When you are ready to optimize your applications performance, Apple provides both general-purpose andOpenGL-specific profiling tools that make it easy to learn where your application spends its time.

    Relevant Chapters: Optimizing OpenGL for High Resolution (page 44), OpenGL on the MacPlatform (page 17),OpenGL Application Design Strategies (page 89), Best Practices for Working withVertex Data (page 104), Best Practices for Working with Texture Data (page 118), Customizing theOpenGL Pipeline with Shaders (page 139), and Tuning Your OpenGL Application (page 155)

    Concurrency in OpenGL Applications Requires Additional EffortMany Macs ship with multiple processors or multiple cores, and future hardware is expected to add more ofeach. Designing applications to take advantage of multiprocessing is critical. OpenGL places additionalrestrictions on multithreaded applications. If you intend to add concurrency to an OpenGL application, youmust ensure that the application does not access the same context from two different threads at the sametime.

    About OpenGL for OS XAt a Glance

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    13

  • Relevant Chapters: Concurrency and OpenGL (page 148)

    Performance Tuning Allows Your Application to Provide an Exceptional UserExperienceOnce youve improved the performance of your OpenGL application and taken advantage of concurrency, putsome of the freed processing power to work for you. Higher resolution textures, detailed models, and morecomplex lighting and shading algorithms can improve image quality. Full-scene antialiasing on modern graphicshardware can eliminate many of the jaggies common on lower resolution images.

    Relevant Chapters: Customizing the OpenGL Pipeline with Shaders (page 139),Techniques for SceneAntialiasing (page 144)

    How to Use This DocumentIf you have never programmed in OpenGL on the Mac, you should read this book in its entirety, starting withOpenGL on the Mac Platform (page 17). Critical Mac terminology is defined in that chapter as well as in theGlossary (page 178).

    If you already have an OpenGL application running on the Mac, but have not yet updated it for OS X v10.7,read Choosing Renderer and Buffer Attributes (page 64) to learn how to choose an OpenGL profile for yourapplication.

    To find out how to update an existing OpenGL app for high resolution, see Optimizing OpenGL for HighResolution (page 44).

    Once you have OpenGL content in your application, read OpenGL Application Design Strategies (page 89) tolearn fundamental patterns for implementing high-performance OpenGL applications, and the chapters thatfollow to learn how to apply those patterns to specific OpenGL problems.

    About OpenGL for OS XHow to Use This Document

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    14

  • Important: Although this guide describes how to create rendering contexts that support OpenGL 3.2,most code examples and discussion in the rest of the book describe the earlier legacy versions of OpenGL.See Updating an Application to Support the OpenGL 3.2 Core Specification (page 167) for more informationon migrating your application to OpenGL 3.2.

    PrerequisitesThis guide assumes that you have some experience with OpenGL programming, but want to learn how toapply that knowledge to create software for the Mac. Although this guide provides advice on optimizingOpenGL code, it does not provide entry-level information on how to use the OpenGL API. If you are unfamiliarwith OpenGL, you should read OpenGL on the Mac Platform (page 17) to get an overview of OpenGL on theMac platform, and then read the following OpenGL programming guide and reference documents:

    OpenGL Programming Guide, by Dave Shreiner and the Khronos OpenGL Working Group; otherwise knownas "The Red book.

    OpenGL Shading Language , by Randi J. Rost, is an excellent guide for those who want to write programsthat compute surface properties (also known as shaders).

    OpenGL Reference Pages.

    Before reading this document, you should be familiar with Cocoa windows and views as introduced in WindowProgramming Guide and View Programming Guide .

    See AlsoKeep these reference documents handy as you develop your OpenGL program for OS X:

    NSOpenGLView Class Reference , NSOpenGLContext Class Reference , NSOpenGLPixelBuffer Class Reference ,and NSOpenGLPixelFormat Class Reference provide a complete description of the classes and methodsneeded to integrate OpenGL content into a Cocoa application.

    CGL Reference describes low-level functions that can be used to create full-screen OpenGL applications.

    OpenGL Extensions Guide provides information about OpenGL extensions supported in OS X.

    The OpenGL Foundation website, http://www.opengl.org, provides information on OpenGL commands, theKhronos OpenGL Working Group, logo requirements, OpenGL news, and many other topics. It's a site thatyou'll want to visit regularly. Among the many resources it provides, the following are important referencedocuments for OpenGL developers:

    About OpenGL for OS XPrerequisites

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    15

    Fabio Mainardi

  • OpenGL Specification provides detailed information on how an OpenGL implementation is expected tohandle each OpenGL command.

    OpenGL Reference describes the main OpenGL library.

    OpenGL GLU Reference describes the OpenGL Utility Library, which contains convenience functionsimplemented on top of the OpenGL API.

    OpenGL GLUT Reference describes the OpenGL Utility Toolkit, a cross-platform windowing API.

    OpenGL API Code and Tutorial Listings provides code examples for fundamental tasks, such as modelingand texture mapping, as well as for advanced techniques, such as high dynamic range rendering (HDRR).

    About OpenGL for OS XSee Also

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    16

  • You can tell that Apple has an implementation of OpenGL on its platform by looking at the user interface formany of the applications that are installed with OS X. The reflections built into iChat (Figure 1-1) provide oneof the more notable examples. The responsiveness of the windows, the instant results of applying an effect iniPhoto, and many other operations in OS X are due to the use of OpenGL. OpenGL is available to all Macintoshapplications.

    OpenGL for OS X is implemented as a set of frameworks that contain the OpenGL runtime engine and itsdrawing software. These frameworks use platform-neutral virtual resources to free your programming as muchas possible from the underlying graphics hardware. OS X provides a set of application programming interfaces(APIs) that Cocoa applications can use to support OpenGL drawing.

    Figure 1-1 OpenGL provides the reflections in iChat

    This chapter provides an overview of OpenGL and the interfaces your application uses on the Mac platform totap into it.

    OpenGL ConceptsTo understand how OpenGL fits into OS X and your application, you should first understand how OpenGL isdesigned.

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    17

    OpenGL on the Mac Platform

    Fabio Mainardi

  • OpenGL Implements a Client-Server ModelOpenGL uses a client-server model, as shown in Figure 1-2. When your application calls an OpenGL function,it talks to an OpenGL client. The client delivers drawing commands to an OpenGL server. The nature of theclient, the server, and the communication path between them is specific to each implementation of OpenGL.For example, the server and clients could be on different computers, or they could be different processes onthe same computer.

    Figure 1-2 OpenGL client-server model

    Application

    OpenGL client

    OpenGL server

    A client-server model allows the graphics workload to be divided between the client and the server. Forexample, all Macintosh computers ship with dedicated graphics hardware that is optimized to perform graphicscalculations in parallel. Figure 1-3 shows a common arrangement of CPUs and GPUs. With this hardwareconfiguration, the OpenGL client executes on the CPU and the server executes on the GPU.

    Figure 1-3 Graphics platform model

    CPU

    RAM

    Core Core

    GPU

    RAM

    CoreCore CoreCoreCore Core

    CoreCore CoreCoreCore Core

    System

    OpenGL Commands Can Be Executed AsynchronouslyA benefit of the OpenGL client-server model is that the client can return control to the application before thecommand has finished executing. An OpenGL client may also buffer or delay execution of OpenGL commands.If OpenGL required all commands to complete before returning control to the application, then either the CPUor the GPU would be idle waiting for the other to provide it data, resulting in reduced performance.

    OpenGL on the Mac PlatformOpenGL Concepts

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    18

    Fabio Mainardi

    Fabio Mainardi

  • Some OpenGL commands implicitly or explicitly require the client to wait until some or all previously submittedcommands have completed. OpenGL applications should be designed to reduce the frequency of client-serversynchronizations. See OpenGL Application Design Strategies (page 89) for more information on how to designyour OpenGL application.

    OpenGL Commands Are Executed In OrderOpenGL guarantees that commands are executed in the order they are received by OpenGL.

    OpenGL Copies Client Data at Call-TimeWhen an application calls an OpenGL function, the OpenGL client copies any data provided in the parametersbefore returning control to the application. For example, if a parameter points at an array of vertex data storedin application memory, OpenGL must copy that data before returning. Therefore, an application is free tochange memory it owns regardless of calls it makes to OpenGL.

    The data that the client copies is often reformatted before it is transmitted to the server. Copying, modifying,and transmitting parameters to the server adds overhead to calling OpenGL. Applications should be designedto minimize copy overhead.

    OpenGL Relies on Platform-Specific Libraries For Critical FunctionalityOpenGL provides a rich set of cross-platform drawing commands, but does not define functions to interactwith an operating systems graphics subsystem. Instead, OpenGL expects each implementation to define aninterface to create rendering contexts and associate them with the graphics subsystem. A rendering contextholds all of the data stored in the OpenGL state machine. Allowing multiple contexts allows the state in onemachine to be changed by an application without affecting other contexts.

    Associating OpenGL with the graphic subsystem usually means allowing OpenGL content to be rendered toa specific window. When content is associated with a window, the implementation creates whatever resourcesare required to allow OpenGL to render and display images.

    OpenGL on the Mac PlatformOpenGL Concepts

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    19

    Fabio Mainardi

  • OpenGL in OS XOpenGL in OS X implements the OpenGL client-server model using a common OpenGL framework and plug-indrivers. The framework and driver combine to implement the client portion of OpenGL, as shown in Figure1-4. Dedicated graphics hardware provides the server. Although this is the common scenario, Apple alsoprovides a software renderer implemented entirely on the CPU.

    Figure 1-4 MacOS X OpenGL driver model

    OpenGL client

    OpenGL server

    Graphics hardware

    Application

    OpenGL framework

    OpenGL driver

    Runs on GPU

    Runs on CPU

    OS X supports a display space that can include multiple dissimilar displays, each driven by different graphicscards with different capabilities. In addition, multiple OpenGL renderers can drive each graphics card. Toaccommodate this versatility, OpenGL for OS X is segmented into well-defined layers: a window system layer,

    OpenGL on the Mac PlatformOpenGL in OS X

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    20

  • a framework layer, and a driver layer, as shown in Figure 1-5. This segmentation allows for plug-in interfacesto both the window system layer and the framework layer. Plug-in interfaces offer flexibility in software andhardware configuration without violating the OpenGL standard.

    Figure 1-5 Layers of OpenGL for OS X

    ATI GLD plug-inSoftware GLD plug-in NVIDIA GLD plug-in Intel GLD plug-in

    Application

    Hardware

    Window system layer

    Common OpenGL framework

    Driver layer

    CGL OpenGLNSOpenGL

    The window system layer is an OS Xspecific layer that your application uses to create OpenGL renderingcontexts and associate them with the OS X windowing system. The NSOpenGL classes and Core OpenGL (CGL)API also provide some additional controls for how OpenGL operates on that context. See OpenGL APIs Specificto OS X (page 22) for more information. Finally, this layer also includes the OpenGL librariesGL, GLU, andGLUT. (See Apple-Implemented OpenGL Libraries (page 23) for details.)

    The common OpenGL framework layer is the software interface to the graphics hardware. This layer containsApple's implementation of the OpenGL specification.

    The driver layer contains the optional GLD plug-in interface and one or more GLD plug-in drivers, which mayhave different software and hardware support capabilities. The GLD plug-in interface supports third-partyplug-in drivers, allowing third-party hardware vendors to provide drivers optimized to take best advantage oftheir graphics hardware.

    Accessing OpenGL Within Your ApplicationThe programming interfaces that your application calls fall into two categoriesthose specific to the Macintoshplatform and those defined by the OpenGL Working Group. The Apple-specific programming interfaces arewhat Cocoa applications use to communicate with the OS X windowing system. These APIs don't create OpenGLcontent, they manage content, direct it to a drawing destination, and control various aspects of the rendering

    OpenGL on the Mac PlatformAccessing OpenGL Within Your Application

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    21

  • operation. Your application calls the OpenGL APIs to create content. OpenGL routines accept vertex, pixel, andtexture data and assemble the data to create an image. The final image resides in a framebuffer, which ispresented to the user through the windowing-system specific API.

    Figure 1-6 The programing interfaces used for OpenGL content

    OpenGL engine and drivers

    GLUT

    CGL OpenGL

    NSOpenGLclasses

    GLUT application Cocoa application

    OpenGL APIs Specific to OS XOS X offers two easy-to-use APIs that are specific to the Macintosh platform: the NSOpenGL classes and theCGL API. Throughout this document, these APIs are referred to as the Apple-specific OpenGL APIs.

    Cocoa provides many classes specifically for OpenGL:

    The NSOpenGLContext class implements a standard OpenGL rendering context.

    The NSOpenGLPixelFormat class is used by an application to specify the parameters used to create theOpenGL context.

    The NSOpenGLView class is a subclass of NSView that uses NSOpenGLContext andNSOpenGLPixelFormat to display OpenGL content in a view. Applications that subclass NSOpenGLViewdo not need to directly subclass NSOpenGLPixelFormat or NSOpenGLContext. Applications that needcustomization or flexibility, can subclass NSView and create NSOpenGLPixelFormat andNSOpenGLContext objects manually.

    The NSOpenGLLayer class allows your application to integrate OpenGL drawing with Core Animation.

    The NSOpenGLPixelBuffer class provides hardware-accelerated offscreen drawing.

    OpenGL on the Mac PlatformAccessing OpenGL Within Your Application

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    22

  • The Core OpenGL API (CGL) resides in the OpenGL framework and is used to implement the NSOpenGL classes.CGL offers the most direct access to system functionality and provides the highest level of graphics performanceand control for drawing to the full screen. CGL Reference provides a complete description of this API.

    Apple-Implemented OpenGL LibrariesOS X also provides the full suite of graphics libraries that are part of every implementation of OpenGL: GL, GLU,GLUT, and GLX. Two of theseGL and GLUprovide low-level drawing support. The other twoGLUT andGLXsupport drawing to the screen.

    Your application typically interfaces directly with the core OpenGL library (GL), the OpenGL Utility library (GLU),and the OpenGL Utility Toolkit (GLUT). The GL library provides a low-level modular API that allows you todefine graphical objects. It supports the core functions defined by the OpenGL specification. It provides supportfor two fundamental types of graphics primitives: objects defined by sets of vertices, such as line segmentsand simple polygons, and objects that are pixel-based images, such as filled rectangles and bitmaps. The GLAPI does not handle complex custom graphical objects; your application must decompose them into simplergeometries.

    The GLU library combines functions from the GL library to support more advanced graphics features. It runson all conforming implementations of OpenGL. GLU is capable of creating and handling complex polygons(including quartic equations), processing nonuniform rational b-spline curves (NURBs), scaling images, anddecomposing a surface to a series of polygons (tessellation).

    The GLUT library provides a cross-platform API for performing operations associated with the user windowingenvironmentdisplaying and redrawing content, handling events, and so on. It is implemented on most UNIX,Linux, and Windows platforms. Code that you write with GLUT can be reused across multiple platforms. However,such code is constrained by a generic set of user interface elements and event-handling options. This documentdoes not show how to use GLUT. The GLUTBasics sample project shows you how to get started with GLUT.

    GLX is an OpenGL extension that supports using OpenGL within a window provided by the X Window system.X11 for OS X is available as an optional installation. (It's not shown in Figure 1-6 (page 22).) See OpenGLProgramming for the X Window System , published by Addison Wesley for more information.

    This document does not show how to use these libraries. For detailed information, either go to the OpenGLFoundation website http://www.opengl.org or see the most recent version of "The Red book"OpenGL Pro-gramming Guide, published by Addison Wesley.

    OpenGL on the Mac PlatformAccessing OpenGL Within Your Application

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    23

    Fabio Mainardi

  • TerminologyThere are a number of terms that youll want to understand so that you can write code effectively using OpenGL:renderer, renderer attributes, buffer attributes, pixel format objects, rendering contexts, drawable objects, andvirtual screens. As an OpenGL programmer, some of these may seem familiar to you. However, understandingthe Apple-specific nuances of these terms will help you get the most out of OpenGL on the Macintosh platform.

    RendererA renderer is the combination of the hardware and software that OpenGL uses to execute OpenGL commands.The characteristics of the final image depend on the capabilities of the graphics hardware associated with therenderer and the device used to display the image. OS X supports graphics accelerator cards with varyingcapabilities, as well as a software renderer. It is possible for multiple renderers, each with different capabilitiesor features, to drive a single set of graphics hardware. To learn how to determine the exact features of arenderer, see Determining the OpenGL Capabilities Supported by the Renderer (page 83).

    Renderer and Buffer AttributesYour application uses renderer and buffer attributes to communicate renderer and buffer requirements toOpenGL. The Apple implementation of OpenGL dynamically selects the best renderer for the current renderingtask and does so transparently to your application. If your application has very specific rendering requirementsand wants to control renderer selection, it can do so by supplying the appropriate renderer attributes. Bufferattributes describe such things as color and depth buffer sizes, and whether the data is stereoscopic ormonoscopic.

    Renderer and buffer attributes are represented by constants defined in the Apple-specific OpenGL APIs. OpenGLuses the attributes you supply to perform the setup work needed prior to drawing content. Drawing to aWindow or View (page 35) provides a simple example that shows how to use renderer and buffer attributes.Choosing Renderer and Buffer Attributes (page 64) explains how to choose renderer and buffer attributes toachieve specific rendering goals.

    Pixel Format ObjectsA pixel format describes the format for pixel data storage in memory. The description includes the numberand order of components as well as their names (typically red, blue, green and alpha). It also includes otherinformation, such as whether a pixel contains stencil and depth values. A pixel format object is an opaquedata structure that holds a pixel format along with a list of renderers and display devices that satisfy therequirements specified by an application.

    OpenGL on the Mac PlatformTerminology

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    24

  • Each of the Apple-specific OpenGL APIs defines a pixel format data type and accessor routines that you canuse to obtain the information referenced by this object. See Virtual Screens (page 26) for more informationon renderer and display devices.

    OpenGL ProfilesOpenGL profiles are new in OS X 10.7. An OpenGL profile is a renderer attribute used to request a specificversion of the OpenGL specification. When your application provides an OpenGL profile as part of its rendererattributes, it only receives renderers that provide the complete feature set promised by that profile. The rendercan implement a different version of the OpenGL so long as the version it supplies to your application providesthe same functionality that your application requested.

    Rendering ContextsA rendering context, or simply context , contains OpenGL state information and objects for your application.State variables include such things as drawing color, the viewing and projection transformations, lightingcharacteristics, and material properties. State variables are set per context. When your application createsOpenGL objects (for example, textures), these are also associated with the rendering context.

    Although your application can maintain more than one context, only one context can be the current contextin a thread. The current context is the rendering context that receives OpenGL commands issued by yourapplication.

    Drawable ObjectsA drawable object refers to an object allocated by the windowing system that can serve as an OpenGLframebuffer. A drawable object is the destination for OpenGL drawing operations. The behavior of drawableobjects is not part of the OpenGL specification, but is defined by the OS X windowing system.

    A drawable object can be any of the following: a Cocoa view, offscreen memory, a full-screen graphics device,or a pixel buffer.

    OpenGL on the Mac PlatformTerminology

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    25

  • Note: A pixel buffer (pbuffer) is an OpenGL buffer designed for hardware-accelerated offscreendrawing and as a source for texturing. An application can render an image into a pixel buffer andthen use the pixel buffer as a texture for other OpenGL commands. Although pixel buffers aresupported on Apples implementation of OpenGL, Apple recommends you use framebuffer objectsinstead. See Drawing Offscreen (page 53) for more information on offscreen rendering.

    Before OpenGL can draw to a drawable object, the object must be attached to a rendering context. Thecharacteristics of the drawable object narrow the selection of hardware and software specified by the renderingcontext. Apples OpenGL automatically allocates buffers, creates surfaces, and specifies which renderer is thecurrent renderer.

    The logical flow of data from an application through OpenGL to a drawable object is shown in Figure 1-7. Theapplication issues OpenGL commands that are sent to the current rendering context. The current context,which contains state information, constrains how the commands are interpreted by the appropriate renderer.The renderer converts the OpenGL primitives to an image in the framebuffer. (See also Running an OpenGLProgram in OS X (page 31).)

    Figure 1-7 Data flow through OpenGL

    Rendered ImageApplication

    Possible renderers

    OpenGLbuffers

    Current

    Drawableobjects

    #/.4%84

    Virtual ScreensThe characteristics and quality of the OpenGL content that the user sees depend on both the renderer andthe physical display used to view the content. The combination of renderer and physical display is called avirtual screen. This important concept has implications for any OpenGL application running on OS X.

    A simple system, with one graphics card and one physical display, typically has two virtual screens. One virtualscreen consists of a hardware-based renderer and the physical display and the other virtual screen consists ofa software-based renderer and the physical display. OS X provides a software-based renderer as a fallback. It'spossible for your application to decline the use of this fallback. You'll see how in Choosing Renderer and BufferAttributes (page 64).

    OpenGL on the Mac PlatformTerminology

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    26

  • The green rectangle around the OpenGL image in Figure 1-8 surrounds a virtual screen for a system with onegraphics card and one display. Note that a virtual screen is not the physical display, which is why the greenrectangle is drawn around the application window that shows the OpenGL content. In this case, it is the rendererprovided by the graphics card combined with the characteristics of the display.

    Figure 1-8 A virtual screen displays what the user sees

    Graphics card

    Virtual screen

    OpenGL on the Mac PlatformTerminology

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    27

  • Because a virtual screen is not simply the physical display, a system with one display can use more than onevirtual screen at a time, as shown in Figure 1-9. The green rectangles are drawn to point out each virtual screen.Imagine that the virtual screen on the right side uses a software-only renderer and that the one on the leftuses a hardware-dependent renderer. Although this is a contrived example, it illustrates the point.

    Figure 1-9 Two virtual screens

    Graphics card

    Virtual screen 2(Software renderer)

    Virtual screen 1(Hardware renderer)

    OpenGL on the Mac PlatformTerminology

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    28

  • It's also possible to have a virtual screen that can represent more than one physical display. The green rectanglein Figure 1-10 is drawn around a virtual screen that spans two physical displays. In this case, the same graphicshardware drives a pair of identical displays. A mirrored display also has a single virtual screen associated withmultiple physical displays.

    Figure 1-10 A virtual screen can represent more than one physical screen

    Dual-headed graphics card

    Virtual screenIdentical displays

    The concept of a virtual screen is particularly important when the user drags an image from one physical screento another. When this happens, the virtual screen may change, and with it, a number of attributes of theimaging process, such as the current renderer, may change. With the dual-headed graphics card shown inFigure 1-10 (page 29), dragging between displays preserves the same virtual screen. However, Figure 1-11shows the case for which two displays represent two unique virtual screens. Not only are the two graphicscards different, but it's possible that the renderer, buffer attributes, and pixel characteristics are different. Achange in any of these three items can result in a change in the virtual screen.

    OpenGL on the Mac PlatformTerminology

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    29

  • When the user drags an image from one display to another, and the virtual screen is the same for both displays,the image quality should appear similar. However, for the case shown in Figure 1-11, the image quality can bequite different.

    Figure 1-11 Two virtual screens and two graphics cards

    Graphics card 1

    Graphics card 2

    Virtual screen 1 Virtual screen 2

    OpenGL for OS X transparently manages rendering across multiple monitors. A user can drag a window fromone monitor to another, even though their display capabilities may be different or they may be driven bydissimilar graphics cards with dissimilar resolutions and color depths.

    OpenGL dynamically switches renderers when the virtual screen that contains the majority of the pixels in anOpenGL window changes. When a window is split between multiple virtual screens, the framebuffer is rasterizedentirely by the renderer driving the screen that contains the largest segment of the window. The regions ofthe window on the other virtual screens are drawn by copying the rasterized image. When the entire OpenGLdrawable object is displayed on one virtual screen, there is no performance impact from multiple monitorsupport.

    Applications need to track virtual screen changes and, if appropriate, update the current application state toreflect changes in renderer capabilities. See Working with Rendering Contexts (page 72).

    OpenGL on the Mac PlatformTerminology

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    30

  • Offline RendererAn offline renderer is one that is not currently associated with a display. For example, a graphics processormight be powered down to conserve power, or there might not be a display hooked up to the graphics card.Offline renderers are not normally visible to your application, but your application can enable them by addingthe appropriate renderer attribute. Taking advantage of offline renderers is useful because it gives the user aseamless experience when they plug in or remove displays.

    For more information about configuring a context to see offline renderers, see Choosing Renderer and BufferAttributes (page 64). To enable your application to switch to a renderer when a display is attached, see Updatethe Rendering Context When the Renderer or Geometry Changes (page 72).

    Running an OpenGL Program in OS XFigure 1-12 shows the flow of data in an OpenGL program, regardless of the platform that the program runson.

    Figure 1-12 The flow of data through OpenGL

    RasterizationFragment shadingand per-fragment

    operations

    Per-pixeloperations

    Textureassembly

    Framebuffer

    Vertex shadingand per-vertex

    operations

    Pixel data

    Vertex data

    Per-vertex operations include such things as applying transformation matrices to add perspective or to clip,and applying lighting effects. Per-pixel operations include such things as color conversion and applying blurand distortion effects. Pixels destined for textures are sent to texture assembly, where OpenGL stores texturesuntil it needs to apply them onto an object.

    OpenGL rasterizes the processed vertex and pixel data, meaning that the data are converged to create fragments.A fragment encapsulates all the values for a pixel, including color, depth, and sometimes texture values. Thesevalues are used during antialiasing and any other calculations needed to fill shapes and to connect vertices.

    OpenGL on the Mac PlatformRunning an OpenGL Program in OS X

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    31

  • Per-fragment operations include applying environment effects, depth and stencil testing, and performingother operations such as blending and dithering. Some operationssuch as hidden-surface removalendthe processing of a fragment. OpenGL draws fully processed fragments into the appropriate location in theframebuffer.

    The dashed arrows in Figure 1-12 indicate reading pixel data back from the framebuffer. They representoperations performed by OpenGL functions such asglReadPixels,glCopyPixels, andglCopyTexImage2D.

    So far you've seen how OpenGL operates on any platform. But how do Cocoa applications provide data to theOpenGL for processing? A Mac application must perform these tasks:

    Set up a list of buffer and renderer attributes that define the sort of drawing you want to perform. (SeeRenderer and Buffer Attributes (page 24).)

    Request the system to create a pixel format object that contains a pixel format that meets the constraintsof the buffer and render attributes and a list of all suitable combinations of displays and renderers. (SeePixel Format Objects (page 24) and Virtual Screens (page 26).)

    Create a rendering context to hold state information that controls such things as drawing color, view andprojection matrices, characteristics of light, and conventions used to pack pixels. When you set up thiscontext, you must provide a pixel format object because the rendering context needs to know the set ofvirtual screens that can be used for drawing. (See Rendering Contexts (page 25).)

    Bind a drawable object to the rendering context. The drawable object is what captures the OpenGL drawingsent to that rendering context. (See Drawable Objects (page 25).)

    Make the rendering context the current context. OpenGL automatically targets the current context.Although your application might have several rendering contexts set up, only the current one is the activeone for drawing purposes.

    Issue OpenGL drawing commands.

    Flush the contents of the rendering context. This causes previously submitted commands to be renderedto the drawable object and displays them to the user.

    The tasks described in the first five bullet items are platform-specific. Drawing to a Window or View (page 35)provides simple examples of how to perform them. As you read other parts of this document, you'll see thereare a number of other tasks that, although not mandatory for drawing, are really quite necessary for anyapplication that wants to use OpenGL to perform complex 3D drawing efficiently on a wide variety of Macintoshsystems.

    OpenGL on the Mac PlatformRunning an OpenGL Program in OS X

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    32

  • Making Great OpenGL Applications on the MacintoshOpenGL lets you create applications with outstanding graphics performance as well as a great userexperiencebut neither of these things come for free. Your application performs best when it works withOpenGL rather than against it. With that in mind, here are guidelines you should follow to createhigh-performance, future-looking OpenGL applications:

    Ensure your application runs successfully with offline renderers and multiple graphics cards.

    Apple ships many sophisticated hardware configurations. Your application should handle renderer changesseamlessly. You should test your application on a Mac with multiple graphics processors and include testsfor attaching and removing displays. For more information on how to implement hot plugging correctly,see Working with Rendering Contexts (page 72)

    Avoid finishing and flushing operations.

    Pay particular attention to OpenGL functions that force previously submitted commands to complete.Synchronizing the graphics hardware to the CPU may result in dramatically lower performance. Performanceis covered in detail in OpenGL Application Design Strategies (page 89).

    Use multithreading to improve the performance of your OpenGL application.

    Many Macs support multiple simultaneous threads of execution. Your application should take advantageof concurrency. Well-behaved applications can take advantage of concurrency in just a few line of code.See Concurrency and OpenGL (page 148).

    Use buffer objects to manage your data.

    Vertex buffer objects (VBOs) allow OpenGL to manage your applications vertex data. Using vertex bufferobjects gives OpenGL more opportunities to cache vertex data in a format that is friendly to the graphicshardware, improving application performance. For more information see Best Practices for Working withVertex Data (page 104).

    Similarly, pixel buffer objects (PBOs) should be used to manage your image data. See Best Practices forWorking with Texture Data (page 118)

    Use framebuffer objects (FBOs) when you need to render to offscreen memory.

    Framebuffer objects allow your application to create offscreen rendering targets without many of thelimitations of platform-dependent interfaces. See Rendering to a Framebuffer Object (page 53).

    Generate objects before binding them.

    Earlier version of OpenGL allowed your applications to create its own object names before binding them.However, you should avoid this. Always use the OpenGL API to generate object names.

    Migrate your OpenGL Applications to OpenGL 3.2

    OpenGL on the Mac PlatformMaking Great OpenGL Applications on the Macintosh

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    33

  • The OpenGL 3.2 Core profile provides a clean break from earlier versions of OpenGL in favor of a simplershader-based pipeline. For better compatibility with future hardware and OS X releases, migrate yourapplications away from legacy versions of OpenGL. Many of the recommendations listed above are requiredwhen your application uses OpenGL 3.2.

    Harness the power of Apples development tools.

    Apple provides many tools that help create OpenGL applications and analyze and tune their performance.Learning how to use these tools helps you create fast, reliable applications. Tuning Your OpenGLApplication (page 155) describes many of these tools.

    OpenGL on the Mac PlatformMaking Great OpenGL Applications on the Macintosh

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    34

  • The OpenGL programming interface provides hundreds of drawing commands that drive graphics hardware.It doesn't provide any commands that interface with the windowing system of an operating system. Withouta windowing system, the 3D graphics of an OpenGL program are trapped inside the GPU. Figure 2-1 shows acube drawn to a Cocoa view.

    Figure 2-1 OpenGL content in a Cocoa view

    This chapter shows how to display OpenGL drawing onscreen using the APIs provided by OS X. (This chapterdoes not show how to use GLUT.) The first section describes the overall approach to drawing onscreen andprovides an overview of the functions and methods used by each API.

    General ApproachTo draw your content to a view or a layer, your application uses the NSOpenGL classes from within the Cocoaapplication framework. While the CGL API is used by your applications only to create full-screen content, everyNSOpenGLContext object contains a CGL context object. This object can be retrieved from theNSOpenGLContext when your application needs to reference it directly. To show the similarities between thetwo, this chapter discusses both the NSOpenGL classes and the CGL API.

    To draw OpenGL content to a window or view using the NSOpenGL classes, you need to perform these tasks:

    1. Set up the renderer and buffer attributes that support the OpenGL drawing you want to perform.

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    35

    Drawing to a Window or View

  • Each of the OpenGL APIs in OS X has its own set of constants that represent renderer and buffer attributes.For example, the all-renderers attribute is represented by the NSOpenGLPFAAllRenderers constant inCocoa and the kCGLPFAAllRenderers constant in the CGL API.

    2. Request, from the operating system, a pixel format object that encapsulates pixel storage information andthe renderer and buffer attributes required by your application. The returned pixel format object containsall possible combinations of renderers and displays available on the system that your program runs onand that meets the requirements specified by the attributes. The combinations are referred to as virtualscreens . (See Virtual Screens (page 26).)

    There may be situations for which you want to ensure that your program uses a specific renderer. ChoosingRenderer and Buffer Attributes (page 64) discusses how to set up an attributes array that guarantees thesystem passes back a pixel format object that uses only that renderer.

    If an error occurs, your application may receive a NULL pixel format object. Your application must handlethis condition.

    3. Create a rendering context and bind the pixel format object to it. The rendering context keeps track ofstate information that controls such things as drawing color, view and projection matrices, characteristicsof light, and conventions used to pack pixels.

    Your application needs a pixel format object to create a rendering context.

    4. Release the pixel format object. Once the pixel format object is bound to a rendering context, its resourcesare no longer needed.

    5. Bind a drawable object to the rendering context. For a windowed context, this is typically a Cocoa view.

    6. Make the rendering context the current context. The system sends OpenGL drawing to whichever renderingcontext is designated as the current one. It's possible for you to set up more than one rendering context,so you need to make sure that the one you want to draw to is the current one.

    7. Perform your drawing.

    The specific functions or methods that you use to perform each of the steps are discussed in the sections thatfollow.

    Drawing to a Cocoa ViewThere are two ways to draw OpenGL content to a Cocoa view. If your application has modest drawingrequirements, then you can use the NSOpenGLView class. See Drawing to an NSOpenGLView Class: ATutorial (page 37).

    Drawing to a Window or ViewDrawing to a Cocoa View

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    36

  • If your application is more complex and needs to support drawing to multiple rendering contexts, you maywant to consider subclassing the NSView class. For example, if your application supports drawing to multipleviews at the same time, you need to set up a custom NSView class. See Drawing OpenGL Content to a CustomView (page 40).

    Drawing to an NSOpenGLView Class: A TutorialThe NSOpenGLView class is a lightweight subclass of the NSView class that provides convenience methodsfor setting up OpenGL drawing. An NSOpenGLView object maintains an NSOpenGLPixelFormat object andan NSOpenGLContext object into which OpenGL calls can be rendered. It provides methods for accessingand managing the pixel format object and the rendering context, and handles notification of visible regionchanges.

    An NSOpenGLView object does not support subviews. You can, however, divide the view into multiple renderingareas using the OpenGL function glViewport.

    This section provides step-by-step instructions for creating a simple Cocoa application that draws OpenGLcontent to a view. The tutorial assumes that you know how to use Xcode and Interface Builder. If you havenever created an application using the Xcode development environment, see Getting Started with Tools.

    1. Create a Cocoa application project named Golden Triangle.

    2. Add the OpenGL framework to your project.

    3. Add a new file to your project using the Objective-C class template. Name the file MyOpenGLView.m andcreate a header file for it.

    4. Open the MyOpenGLView.h file and modify the file so that it looks like the code shown in Listing 2-1 todeclare the interface.

    Listing 2-1 The interface for MyOpenGLView

    #import

    @interface MyOpenGLView : NSOpenGLView

    {

    }

    - (void) drawRect: (NSRect) bounds;

    @end

    5. Save and close the MyOpenGLView.h file.

    6. Open the MyOpenGLView.m file and include the gl.h file, as shown in Listing 2-2.

    Drawing to a Window or ViewDrawing to a Cocoa View

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    37

  • Listing 2-2 Include OpenGL/gl.h

    #import "MyOpenGLView.h"

    #include

    @implementation MyOpenGLView

    @end

    7. Implement the drawRect:method as shown in Listing 2-3, adding the code after the @implementationstatement. The method sets the clear color to black and clears the color buffer in preparation for drawing.Then, drawRect: calls your drawing routine, which youll add next. The OpenGL command glFlushdraws the content provided by your routine to the view.

    Listing 2-3 The drawRect: method for MyOpenGLView

    -(void) drawRect: (NSRect) bounds

    {

    glClearColor(0, 0, 0, 0);

    glClear(GL_COLOR_BUFFER_BIT);

    drawAnObject();

    glFlush();

    }

    8. Add the code to perform your drawing. In your own application, you'd perform whatever drawing isappropriate. But for the purpose of learning how to draw OpenGL content to a view, add the code shownin Listing 2-4. This code draws a 2D, gold-colored triangle, whose dimensions are not quite the dimensionsof a true golden triangle, but good enough to show how to perform OpenGL drawing.

    Make sure that you insert this routine before the drawRect: method in the MyOpenGLView.m file.

    Listing 2-4 Code that draws a triangle using OpenGL commands

    static void drawAnObject ()

    {

    glColor3f(1.0f, 0.85f, 0.35f);

    glBegin(GL_TRIANGLES);

    {

    Drawing to a Window or ViewDrawing to a Cocoa View

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    38

    Fabio Mainardi

  • glVertex3f( 0.0, 0.6, 0.0);

    glVertex3f( -0.2, -0.3, 0.0);

    glVertex3f( 0.2, -0.3 ,0.0);

    }

    glEnd();

    }

    9. Open the MainMenu.xib in Interface Builder.

    10. Change the windows title to Golden Triangle.

    11. Drag an NSOpenGLView object from the Library to the window. Resize the view to fit the window.

    12. Change the class of this object to MyOpenGLView.

    13. Open the Attributes pane of the inspector for the view, and take a look at the renderer and buffer attributesthat are available to set. These settings save you from setting attributes programmatically.

    Only those attributes listed in the Interface Builder inspector are set when the view is instantiated. If youneed additional attributes, you need to set them programmatically.

    14. Build and run your application. You should see content similar to the triangle shown in Figure 2-2.

    Figure 2-2 The output from the Golden Triangle program

    This example is extremely simple. In a more complex application, you'd want to do the following:

    Replace the immediate-mode drawing commands with commands that persist your vertex data insideOpenGL. See OpenGL Application Design Strategies (page 89).

    Drawing to a Window or ViewDrawing to a Cocoa View

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    39

  • In the interface for the view, declare a variable that indicates whether the view is ready to accept drawing.A view is ready for drawing only if it is bound to a rendering context and that context is set to be thecurrent one.

    Cocoa does not call initialization routines for objects created in Interface Builder. If you need to performany initialization tasks, do so in the awakeFromNib method for the view. Note that because you setattributes in the inspector, there is no need to set them up programmatically unless you need additionalones. There is also no need to create a pixel format object programmatically; it is created and loaded whenCocoa loads the nib file.

    Your drawRect: method should test whether the view is ready to draw into. You need to provide codethat handles the case when the view is not ready to draw into.

    OpenGL is at its best when doing real-time and interactive graphics. Your application needs to provide atimer or support user interaction. For more information about creating animation in your OpenGLapplication, see Synchronize with the Screen Refresh Rate (page 96).

    Drawing OpenGL Content to a Custom ViewThis section provides an overview of the key tasks you need to perform to customize the NSView class forOpenGL drawing. Before you create a custom view for OpenGL drawing, you should read Creating a CustomView in View Programming Guide .

    When you subclass the NSView class to create a custom view for OpenGL drawing, you override any Quartzdrawing or other content that is in that view. To set up a custom view for OpenGL drawing, subclass NSViewand create two private variablesone which is an NSOpenGLContext object and the other anNSOpenGLPixelFormat object, as shown in Listing 2-5.

    Listing 2-5 The interface for a custom OpenGL view

    @class NSOpenGLContext, NSOpenGLPixelFormat;

    @interface CustomOpenGLView : NSView

    {

    @private

    NSOpenGLContext* _openGLContext;

    NSOpenGLPixelFormat* _pixelFormat;

    }

    + (NSOpenGLPixelFormat*)defaultPixelFormat;

    - (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format;

    - (void)setOpenGLContext:(NSOpenGLContext*)context;

    Drawing to a Window or ViewDrawing to a Cocoa View

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    40

  • - (NSOpenGLContext*)openGLContext;

    - (void)clearGLContext;

    - (void)prepareOpenGL;

    - (void)update;

    - (void)setPixelFormat:(NSOpenGLPixelFormat*)pixelFormat;

    - (NSOpenGLPixelFormat*)pixelFormat;

    @end

    In addition to the usual methods for the private variables (openGLContext, setOpenGLContext:,pixelFormat, and setPixelFormat:) you need to implement the following methods:

    + (NSOpenGLPixelFormat*) defaultPixelFormat

    Use this method to allocate and initialize the NSOpenGLPixelFormat object.

    - (void) clearGLContext

    Use this method to clear and release the NSOpenGLContext object.

    - (void) prepareOpenGL

    Use this method to initialize the OpenGL state after creating the NSOpenGLContext object.

    You need to override the update and initWithFrame: methods of the NSView class.

    update calls the update method of the NSOpenGLContext class.

    initWithFrame:pixelFormat retains the pixel format and sets up the notificationNSViewGlobalFrameDidChangeNotification. See Listing 2-6.

    Listing 2-6 The initWithFrame:pixelFormat: method

    - (id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat*)format

    {

    self = [super initWithFrame:frameRect];

    if (self != nil) {

    _pixelFormat = [format retain];

    [[NSNotificationCenter defaultCenter] addObserver:self

    selector:@selector(_surfaceNeedsUpdate:)

    name:NSViewGlobalFrameDidChangeNotification

    object:self];

    }

    Drawing to a Window or ViewDrawing to a Cocoa View

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    41

  • return self;

    }

    - (void) _surfaceNeedsUpdate:(NSNotification*)notification

    {

    [self update];

    }

    If the custom view is not guaranteed to be in a window, you must also override the lockFocus method ofthe NSView class. See Listing 2-7. This method makes sure that the view is locked prior to drawing and thatthe context is the current one.

    Listing 2-7 The lockFocus method

    - (void)lockFocus

    {

    NSOpenGLContext* context = [self openGLContext];

    [super lockFocus];

    if ([context view] != self) {

    [context setView:self];

    }

    [context makeCurrentContext];

    }

    The reshape method is not supported by the NSView class. You need to update bounds in the drawRect:method, which should take the form shown in Listing 2-8.

    Listing 2-8 The drawRect method for a custom view

    -(void) drawRect

    {

    [context makeCurrentContext];

    //Perform drawing here

    [context flushBuffer];

    }

    Drawing to a Window or ViewDrawing to a Cocoa View

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    42

  • There may be other methods that you want to add. For example, you might consider detaching the contextfrom the drawable object when the custom view is moved from the window, as shown in Listing 2-9.

    Listing 2-9 Detaching the context from a drawable object

    -(void) viewDidMoveToWindow

    {

    [super viewDidMoveToWindow];

    if ([self window] == nil)

    [context clearDrawable];

    }

    Drawing to a Window or ViewDrawing to a Cocoa View

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    43

  • OpenGL is a pixel-based API so the NSOpenGLView class does not provide high-resolution surfaces by default.Because adding more pixels to renderbuffers has performance implications, you must explicitly opt in to supporthigh-resolution screens. Its easy to enable high-resolution backing for an OpenGL view. When you do, youllwant to perform a few additional tasks to ensure the best possible high-resolution experience for your users.

    Enable High-Resolution Backing for an OpenGL ViewYou can opt in to high resolution by calling the method setWantsBestResolutionOpenGLSurface:whenyou initialize the view, and supplying YES as an argument:

    [self setWantsBestResolutionOpenGLSurface:YES];

    If you dont opt in, the system magnifies the rendered results.

    The wantsBestResolutionOpenGLSurface property is relevant only for views to which anNSOpenGLContext object is bound. Its value does not affect the behavior of other views. For compatibility,wantsBestResolutionOpenGLSurface defaults to NO, providing a 1-pixel-per-point framebuffer regardlessof the backing scale factor for the display the view occupies. Setting this property to YES for a given viewcauses AppKit to allocate a higher-resolution framebuffer when appropriate for the backing scale factor andtarget display.

    To function correctly with wantsBestResolutionOpenGLSurface set to YES, a view must perform correctconversions between view units (points) and pixel units as needed. For example, the common practice ofpassing the width and height of [self bounds] to glViewport()will yield incorrect results at high resolution,because the parameters passed to the glViewport() function must be in pixels. As a result, youll get onlypartial instead of complete coverage of the render surface. Instead, use the backing store bounds:

    [self convertRectToBacking:[self bounds]];

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    44

    Optimizing OpenGL for High Resolution

  • You can also opt in to high resolution by enabling the Supports Hi-Res Backing setting for the OpenGL viewin Xcode, as shown in Figure 3-1.

    Figure 3-1 Enabling high-resolution backing for an OpenGL view

    Set Up the Viewport to Support High ResolutionThe viewport dimensions are in pixels relative to the OpenGL surface. Pass the width and height to glViewPortand use 0,0 for the x and y offsets. Listing 3-1 shows how to get the view dimensions in pixels and take thebacking store size into account.

    Listing 3-1 Setting up the viewport for drawing

    - (void)drawRect:(NSRect)rect // NSOpenGLView subclass

    {

    // Get view dimensions in pixels

    NSRect backingBounds = [self convertRectToBacking:[self bounds]];

    Optimizing OpenGL for High ResolutionSet Up the Viewport to Support High Resolution

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    45

  • GLsizei backingPixelWidth = (GLsizei)(backingBounds.size.width),

    backingPixelHeight = (GLsizei)(backingBounds.size.height);

    // Set viewport

    glViewport(0, 0, backingPixelWidth, backingPixelHeight);

    // draw

    }

    You dont need to perform rendering in pixels, but you do need to be aware of the coordinate system youwant to render in. For example, if you want to render in points, this code will work:

    glOrtho(NSWidth(bounds), NSHeight(bounds),...)

    Adjust Model and Texture AssetsIf you opt in to high-resolution drawing, you also need to adjust the model and texture assets of your app. Forexample, when running on a high-resolution display, you might want to choose larger models and moredetailed textures to take advantage of the increased number of pixels. Conversely, on a standard-resolutiondisplay, you can continue to use smaller models and textures.

    If you create and cache textures when you initialize your app, you might want to consider a strategy thataccommodates changing the texture based on the resolution of the display.

    Check for Calls Defined in Pixel DimensionsThese functions use pixel dimensions:

    glViewport (GLint x, GLint y, GLsizei width, GLsizei height)

    glScissor (GLint x, GLint y, GLsizei width, GLsizei height)

    glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, ...)

    glLineWidth (GLfloat width)

    glRenderbufferStorage (..., GLsizei width, GLsizei height)

    glTexImage2D (..., GLsizei width, GLsizei height, ...)

    Optimizing OpenGL for High ResolutionAdjust Model and Texture Assets

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    46

  • Tune OpenGL Performance for High ResolutionPerformance is an important factor when determining whether to support high-resolution content. Thequadrupling of pixels that occurs when you opt in to high resolution requires more work by the fragmentprocessor. If your app performs many per-fragment calculations, the increase in pixels might reduce its framerate. If your app runs significantly slower at high resolution, consider the following options:

    Optimize fragment shader performance. (See Tuning Your OpenGL Application (page 155).)

    Choose a simpler algorithm to implement in your fragment shader. This reduces the quality of eachindividual pixel to allow for rendering the overall image at a higher resolution.

    Use a fractional scale factor between 1.0 and 2.0. A scale factor of 1.5 provides better quality than a scalefactor of 1.0, but it needs to fill fewer pixels than an image scaled to 2.0.

    Multisampling antialiasing can be costly with marginal benefit at high resolution. If you are using it, youmight want to reconsider.

    The best solution depends on the needs of your OpenGL app; you should test more than one of these optionsand choose the approach that provides the best balance between performance and image quality.

    Optimizing OpenGL for High ResolutionTune OpenGL Performance for High Resolution

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    47

  • Use a Layer-Backed View to Overlay Text on OpenGL ContentWhen you draw standard controls and Cocoa text to a layer-backed view, the system handles scaling thecontents of that layer for you. You need to perform only a few steps to set and use the layer. Compare thecontrols and text in standard and high resolutions, as shown in Figure 3-2. The text looks the same on bothwithout any additional work on your part.

    Figure 3-2 A text overlay scales automatically for standard resolution (left) and high resolution (right)

    To set up a layer-backed view for OpenGL content

    1. Set the wantsLayer property of your NSOpenGLView subclass to YES.

    Enabling the wantsLayer property of an NSOpenGLView object activates layer-backed rendering ofthe OpenGL view. Drawing a layer-backed OpenGL view proceeds mostly normally through the viewsdrawRect:method. The layer-backed rendering mode uses its own NSOpenGLContext object, whichis distinct from the NSOpenGLContext that the view uses for drawing in non-layer-backed mode.

    AppKit automatically creates this context and assigns it to the view by invoking thesetOpenGLContext: method. The views openGLContext accessor will return the layer-backedOpenGL context (rather than the non-layer-backed context) while the view is operating in layer-backedmode.

    Optimizing OpenGL for High ResolutionUse a Layer-Backed View to Overlay Text on OpenGL Content

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    48

  • 2. Create the layer content either as a XIB file or programmatically.

    The controls shown in Figure 3-2 were created in a XIB file by subclassing NSBox and using static textwith a variety of standard controls. Using this approach allows the NSBox subclass to ignore mouseevents while still allowing the user to interact with the OpenGL content.

    3. Add the layer to the OpenGL view by calling the addSublayer: method.

    Use an Application Window for Fullscreen OperationFor the best user experience, if you want your app to run full screen, create a window that covers the entirescreen. This approach offers two advantages:

    The system provides optimized context performance.

    Users will be able to see critical system dialogs above your content.

    You should avoid changing the display mode of the system.

    Convert the Coordinate Space When Hit TestingAlways convert window event coordinates when performing hit testing in OpenGL. The locationInWindowmethod of the NSEvent class returns the receivers location in the base coordinate system of the window. Youthen need to call the convertPoint:fromView: method to get the local coordinates for the OpenGL view.

    NSPoint aPoint = [theEvent locationInWindow];

    NSPoint localPoint = [myOpenGLView convertPoint:aPoint fromView:nil];

    Optimizing OpenGL for High ResolutionUse an Application Window for Fullscreen Operation

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    49

  • In OS X, you have the option to draw to the entire screen. This is a common scenario for games and otherimmersive applications, and OS X applies additional optimizations to improve the performance of full-screencontexts.

    Figure 4-1 Drawing OpenGL content to the full screen

    OS X v10.6 and later automatically optimize the performance of screen-sized windows, allowing your applicationto take complete advantage of the window server environment on OS X. For example, critical operating systemdialogs may be displayed over your content when necessary.

    For information about high-resolution and full-screen drawing, see Use an Application Window for FullscreenOperation (page 49).

    Creating a Full-Screen ApplicationCreating a full-screen context is very simple. Your application should follow these steps:

    1. Create a screen-sized window on the display you want to take over:

    NSRect mainDisplayRect = [[NSScreen mainScreen] frame];

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    50

    Drawing to the Full Screen

  • NSWindow *fullScreenWindow = [[NSWindow alloc] initWithContentRect:mainDisplayRect styleMask:NSBorderlessWindowMaskbacking:NSBackingStoreBuffered defer:YES];

    2. Set the window level to be above the menu bar.:

    [fullScreenWindow setLevel:NSMainMenuWindowLevel+1];

    3. Perform any other window configuration you desire:

    [fullScreenWindow setOpaque:YES];

    [fullScreenWindow setHidesOnDeactivate:YES];

    4. Create a view with a double-buffered OpenGL context and attach it to the window:

    NSOpenGLPixelFormatAttribute attrs[] =

    {

    NSOpenGLPFADoubleBuffer,

    0

    };

    NSOpenGLPixelFormat* pixelFormat = [[NSOpenGLPixelFormat alloc]initWithAttributes:attrs];

    NSRect viewRect = NSMakeRect(0.0, 0.0, mainDisplayRect.size.width,mainDisplayRect.size.height);

    MyOpenGLView *fullScreenView = [[MyOpenGLView alloc] initWithFrame:viewRectpixelFormat: pixelFormat];

    [fullScreenWindow setContentView: fullScreenView];

    5. Show the window:

    [fullScreenWindow makeKeyAndOrderFront:self];

    Thats all you need to do. Your content is in a window that is above most other content, but because it is in awindow, OS X can still show critical UI elements above your content when necessary (such as error dialogs).When there is no content above your full-screen window, OS X automatically attempts to optimize this contextsperformance. For example, when your application calls flushBuffer on the NSOpenGLContext object, the

    Drawing to the Full ScreenCreating a Full-Screen Application

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    51

  • system may swap the buffers rather than copying the contents of the back buffer to the front buffer. Theseperformance optimizations are not applied when your application adds the NSOpenGLPFABackingStoreattribute to the context. Because the system may choose to swap the buffers rather than copy them, yourapplication must completely redraw the scene after every call to flushBuffer. For more information onNSOpenGLPFABackingStore, see Ensuring That Back Buffer Contents Remain the Same (page 66).

    Avoid changing the display resolution from that chosen by the user. If your application needs to render dataat a lower resolution for performance reasons, you can explicitly create a back buffer at the desired resolutionand allow OpenGL to scale those results to the display. See Controlling the Back Buffer Size (page 78).

    Drawing to the Full ScreenCreating a Full-Screen Application

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    52

  • OpenGL applications may want to use OpenGL to render images without actually displaying them to the user.For example, an image processing application might render the image, then copy that image back to theapplication and save it to disk. Another useful strategy is to create intermediate images that are used later torender additional content. For example, your application might want to render an image and use it as a texturein a future rendering pass. For best performance, offscreen targets should be managed by OpenGL. HavingOpenGL manage offscreen targets allows you to avoid copying pixel data back to your application, exceptwhen this is absolutely necessary.

    OS X offers two useful options for creating offscreen rendering targets:

    Framebuffer objects. The OpenGL framebuffer extension allows your application to create fully supportedoffscreen OpenGL framebuffers. Framebuffer objects are fully supported as a cross-platform extension, sothey are the preferred way to create offscreen rendering targets. See Rendering to a FramebufferObject (page 53).

    Pixel buffer drawable objects. Pixel buffer drawable objects are an Apple-specific technology for creatingan offscreen target. Each of the Apple-specific OpenGL APIs provides routines to create an offscreenhardware accelerated pixel buffer. Pixel buffers are recommended for use only when framebuffer objectsare not available. See Rendering to a Pixel Buffer (page 60).

    Rendering to a Framebuffer ObjectThe OpenGL framebuffer extension (GL_EXT_framebuffer_object) allows applications to create offscreenrendering targets from within OpenGL. OpenGL manages the memory for these framebuffers.

    Note: Extensions are available on a per-renderer basis. Before you use framebuffer objects you mustcheck each renderer to make sure that it supports the extension. See Detecting Functionality (page83) for more information.

    A framebuffer object (FBO) is similar to a drawable object, except a drawable object is a window-system-specificobject, whereas a framebuffer object is a window-agnostic object that's defined in the OpenGL standard. Afterdrawing to a framebuffer object, it is straightforward to read the pixel data to the application, or to use it assource data for other OpenGL commands.

    2012-07-23 | Copyright 2004, 2012 Apple Inc. All Rights Reserved.

    53

    Drawing Offscreen

  • Framebuffer objects offer a number of benefits:

    They are window-system independent, which makes porting code easier.

    They are easy to set up and save memory. There is no need to set up attributes and obtain a pixel formatobject.

    They are associated with a single OpenGL context, whereas each pixel buffer must be bound to a context.

    You can switch between them faster since there is no context switch as with pixel buffers. Because allcommands are rendered by a single context, no additional serialization is required.

    They can share depth buffers; pixel buffers cannot.

    You can use them for 2D pixel images and texture images.

    Completeness is a key concept to understanding framebuffer objects. Completeness is a state that indicateswhether a framebuffer object meets all the requirements for drawing. You test for this state after performingall the necessary setup work. If a framebuffer object is not complete, it cannot be used as the destination forrendering operations and as a source for read operations.

    Completeness is dependent on many factors that are not possible to condense into one or two statements,but these factors are thoroughly defined in the OpenGL specification for the framebuffer object extension. Thespecification describes the requirements for internal formats of images attached to the framebuffer, how todetermine if a format is color-, depth-