Difference between revisions of "OpenGL Object"

From OpenGL.org
Jump to: navigation, search
(Object Creation and Destruction: Wording correction.)
(Object zero)
(11 intermediate revisions by 3 users not shown)
Line 1: Line 1:
 +
{{object float}}
 
'''OpenGL Objects''' are defined in terms of the context state that they contain. When they are bound to the context, the state that they contain is mapped into the context's state. Thus, changes to context state will be stored in this object, and functions that act on this context state will use the state stored in the object.
 
'''OpenGL Objects''' are defined in terms of the context state that they contain. When they are bound to the context, the state that they contain is mapped into the context's state. Thus, changes to context state will be stored in this object, and functions that act on this context state will use the state stored in the object.
  
Line 11: Line 12:
 
== Object Creation and Destruction ==
 
== Object Creation and Destruction ==
  
To create an object, you generate the object's name. This creates a reference to the object. The object will only contain its default state when it is first bound to the context.
+
To create an object, you generate the object's ''name'' (an integer). This creates a reference to the object. The object will only contain its default state when it is first bound to the context.
  
The functions to generate the object's name this are of the form <code>glGen*</code>, where * is the object's type. All functions of this type have the same signature:
+
The functions to generate the object's name are of the form {{code|glGen*}}, where * is the object's type in plural form. All functions of this type have the same signature:
  
<code>
+
  void glGen*(GLsizei {{param|n}}, GLuint *{{param|objects}});
void glGen*(GLsizei ''n'', GLuint *''objects'');
+
</code>
+
  
This function generates <code>n</code> objects of the given type, storing them in the array given by the <code>objects</code> parameter. This allows you to create multiple objects with one call.
+
This function generates {{param|n}} objects of the given type, storing them in the array given by the {{param|objects}} parameter. This allows you to create multiple objects with one call.
  
An object name is always a GLuint. These names are not pointers, nor should you assume that they are. They are names, numbers that identify an object. They can be any 32-bit unsigned integer except 0. The object number 0 is never a valid object; it is how you specify that you don't want to use an object.
+
An object name is always a GLuint. These names are not pointers, nor should you assume that they are. They are references, numbers that identify an object. They can be any 32-bit unsigned integer except 0. The object number 0 is reserved for special use cases; see below for details.
  
: '''Legacy Note:''' In OpenGL versions before 3.0, the user was allowed to ignore the generation step entirely. The user could just decide that "3" is a valid object name, and start using it like an object. The implementation would then have to accept that and create the object behind the scenes when you first start using it. In GL 3.0, this behavior was deprecated. In core GL 3.1 and above, this is no longer allowed. Regardless of the version of OpenGL, it is always good practice to use <code>glGen*</code> rather than making up your own object names.
+
: '''Legacy Note:''' In OpenGL versions before 3.0, the user was allowed to ignore the generation step entirely. The user could just decide that "3" is a valid object name, and start using it like an object. The implementation would then have to accept that and create the object behind the scenes when you first start using it. In GL 3.0, this behavior was deprecated. In core GL 3.1 and above, this is no longer allowed. Regardless of the version of OpenGL, it is always good practice to use {{code|glGen*}} rather than making up your own object names.
  
Once you are finished with an object, you should delete it. The functions for this are of the form <code>glDelete*</code>, using the same object type as before. These functions have this signature:
+
Once you are finished with an object, you should delete it. The functions for this are of the form {{code|glDelete*}}, using the same object type as before. These functions have this signature:
  
<code>
+
void glDelete*(GLsizei {{param|n}}, const GLuint *{{param|objects}});
void glDelete*(GLsizei ''n'', const GLuint *''objects'');
+
</code>
+
  
This works like the <code>glGen</code> functions, only it deletes the objects instead of creating them.
+
This works like the {{code|glGen*}} functions, only it deletes the objects instead of creating them.
  
=== Object Attachment and Orphaning ===
+
When OpenGL objects are deleted, their names are no longer considered valid. Following this call, a subsequent {{code|glGen*}} call may or may not reuse a previously-deleted name; you should not make assumptions either way.
  
