The OpenGL specification defines the concept of the Context. The context contains all of the information that will be used by the OpenGL system to render, when the system is given a rendering command. A context effectively is OpenGL, because OpenGL cannot be used without one.
OpenGL contexts are local to a particular application; you cannot peek at another application's contexts. However, each application can have multiple contexts. Each context is completely separate and isolated from one another, with one exception. Objects (see below) can be shared between contexts, if the contexts are setup to do so when they are initially created.
All OpenGL functions operate on the context which is "current". This is very much like a global variable that every OpenGL function operates on. OpenGL functions do not work unless a context is current.
Note: To be technical, OpenGL function pointers retrieved from one context should not be used with function pointers retrieved from another context. That being said, this will almost never cause problems, so long as the same driver is servicing both contexts.
While the OpenGL specification details the behavior of contexts, it does not cover the creation
of them. This is governed by platform-specific APIs. Therefore, while OpenGL code is generally platform-neutral, it is always dependent on some platform-specific code to create and destroy OpenGL contexts.
The OpenGL specification, usually, defines the behavior of commands such that they will execute in the order given, and that every subsequent command must behave as if all prior commands have completed and their contents are visible. However, it is important to keep in mind that this is how OpenGL is specified, not how it is implemented.
OpenGL implementations attempt to do as much work asynchronously as possible. When a rendering function returns, odds are good that the actual rendering operation has not even started yet, let alone has finished. However, as long as you don't query any state that would be changed by that rendering command (such as the content of the destination images), you would not be able to tell the difference.
The key phrase to remember from the above definition is "as if". The implementation must make rendering look synchronous, while being as asynchronous as possible. So for best performance, you must avoid querying state that has been affected by rendering commands. You must also avoid changing the contents of objects that will be used by rendering commands that have been sent but may not yet have executed.
The OpenGL Memory Model governs when state set by one OpenGL command becomes visible to other commands. Normally, the memory model is perfectly sequential and synchronous: state set by one command is immediately visible to any subsequent command, but not any prior ones. However, there are certain cases where the model breaks down or otherwise requires explicit synchronization.
Rendering to the same image as one is sampling from is one such case. A second case is when dealing with multiple contexts that have objects shared between them. State set from one context may not be immediately visible in another; special considerations need to be taken.
The big one has to do with arbitrary image reads/writes
in GL 4.2+. The use of this feature (as well as some related ones
) completely throws out any implicit GL memory model
, thus forcing all synchronization for these operations on the user.
Debugging an OpenGL application can be difficult. But OpenGL does provide ways to make debugging more reasonable.
OpenGL requires its functions to check their parameters for mistakes or inconsistencies, and emit errors when this occurs. Many other aspects of function calls are checked, to make sure that the current context state matches with what the system expects. If it does not, other errors are emitted.
Because error checking is a very manual process, many OpenGL implementations provide access to Debug Output. This functionality is a powerful mechanism for testing against these kinds of errors.
These mechanisms only test malformed use of the API; there are many things that can go wrong which are not checked for. For these, there are a number of Debugging Tools
available to help track down various issues.
The OpenGL context contains information used by the rendering system. This information is called State, which has given rise to the saying that OpenGL is a "state machine". A piece of state is simply some value stored in the OpenGL context.
There is a way to uniquely identify every individual piece of state in the OpenGL context. The OpenGL specification document has a massive table at the end, defining what these identifiers are and which state they can be used to query. Not all of the identifiers are as simple as an enumeration, as OpenGL state can be in lists, where each entry must be queried individually.
When a context is created, every piece of state is initialized to a well-defined default value. The state table defines what the initial value is for every piece of OpenGL state. Note that this does not mean that a freshly created context can be used to render with without some setup work.
OpenGL functions can be grouped into 3 broad categories: functions that set state into the context, functions that query state, and functions that render, given the current state of the context. Functions that query state use the unique identifier to name which state value they retrieve. The state table in the specification says which functions are used to query each state value.
Certain OpenGL state values are aggregated into objects. This allows groups of state to be stored and reset with a single command. Most objects in OpenGL are defined as groups of context state, even if that context state is not available if no object is currently in use.
Most objects in OpenGL follow the same general paradigm and naming convention. Object names are GLuints; these are handles used to identify an object. Live objects are created with a function of the form glGen*; those objects are deleted with a call to the equivalent glDelete*. Objects are aggregates of state, and state exists within the OpenGL context. Therefore, to modify an object or to use it to render something, the object must first be bound to the context. The function to do this is of the form glBind*. Any functions that modify or query the state that this object contains will modify/query the object's internal state.
The object 0 is special, and it has different behaviors for different object types. For many objects, 0 represents "not an object", much like a NULL pointer. For a few object types, it is a default object, which can not be destroyed. In general, with the exception of Framebuffers
, you should treat 0 like NULL: an invalid object.
The Rendering Pipeline is the sequence of steps that are taken by the OpenGL rendering system when the user issues a rendering command. The pipeline is a sequential series of steps, where each step performs some computation and passes its data to the next step for further processing.
The OpenGL specification is very clear on the order in which objects are rendered. Specifically, objects are rendered in the exact order the user provides. While implementations are free to adjust the order internally, the rendered output must be as if it were processed in order.
Certain stages of the rendering pipeline are programmable. The term for a programmable stage of the pipeline is Shader, and the programs that are executed by that pipeline stage are called "Shaders".
In OpenGL, shaders are written in the OpenGL Shading Language
. Many OpenGL implementations offer extensions that provide alternative languages.
A Framebuffer is a OpenGL object that aggregates images together, which rendering operations can use as their eventual destination. Every OpenGL context has a Default Framebuffer, which is usually associated with a window or other display device. Rendering operations that are intended to be directly visualized should go to the default framebuffer.
Users can construct Framebuffer Objects
, framebuffers built from images provided by Textures
. These are useful for rendering data off-screen; the data can later be transferred to the default framebuffer.
In OpenGL version 3.0, a lot of redundant yet long-standing functionality was marked Deprecated. This means that it was still supported, but the ARB would be willing to remove it in later versions. In OpenGL 3.1, most of this functionality was removed (and therefore is not deprecated). In OpenGL 3.2, the removed functionality was spun off into a "compatibility profile" specification. The core profile would continue to not have this functionality.
This wiki focuses primarily on the core profile of OpenGL.