Calling <code>glDelete*</code> on an object does not guarantee its ''immediate'' deletion. Because OpenGL is allowed to execute rendering commands well after you issue them (for maximum parallelism and performance), it is entirely possible for an object to remain with the OpenGL server for some time before it actually deletes it.
+
=== Deletion unbinding ===
  
Note that this is an implementation detail. Once you call <code>glDelete*</code> on the object, the object name becomes useless. You can no longer refer to that object, even if the object is still being used by the rendering pipeline.
+
When an object is deleted, if is bound to the current context (and note this ''only'' applies to the current context), then the object will be unbound from all binding to the context.
  
This is not the case for objects that can become attached to other objects. If you delete an object that is attached to another object, the object will continue to exist until all objects it is attached to are deleted, or the object becomes unattached. This is different from the orphaning described above; you can still refer to the object through normal commands. You shouldn't, because the object can be deleted later by commands that normally would not delete objects, but you still can.
+
{{note|This says "binding", not ''"attachment"''. Binding goes to the context; attachment is what you do when one object references another. Attachments are ''not'' severed due to this call.}}
  
If you have bound an object to the current GL context, and you call <code>glDelete*</code> on it, this will also cause that binding to be terminated. The context will be as though you had bound object name "0" (not an object) to the context. If you have bound the object to another context (though object sharing, see below), then the object will not be deleted.
+
Some objects can be associated with the context in unusual ways. These ways include, but are not limited to:
 +
 
 +
* [[Buffer Object]]s bound to [[Buffer Object#Binding indexed targets|indexed targets]] via {{apifunc|glBindBufferRange}} or its equivalents.
 +
* [[Texture]]s bound as [[Image Load Store#Images in the context|images]].
 +
 
 +
In such cases, these binds are ''not'' undone when the object is deleted. The only bindings that are undone are bindings that can be undone by calling the basic {{code|glBind*}} function for the object type.
 +
 
 +
So if you call {{apifunc|glBindBufferRange|(GL_UNIFORM_BUFFER, ...)}} and then delete that buffer, it will be as if {{apifunc|glBindBuffer|(GL_UNIFORM_BUFFER, 0)}} was called. This does not unbind it from the indexed target.
 +
 
 +
=== Deletion orphaning ===
 +
 
 +
Calling {{code|glDelete*}} on an object does not guarantee its ''immediate'' deletion. Because OpenGL is allowed to execute rendering commands well after you issue them (for maximum parallelism and performance), it is entirely possible for an object to remain with the OpenGL server for some time before it actually deletes it.
 +
 
 +
If an object is still "in use" after it is deleted, then the object will remain alive within the OpenGL implementation. An object is "in use" if:
 +
 
 +
* It is bound to a context. This is not necessarily the current one, since deleting it will automatically unbind it from the current context. Though remember the caveat above about non-standard binding points.
 +
* It is attached to a [[#Container objects|container object]].
 +
 
 +
So if a [[Texture]] is attached to a [[Framebuffer Object]], the FBO will still be functional after deleting the texture. Only when the FBO is either deleted or a new texture attachment replaces the old will the texture finally be fully deleted.
 +
 
 +
Note that the name is still detectable via the OpenGL API. You can call {{apifunc|glGetFramebufferAttachmentParameter|iv(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)}} to fetch the object's name. However, the name is still considered unused, so don't use it for anything.
 +
 
 +
{{note|Some implementations don't implement that last part correctly. So ''really'' don't use this.}}
  
 
== Object Usage ==
 
== Object Usage ==
  
Because objects in OpenGL are defined as a collections of state, to modify objects, you must first bind them to the OpenGL context. Binding objects to the context causes the state in them to be set to be the current context's state. This also means that any functions that change the encapsulated state will simply change the state within the object, thus preserving that state.
+
Because objects in OpenGL are defined as a collections of state, to modify objects, you must first bind them to the OpenGL context. Binding objects to the context causes the state in them to be set to be the current context's state. This means that any functions that change the state governed by that object will simply change the state within the object, thus preserving that state.
 +
 
 +
Binding a newly generated object name will create new state for that object. In some cases, the target to which it is first bound (see below) will affect properties of the newly created state for the object.
  
 
Different objects have different binding functions. They do share a naming convention and general parameters:
 
Different objects have different binding functions. They do share a naming convention and general parameters:
  
<code>
+
void '''glBind*'''({{param|location}}, GLuint {{param|object}});
void glBind*(''location'', GLuint ''object'');
+
</code>
+
  
The * is the type of object, and <code>object</code> is the object to be bound.
+
The * is the type of object, and {{param|object}} is the object to be bound.
  
The ''location'' is where different object types differ. Some objects can be bound to multiple locations in the context, while others can only be bound to a specific place. For example, a buffer object can be bound as an array buffer, index buffer, pixel buffer, transform buffer, or various other possibilities. If an object can be bound to multiple locations, then there will be some kind of parameter to define where the binding happens. Buffer objects take an enumeration, for example.
+
The {{param|location}} is where different object types differ. Some objects can be bound to multiple locations in the context, while others can only be bound to a single specific place. For example, a buffer object can be bound as an array buffer, index buffer, pixel buffer, transform buffer, or various other possibilities. If an object can be bound to multiple locations, then there will be some kind of parameter to define where the binding happens. {{apifunc|glBindBuffer}} takes an enumeration, for example.
  
 
Different locations have separate bindings. So you can bind a buffer object as an array, and a different buffer object as an index buffer without having any crosstalk between them.
 
Different locations have separate bindings. So you can bind a buffer object as an array, and a different buffer object as an index buffer without having any crosstalk between them.
  
If an object is bound to a location where another object is also bound, the previously bound object will be unbound. If the <code>object</code> parameter is object 0 (not an object), then the currently bound object to that will be unbound, but no new object will be bound.
+
If an object is bound to a location where another object is also bound, the previously bound object will be unbound.
  
The way functions that access object state behave when object 0 is bound depends on what kind of object it is. [[Vertex Array Object|Vertex Array Objects]] for example, actually have state that corresponds to object 0. For VAOs, object 0 is essentially an undelete-able object; VAO object 0 can have its state set and modified exactly like a regular VAO.
+
=== Object zero ===
  
This is not the case for all objects. For [[Framebuffer Objects]], object 0 refers to the [[Default Framebuffer]]. This framebuffer does not behave like an FBO. Some functions that modify FBO state, like glDrawBuffers or glReadBuffer, will work just as well on the default framebuffer as on an FBO. More FBO-specific functions, like the ones to attach images to the FBO, will give rise to an error when object 0 is bound.
+
The GLuint value 0 is treated specially by OpenGL objects. However, some objects treat it in different ways. 0 will never be returned by a {{code|glGen*}} function.
 +
 
 +
For most object types, object 0 is much like the NULL pointer: it is not an object. If 0 is bound for such object types, then attempts to use that object for rendering purposes will fail.
 +
 
 +
For some objects, object 0 represents a kind of "default object". [[Texture]]s have this concept, though it is very complex, and object 0 cannot be deleted. Such default texture objects cannot be used in many of the ways that real texture objects can, so you are ''strongly'' encouraged to think of texture 0 as a non-existent texture, as above.
 +
 
 +
For [[Framebuffer Object]]s, object 0 represents the [[Default Framebuffer]]. While it has most of the same interfaces as user-created FBOs, it uses a very different set of images.
 +
 
 +
{{recommend|With the exception of [[Framebuffer Object]]s, you should completely ignore object 0. Even if an object type has a valid object 0, you should treat it as if it did not. Treat it as you would the NULL pointer in C/C++; you can store it in a pointer, but you can't ''use'' that pointer until you put a real pointer there.}}
  
 
== Object Sharing ==
 
== Object Sharing ==
Line 71: Line 98:
 
At context creation time however, you are able to create a context that shares objects with another context. This means you can use objects created in one context in another context.
 
At context creation time however, you are able to create a context that shares objects with another context. This means you can use objects created in one context in another context.
  
Not all object types can be shared across contexts. The unsharable objects tend to be ones made from simple state; objects that hold lots of data, like buffers or textures, are sharable.
+
Not all object types can be shared across contexts. [[#Container objects|Objects that contain references to other objects]] cannot be shared. All other object types can be shared. This includes [[GLSL Object]]s and [[Sync Object]]s, which do not follow the OpenGL Object model.
  
== Object Types ==
+
== Object types ==
  
* [[Buffer Object]]s, with a number of different uses:
+
Objects can be separated into two different categories: regular objects and container objects. Here is the list of regular objects.
** [[Vertex Buffer Object]]s
+
 
** [[Pixel Buffer Object]]s
+
* [[Buffer Object]]s
** [[Uniform Buffer Object]]s
+
* [[Query Object]]s
* [[Vertex Array Object]]s
+
* [[Renderbuffer Object]]s
 +
* [[Sampler Object]]s
 
* [[Texture|Texture Objects]]
 
* [[Texture|Texture Objects]]
 +
 +
=== Container objects ===
 +
 
* [[Framebuffer Object]]s
 
* [[Framebuffer Object]]s
** [[Renderbuffer Object]]s
+
* [[Program Pipeline Object]]s
 +
* [[Transform Feedback]] Objects
 +
* [[Vertex Array Object]]s
 +
 
 +
== Non-standard objects ==
  
The following are ''not'' OpenGL Objects. They are called "objects" in the OpenGL API, but they do not follow the well-defined conventions specified above:
+
The following are "objects", but they do not follow the standard conventions laid out on this page for OpenGL objects:
  
 
* [[Sync Object]]s
 
* [[Sync Object]]s
 
* [[GLSL Object|GLSL Shader and Program Objects]]
 
* [[GLSL Object|GLSL Shader and Program Objects]]
 +
** Except for program pipeline objects, which ''do'' follow the OpenGL Object conventions.
  
 
[[Category:Objects]]
 
[[Category:Objects]]
 
[[Category:General OpenGL]]
 
[[Category:General OpenGL]]

Revision as of 20:24, 14 February 2013

OpenGL Objects are defined in terms of the context state that they contain. When they are bound to the context, the state that they contain is mapped into the context's state. Thus, changes to context state will be stored in this object, and functions that act on this context state will use the state stored in the object.

State and Objects

OpenGL is defined as a state machine. The various API calls change the OpenGL state, query some part of that state, or cause OpenGL to use its current state to render something.

Objects are always containers for state. Each particular kind of object is defined by the particular state that it contains. An OpenGL object is a way to encapsulate a particular group of state and change all of it in one function call.

Remember: this is just how OpenGL is defined by its specification. How these objects are actually implemented in drivers is another matter. But that is nothing you need to worry about; what matters is how objects and state interact as defined by the specification.

Object Creation and Destruction

To create an object, you generate the object's name (an integer). This creates a reference to the object. The object will only contain its default state when it is first bound to the context.

The functions to generate the object's name are of the form glGen*​, where * is the object's type in plural form. All functions of this type have the same signature:

 void glGen*(GLsizei n​, GLuint *objects​);

This function generates n​ objects of the given type, storing them in the array given by the objects​ parameter. This allows you to create multiple objects with one call.

An object name is always a GLuint. These names are not pointers, nor should you assume that they are. They are references, numbers that identify an object. They can be any 32-bit unsigned integer except 0. The object number 0 is reserved for special use cases; see below for details.

Legacy Note: In OpenGL versions before 3.0, the user was allowed to ignore the generation step entirely. The user could just decide that "3" is a valid object name, and start using it like an object. The implementation would then have to accept that and create the object behind the scenes when you first start using it. In GL 3.0, this behavior was deprecated. In core GL 3.1 and above, this is no longer allowed. Regardless of the version of OpenGL, it is always good practice to use glGen*​ rather than making up your own object names.

Once you are finished with an object, you should delete it. The functions for this are of the form glDelete*​, using the same object type as before. These functions have this signature:

void glDelete*(GLsizei n​, const GLuint *objects​);

This works like the glGen*​ functions, only it deletes the objects instead of creating them.

When OpenGL objects are deleted, their names are no longer considered valid. Following this call, a subsequent glGen*​ call may or may not reuse a previously-deleted name; you should not make assumptions either way.

Deletion unbinding

When an object is deleted, if is bound to the current context (and note this only applies to the current context), then the object will be unbound from all binding to the context.

Note: This says "binding", not "attachment". Binding goes to the context; attachment is what you do when one object references another. Attachments are not severed due to this call.

Some objects can be associated with the context in unusual ways. These ways include, but are not limited to:

In such cases, these binds are not undone when the object is deleted. The only bindings that are undone are bindings that can be undone by calling the basic glBind*​ function for the object type.

So if you call glBindBufferRange(GL_UNIFORM_BUFFER, ...) and then delete that buffer, it will be as if glBindBuffer(GL_UNIFORM_BUFFER, 0) was called. This does not unbind it from the indexed target.

Deletion orphaning

Calling glDelete*​ on an object does not guarantee its immediate deletion. Because OpenGL is allowed to execute rendering commands well after you issue them (for maximum parallelism and performance), it is entirely possible for an object to remain with the OpenGL server for some time before it actually deletes it.

If an object is still "in use" after it is deleted, then the object will remain alive within the OpenGL implementation. An object is "in use" if:

  • It is bound to a context. This is not necessarily the current one, since deleting it will automatically unbind it from the current context. Though remember the caveat above about non-standard binding points.
  • It is attached to a container object.

So if a Texture is attached to a Framebuffer Object, the FBO will still be functional after deleting the texture. Only when the FBO is either deleted or a new texture attachment replaces the old will the texture finally be fully deleted.

Note that the name is still detectable via the OpenGL API. You can call glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) to fetch the object's name. However, the name is still considered unused, so don't use it for anything.

Note: Some implementations don't implement that last part correctly. So really don't use this.

Object Usage

Because objects in OpenGL are defined as a collections of state, to modify objects, you must first bind them to the OpenGL context. Binding objects to the context causes the state in them to be set to be the current context's state. This means that any functions that change the state governed by that object will simply change the state within the object, thus preserving that state.

Binding a newly generated object name will create new state for that object. In some cases, the target to which it is first bound (see below) will affect properties of the newly created state for the object.

Different objects have different binding functions. They do share a naming convention and general parameters:

void glBind*(location​, GLuint object​);

The * is the type of object, and object​ is the object to be bound.

The location​ is where different object types differ. Some objects can be bound to multiple locations in the context, while others can only be bound to a single specific place. For example, a buffer object can be bound as an array buffer, index buffer, pixel buffer, transform buffer, or various other possibilities. If an object can be bound to multiple locations, then there will be some kind of parameter to define where the binding happens. glBindBuffer takes an enumeration, for example.

Different locations have separate bindings. So you can bind a buffer object as an array, and a different buffer object as an index buffer without having any crosstalk between them.

If an object is bound to a location where another object is also bound, the previously bound object will be unbound.

Object zero

The GLuint value 0 is treated specially by OpenGL objects. However, some objects treat it in different ways. 0 will never be returned by a glGen*​ function.

For most object types, object 0 is much like the NULL pointer: it is not an object. If 0 is bound for such object types, then attempts to use that object for rendering purposes will fail.

For some objects, object 0 represents a kind of "default object". Textures have this concept, though it is very complex, and object 0 cannot be deleted. Such default texture objects cannot be used in many of the ways that real texture objects can, so you are strongly encouraged to think of texture 0 as a non-existent texture, as above.

For Framebuffer Objects, object 0 represents the Default Framebuffer. While it has most of the same interfaces as user-created FBOs, it uses a very different set of images.

Recommendation: With the exception of Framebuffer Objects, you should completely ignore object 0. Even if an object type has a valid object 0, you should treat it as if it did not. Treat it as you would the NULL pointer in C/C++; you can store it in a pointer, but you can't use that pointer until you put a real pointer there.

Object Sharing

You can create multiple OpenGL contexts. This is useful, as the current GL context is thread-specific. Normally, each context is entirely separate from the others; nothing done in one can affect the others.

At context creation time however, you are able to create a context that shares objects with another context. This means you can use objects created in one context in another context.

Not all object types can be shared across contexts. Objects that contain references to other objects cannot be shared. All other object types can be shared. This includes GLSL Objects and Sync Objects, which do not follow the OpenGL Object model.

Object types

Objects can be separated into two different categories: regular objects and container objects. Here is the list of regular objects.

Container objects

Non-standard objects

The following are "objects", but they do not follow the standard conventions laid out on this page for OpenGL objects: