blob: e3dd07e6eb27a9e5f4a6ec0fbb90542b1233d564 [file] [log] [blame]
Name
EXT_framebuffer_object
Name Strings
GL_EXT_framebuffer_object
Contributors
Kurt Akeley
Jason Allen
Bob Beretta
Pat Brown
Matt Craighead
Alex Eddy
Cass Everitt
Mark Galvan
Michael Gold
Evan Hart
Jeff Juliano
Mark Kilgard
Dale Kirkland
Jon Leech
Bill Licea-Kane
Barthold Lichtenbelt
Kent Lin
Rob Mace
Teri Morrison
Chris Niederauer
Brian Paul
Paul Puey
Ian Romanick
John Rosasco
R. Jason Sams
Jeremy Sandmel
Mark Segal
Avinash Seetharamaiah
Folker Schamel
Daniel Vogel
Eric Werness
Cliff Woolley
Contacts
Jeff Juliano, NVIDIA Corporation (jjuliano 'at' nvidia.com)
Jeremy Sandmel, Apple Computer (jsandmel 'at' apple.com)
Status
Complete.
Approved by the ARB "superbuffers" Working Group on January 31, 2005.
Despite being controlled by the ARB WG, this is not an officially
approved ARB extension at this time, thus the "EXT" tag.
Version
Last Modified Date: October 6, 2016
Revision: #123
Number
310
Dependencies
OpenGL 1.1 is required.
WGL_ARB_make_current_read affects the definition of this extension.
GLX 1.3 / GLX_SGI_make_current_read affects the definition of this
extension.
ATI_draw_buffers affects the definition of this extension.
ARB_draw_buffers affects the definition of this extension.
ARB_fragment_program affects the definition of this extension.
ARB_fragment_shader affects the definition of this extension.
ARB_framebuffer_object and OpenGL 3.0 core affect the definition of
this extension.
ARB_texture_rectangle affects the definition of this extension.
ARB_vertex_shader affects the definition of this extension.
EXT_packed_depth_stencil affects the definition of this extension.
NV_float_buffer affects the definition of this extension.
NV_texture_shader affects the definition of this extension.
Written based on the wording of the OpenGL 1.5 specification.
Overview
This extension defines a simple interface for drawing to rendering
destinations other than the buffers provided to the GL by the
window-system.
In this extension, these newly defined rendering destinations are
known collectively as "framebuffer-attachable images". This
extension provides a mechanism for attaching framebuffer-attachable
images to the GL framebuffer as one of the standard GL logical
buffers: color, depth, and stencil. (Attaching a
framebuffer-attachable image to the accum logical buffer is left for
a future extension to define). When a framebuffer-attachable image
is attached to the framebuffer, it is used as the source and
destination of fragment operations as described in Chapter 4.
By allowing the use of a framebuffer-attachable image as a rendering
destination, this extension enables a form of "offscreen" rendering.
Furthermore, "render to texture" is supported by allowing the images
of a texture to be used as framebuffer-attachable images. A
particular image of a texture object is selected for use as a
framebuffer-attachable image by specifying the mipmap level, cube
map face (for a cube map texture), and z-offset (for a 3D texture)
that identifies the image. The "render to texture" semantics of
this extension are similar to performing traditional rendering to
the framebuffer, followed immediately by a call to CopyTexSubImage.
However, by using this extension instead, an application can achieve
the same effect, but with the advantage that the GL can usually
eliminate the data copy that would have been incurred by calling
CopyTexSubImage.
This extension also defines a new GL object type, called a
"renderbuffer", which encapsulates a single 2D pixel image. The
image of renderbuffer can be used as a framebuffer-attachable image
for generalized offscreen rendering and it also provides a means to
support rendering to GL logical buffer types which have no
corresponding texture format (stencil, accum, etc). A renderbuffer
is similar to a texture in that both renderbuffers and textures can
be independently allocated and shared among multiple contexts. The
framework defined by this extension is general enough that support
for attaching images from GL objects other than textures and
renderbuffers could be added by layered extensions.
To facilitate efficient switching between collections of
framebuffer-attachable images, this extension introduces another new
GL object, called a framebuffer object. A framebuffer object
contains the state that defines the traditional GL framebuffer,
including its set of images. Prior to this extension, it was the
window-system which defined and managed this collection of images,
traditionally by grouping them into a "drawable". The window-system
API's would also provide a function (i.e., wglMakeCurrent,
glXMakeCurrent, aglSetDrawable, etc.) to bind a drawable with a GL
context (as is done in the WGL_ARB_pbuffer extension). In this
extension however, this functionality is subsumed by the GL and the
GL provides the function BindFramebufferEXT to bind a framebuffer
object to the current context. Later, the context can bind back to
the window-system-provided framebuffer in order to display rendered
content.
Previous extensions that enabled rendering to a texture have been
much more complicated. One example is the combination of
ARB_pbuffer and ARB_render_texture, both of which are window-system
extensions. This combination requires calling MakeCurrent, an
operation that may be expensive, to switch between the window and
the pbuffer drawables. An application must create one pbuffer per
renderable texture in order to portably use ARB_render_texture. An
application must maintain at least one GL context per texture
format, because each context can only operate on a single
pixelformat or FBConfig. All of these characteristics make
ARB_render_texture both inefficient and cumbersome to use.
EXT_framebuffer_object, on the other hand, is both simpler to use
and more efficient than ARB_render_texture. The
EXT_framebuffer_object API is contained wholly within the GL API and
has no (non-portable) window-system components. Under
EXT_framebuffer_object, it is not necessary to create a second GL
context when rendering to a texture image whose format differs from
that of the window. Finally, unlike the pbuffers of
ARB_render_texture, a single framebuffer object can facilitate
rendering to an unlimited number of texture objects.
Glossary of Helpful Terms
logical buffer:
One of the color, depth, or stencil buffers of the
framebuffer.
framebuffer:
The collection of logical buffers and associated state
defining where the output of GL rendering is directed.
texture:
an object which consists of one or more 2D arrays of pixel
images and associated state that can be used as a source of
data during the texture-mapping process described in section
3.8.
texture image:
one of the 2D arrays of pixels that are part of a texture
object as defined in section 3.8. Texture images contain
and define the texels of the texture object.
renderbuffer:
A new type of storage object which contains a single 2D
array of pixels and associated state that can be used as a
destination for pixel data written during the rendering
process described in Chapter 4.
renderbuffer image:
The 2D array of pixels that is part of a renderbuffer
object. A renderbuffer image contains and defines the
pixels of the renderbuffer object.
framebuffer-attachable image:
A 2D pixel image that can be attached to one of the logical
buffer attachment points of a framebuffer object. Texture
images and renderbuffer images are two examples of
framebuffer-attachable images.
attachment point:
The set of state which references a specific
framebuffer-attachable image, and allows that
framebuffer-attachable image to be used to store the
contents of a logical buffer of a framebuffer object. There
is an attachment point state vector for each color, depth,
and stencil buffer of a framebuffer.
attach:
The act of connecting one object to another object.
An "attach" operation is similar to a "bind" operation in
that both represent a reference to the attached or bound
object for the purpose of managing object lifetimes and both
enable manipulation of the state of the attached or bound
object.
However, an "attach" is also different from a "bind" in that
"binding" an unused object creates a new object, while
"attaching" does not. Additionally, "bind" establishes a
connection between a context and an object, while "attach"
establishes a connection between two objects.
Finally, if object "A" is attached to object "B" and object
"B" is bound to context "C", then in most respects, we treat
"A" as if it is <implicitly> bound to "C".
framebuffer attachment completeness:
Similar to texture "mipmap" or "cube" completeness from
section 3.8.10, defines a minimum set of criteria for
framebuffer attachment points. (for complete definition,
see section 4.4.4.1)
framebuffer completeness:
Similar to texture "mipmap cube completeness", defines a
composite set of "completeness" requirements and
relationships among the attached framebuffer-attachable
images. (for complete definition, see section 4.4.4.2)
Issues
Breaking from past convention, the very large issues section has
been moved to the end of the document. It can be found after
Examples, before Revision History.
New Procedures and Functions
boolean IsRenderbufferEXT(uint renderbuffer);
void BindRenderbufferEXT(enum target, uint renderbuffer);
void DeleteRenderbuffersEXT(sizei n, const uint *renderbuffers);
void GenRenderbuffersEXT(sizei n, uint *renderbuffers);
void RenderbufferStorageEXT(enum target, enum internalformat,
sizei width, sizei height);
void GetRenderbufferParameterivEXT(enum target, enum pname, int *params);
boolean IsFramebufferEXT(uint framebuffer);
void BindFramebufferEXT(enum target, uint framebuffer);
void DeleteFramebuffersEXT(sizei n, const uint *framebuffers);
void GenFramebuffersEXT(sizei n, uint *framebuffers);
enum CheckFramebufferStatusEXT(enum target);
void FramebufferTexture1DEXT(enum target, enum attachment,
enum textarget, uint texture,
int level);
void FramebufferTexture2DEXT(enum target, enum attachment,
enum textarget, uint texture,
int level);
void FramebufferTexture3DEXT(enum target, enum attachment,
enum textarget, uint texture,
int level, int zoffset);
void FramebufferRenderbufferEXT(enum target, enum attachment,
enum renderbuffertarget, uint renderbuffer);
void GetFramebufferAttachmentParameterivEXT(enum target, enum attachment,
enum pname, int *params);
void GenerateMipmapEXT(enum target);
New Types
None.
New Tokens
Accepted by the <target> parameter of BindFramebufferEXT,
CheckFramebufferStatusEXT, FramebufferTexture{1D|2D|3D}EXT,
FramebufferRenderbufferEXT, and
GetFramebufferAttachmentParameterivEXT:
FRAMEBUFFER_EXT 0x8D40
Accepted by the <target> parameter of BindRenderbufferEXT,
RenderbufferStorageEXT, and GetRenderbufferParameterivEXT, and
returned by GetFramebufferAttachmentParameterivEXT:
RENDERBUFFER_EXT 0x8D41
Accepted by the <internalformat> parameter of
RenderbufferStorageEXT:
STENCIL_INDEX1_EXT 0x8D46
STENCIL_INDEX4_EXT 0x8D47
STENCIL_INDEX8_EXT 0x8D48
STENCIL_INDEX16_EXT 0x8D49
Accepted by the <pname> parameter of GetRenderbufferParameterivEXT:
RENDERBUFFER_WIDTH_EXT 0x8D42
RENDERBUFFER_HEIGHT_EXT 0x8D43
RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
RENDERBUFFER_RED_SIZE_EXT 0x8D50
RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
Accepted by the <pname> parameter of
GetFramebufferAttachmentParameterivEXT:
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
Accepted by the <attachment> parameter of
FramebufferTexture{1D|2D|3D}EXT, FramebufferRenderbufferEXT, and
GetFramebufferAttachmentParameterivEXT
COLOR_ATTACHMENT0_EXT 0x8CE0
COLOR_ATTACHMENT1_EXT 0x8CE1
COLOR_ATTACHMENT2_EXT 0x8CE2
COLOR_ATTACHMENT3_EXT 0x8CE3
COLOR_ATTACHMENT4_EXT 0x8CE4
COLOR_ATTACHMENT5_EXT 0x8CE5
COLOR_ATTACHMENT6_EXT 0x8CE6
COLOR_ATTACHMENT7_EXT 0x8CE7
COLOR_ATTACHMENT8_EXT 0x8CE8
COLOR_ATTACHMENT9_EXT 0x8CE9
COLOR_ATTACHMENT10_EXT 0x8CEA
COLOR_ATTACHMENT11_EXT 0x8CEB
COLOR_ATTACHMENT12_EXT 0x8CEC
COLOR_ATTACHMENT13_EXT 0x8CED
COLOR_ATTACHMENT14_EXT 0x8CEE
COLOR_ATTACHMENT15_EXT 0x8CEF
DEPTH_ATTACHMENT_EXT 0x8D00
STENCIL_ATTACHMENT_EXT 0x8D20
Returned by CheckFramebufferStatusEXT():
FRAMEBUFFER_COMPLETE_EXT 0x8CD5
FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
Accepted by GetIntegerv():
FRAMEBUFFER_BINDING_EXT 0x8CA6
RENDERBUFFER_BINDING_EXT 0x8CA7
MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
MAX_RENDERBUFFER_SIZE_EXT 0x84E8
Returned by GetError():
INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
Additions to Chapter 2 of the 1.5 Specification (OpenGL Operation)
"The GL interacts with two classes of framebuffers:
window-system-provided framebuffers and application-created
framebuffers. There is always one window-system-provided
framebuffer, while application-created framebuffers can be created
as desired. These two types of framebuffer are distinguished
primarily by the interface for configuring and managing their state.
The effects of GL commands on the window-system-provided framebuffer
are ultimately controlled by the window-system that allocates
framebuffer resources. It is the window-system that determines
which portions of this framebuffer the GL may access at any given
time and that communicates to the GL how those portions are
structured. Therefore, there are no GL commands to configure the
window-system-provided framebuffer. Similarly, display of
framebuffer contents on a CRT monitor (including the transformation
of individual framebuffer values by such techniques as gamma
correction) is not addressed by the GL. Framebuffer configuration
occurs outside of the GL in conjunction with the window-system.
The initialization of a GL context itself occurs when the
window-system allocates a window for GL rendering and is influenced
by the state of the window-system-provided framebuffer."
Additions to Chapter 3 of the OpenGL 1.5 Specification (Rasterization)
In section 3.6.4, page 102, add the following text to the definiton
of DrawPixels:
"If the object bound to FRAMEBUFFER_BINDING_EXT is not "framebuffer
complete" (as defined in section 4.4.4.2), then an attempt to call
DrawPixels will generate the error
INVALID_FRAMEBUFFER_OPERATION_EXT."
In section 3.8.8, add the following text immediately before the
subsection "Mipmapping" on page 151:
"If all of the following conditions are satisfied, then the value of
the selected Tau(ijk), Tau(ij), or Tau(i) in the above equations is
undefined instead of referring to the value of the texel at location
(i), (i,j), or (i,j,k). See Chapter 4 for discussion of framebuffer
objects and their attachments.
* The current FRAMEBUFFER_BINDING_EXT names an application-created
framebuffer object <F>.
* The texture is attached to one of the attachment points, <A>, of
framebuffer object <F>.
* TEXTURE_MIN_FILTER is NEAREST or LINEAR, and the value of
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT for attachment point
<A> is equal to the value of TEXTURE_BASE_LEVEL
-or-
TEXTURE_MIN_FILTER is NEAREST_MIPMAP_NEAREST,
NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_NEAREST, or
LINEAR_MIPMAP_LINEAR, and the value of
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT for attachment point
<A> is within the the inclusive range from TEXTURE_BASE_LEVEL to
q."
In subsection "Automatic Mipmap Generation" to section 3.8.8,
replace the first paragraph with the following text:
"If the value of texture parameter GENERATE MIPMAP is TRUE and a
change is made to the interior or border texels of the level[base]
array of a mipmap by one of the texture image specification
operations defined in sections 3.8.1 through 3.8.3, then a complete
set of mipmap arrays (as defined in section 3.8.10) will be
computed. Array levels level[base] + 1 through p are replaced with
arrays derived from the modified level[base], regardless of their
previous contents. All other mipmap arrays, including the
level[base] array, are left unchanged by this computation."
Add a new subsection "Manual Mipmap Generation" to section 3.8.8,
after "Automatic Mipmap Generation":
"Manual Mipmap Generation
Mipmaps can be generated manually with the command
void GenerateMipmapEXT(enum target);
where <target> is one of TEXTURE_1D, TEXTURE_2D, TEXTURE_CUBE_MAP,
or TEXTURE_3D. Mipmap generation affects the texture image attached
to <target>. For cube map textures, INVALID_OPERATION is generated
if the texture bound to <target> is not cube complete, as defined in
section 3.8.10.
Mipmap generation replaces texture array levels level[base] + 1
through q with arrays derived from the level[base] array, as
described above under Automatic Mipmap Generation. All other mipmap
arrays, including the level[base] array, are left unchanged by this
computation. For arrays in the range level[base] through q,
inclusive, automatic and manual mipmap generation generate the same
derived arrays, given identical level[base] arrays."
Modify the third paragraph of section 3.8.12, page 157, to read:
"Texture objects are deleted by calling
void DeleteTextures( sizei n, uint *textures );
textures contains n names of texture objects to be deleted. After a
texture object is deleted, it has no contents or dimensionality, and
its name is again unused. If a texture that is currently bound to
one of the targets TEXTURE 1D, TEXTURE 2D, TEXTURE 3D, or TEXTURE
CUBE MAP is deleted, it is as though BindTexture had been executed
with the same target and texture zero. Additionally, special care
must be taken when deleting a texture if any of the images of the
texture are attached to a framebuffer object. See section 4.4.2.3
for details.
Unused names in textures are silently ignored, as is the value
zero."
Additions to Chapter 4 of the OpenGL 1.5 Specification (Per-Fragment
Operations and the Framebuffer)
On page 170, in the introduction to chapter 4, modify the first
three paragraphs to read as follows:
"The framebuffer consists of a set of pixels arranged as a
two-dimensional array. The height and width of this array may vary
from one GL implementation to another. For purposes of this
discussion, each pixel in the framebuffer is simply a set of some
number of bits. The number of bits per pixel may also vary
depending on the particular GL implementation or context.
Further there are two classes of framebuffers: the default
framebuffer supplied by the window-system-provided and
application-created framebuffer objects. Every GL context has a
single default window-system-provided framebuffer. Applications can
optionally create additional non-displayable framebuffer objects.
(For more information on application-created framebuffer objects see
section 4.4)
Corresponding bits from each pixel in the framebuffer are grouped
together into a bitplane; each bitplane contains a single bit from
each pixel. These bitplanes are grouped into several logical
buffers. These are the color, depth, stencil, and accumulation
buffers. The color buffer actually consists of a number of buffers,
and these color buffers serve related but slightly different
purposes depending on whether the GL is bound to the default
window-system-provided framebuffer or to an application-created
framebuffer object.
For the default window-system-provided framebuffer, the color
buffers are: the front left buffer, the front right buffer, the back
left buffer, the back right buffer, and some number of auxiliary
buffers. Typically, the contents of the front buffers are displayed
on a color monitor while the contents of the back buffers are
invisible. (Monoscopic contexts display only the front left buffer;
stereoscopic contexts display both the front left and the front
right buffers.) The contents of the auxiliary buffers are never
visible. All color buffers must have the same number of bitplanes,
although an implementation or context may choose not to provide
right buffers, back buffers, or auxiliary buffers at all. Further,
an implementation or context may not provide depth, stencil, or
accumulation buffers.
For application-created framebuffer objects, the color buffers are
not visible, and consequently the names of the color buffers are not
related to a display device. The names of the color buffers of an
application-created framebuffer object are: COLOR_ATTACHMENT0_EXT
through COLOR_ATTACHMENTn_EXT. The names of the depth and stencil
buffers are DEPTH_ATTACHMENT_EXT and STENCIL_ATTACHMENT_EXT. For
more information about the buffers of an application-created
framebuffer object, see section 4.4.2. To be considered framebuffer
complete (see section 4.4.4), all color buffers attached to an
application-created framebuffer object must have the same number of
bitplanes. Depth and stencil buffers may optionally be attached to
application-created framebuffers as well.
Color buffers consist of either unsigned integer color indices or R,
G, B, and, optionally, A unsigned integer values. The number of
bitplanes in each of the color buffers, the depth buffer, the
stencil buffer, and the accumulation buffer is dependent on the
currently bound framebuffer. For the default framebuffer, the
number of bitplanes is fixed. For application-created framebuffer
objects, however, the number of bitplanes in a given logical buffer
may change if the state of the corresponding framebuffer attachment
or attached image changes (see sections 4.4.2 and 4.4.5). If an
accumulation buffer is provided, it must have at least as many
bitplanes per R, G, and B color component as do the color buffers."
Add a new paragraph to the end of section 4.1.1, page 171:
"While an application-created framebuffer object is bound to
FRAMEBUFFER_EXT, the pixel ownership test always passes. The pixels
of application-created frambuffer objects are always owned by the
GL, not the window system. Only while the window-system-provided
framebuffer named zero is bound to FRAMEBUFFER_EXT does the window
system control pixel ownership."
Change section 4.1.5, page 174, third paragraph, first two sentences
to read as follows:
"<ref> is an integer reference value that is used in the unsigned
stencil comparison. Stencil comparison operations and queries of
<ref> use the value of <ref> clamped to the range [0, (2^s) - 1],
where s is the current number of bits in the stencil buffer."
Replace the first three sentences of 4.1.10 "Logical Operation":
"Finally, a logical operation is applied between the incoming
fragment's color or index values and the color or index values
stored at the corresponding location in the framebuffer. The result
replaces the values in the framebuffer at the fragment's (x[w],
y[w]) coordinates. However, if the DRAW_BUFFERS state selects a
single framebuffer-attachable image more than once, then an
undefined value is written to those color buffers at the fragment's
(x[w], y[x]) coordinates."
Change section 4.2.1, to read as follows:
"The first such operation is controlling the buffer into which color
values are written. This is accomplished with
void DrawBuffer( enum buf );
<buf> defines a buffer or set of buffers for writing. <buf> must be
one of the values from tables 4.4 or 10.nnn. Otherwise,
INVALID_ENUM is generated. In addition, acceptable values for <buf>
depend on whether the GL is using the default window-system-provided
framebuffer (i.e., FRAMEBUFFER_BINDING_EXT is zero), or an
application-created framebuffer object (i.e.,
FRAMEBUFFER_BINDING_EXT is non-zero). In the initial state, the GL
is bound to the the window-system-provided framebuffer. For more
information about application-created framebuffer objects, see
section 4.4.
If the GL is bound to the window-system-provided framebuffer, then
<buf> must be one the values listed in table 4.4, which summarizes
the constants and the buffers they indicate. In this case, <buf> is
a symbolic constant specifying zero, one, two, or four buffers for
writing. These constants refer to the four potentially visible
buffers front left, front right, back left, and back right, and to
the auxiliary buffers. Arguments other than AUXi that omit
reference to LEFT or RIGHT refer to both left and right buffers.
Arguments other than AUXi that omit reference to FRONT or BACK refer
to both front and back buffers. AUXi enables drawing only to
auxiliary buffer i. Each AUXi adheres to AUXi = AUX0 + i.
If the GL is bound to an application-created framebuffer object,
<buf> must be one of the values listed in table 10.nnn, which
summarizes the constants and the buffers they indicate. In this
case, <buf> is a symbolic constant specifying a single color buffer
for writing. Specifying COLOR_ATTACHMENTi_EXT enables drawing only
to the image attached to the framebuffer at COLOR_ATTACHMENTi_EXT.
Each COLOR_ATTACHMENTi_EXT adheres to COLOR_ATTACHMENTi_EXT =
COLOR_ATTACHMENT0_EXT + i. The intial value of DRAW_BUFFER for
application-created framebuffer objects is COLOR_ATTACHMENT0_EXT.
Symbolic Constant Meaning
----------------- -------
NONE no buffer
COLOR_ATTACHMENT0 output fragment color to image attached
at color attachment point 0
COLOR_ATTACHMENT1 output fragment color to image attached
at color attachment point 1
... ...
COLOR_ATTACHMENTn output fragment color to image attached
at color attachment point n, where
n is MAX_COLOR_ATTACHMENTS - 1
-------------------------------------------------------------------
Table 10.nnn: Arguments to DrawBuffer(s) and ReadBuffer when the
context is bound to an application-created framebuffer object, and
the buffers they indicate
If the GL is bound to the window-system-provided framebuffer and
DrawBuffer is supplied with a constant (other than NONE) that does
not indicate any of the color buffers allocated to the GL context by
the window-system (including those listed in table 10.nnn), then the
error INVALID_OPERATION results.
If the GL is bound to the application-created framebuffer and
DrawBuffer is supplied with a constant from table 4.4, or
COLOR_ATTACHMENTm where m is greater than or equal to
MAX_COLOR_ATTACHMENTS, then the error INVALID_OPERATION results.
If DrawBuffer is supplied with a constant that is neither legal for
the window-system provided framebuffer nor legal for an
application-created framebuffer object, then the error INVALID_ENUM
results.
The command
void DrawBuffers( sizei n, const enum *bufs );
defines the draw buffers to which all fragment colors are written.
<n> specifies the number of buffers in <bufs>. <bufs> is a pointer
to an array of symbolic constants specifying the buffer to which
each fragment color is written.
Each enumerant listed in <bufs> must be one of the values from
tables 10.nnn or 11.nnn. Otherwise, INVALID_ENUM is generated.
Further, acceptable values for the constants in <bufs> depend on
whether the GL is using the default window-system-provided
framebuffer (i.e., FRAMEBUFFER_BINDING_EXT is zero), or an
application-created framebuffer object (i.e.,
FRAMEBUFFER_BINDING_EXT is non-zero). For more information about
application-created framebuffer objects, see section 4.4.
symbolic front front back back aux
constant left right left right i
-------- ----- ----- ---- ----- ---
NONE
FRONT LEFT X
FRONT RIGHT X
BACK LEFT X
BACK RIGHT X
AUXi X
--------------------------------------------------
Table 11.nnn: Arguments to DrawBuffers, when the context is bound
to the window-system-provided framebuffer, and the buffers that
they indicate.
If the GL is bound to the default window-system-provided
framebuffer, then the each of the constants must be one of the
values listed in table 11.nnn
If the GL is bound to an application-created framebuffer object,
then each of the constants must be one of the values listed in table
10.nnn.
In both cases, the draw buffers being defined correspond in order to
the respective fragment colors. The draw buffer for fragment colors
beyond <n> is set to NONE.
The maximum number of draw buffers is implementation dependent and
must be at least 1. The number of draw buffers supported can be
queried by calling GetIntegerv with the symbolic constant
MAX_DRAW_BUFFERS. INVALID_VALUE is generated if <n> is greater
than MAX_DRAW_BUFFERS.
Except for NONE, a buffer may not appear more then once in the array
pointed to by <bufs>. Specifying a buffer more then once will
result in the error INVALID_OPERATION.
If fixed-function fragment shading is being performed, DrawBuffers
specifies a set of draw buffers into which the fragment color is
written.
If a fragment shader writes to "gl_FragColor", DrawBuffers specifies
a set of draw buffers into which the single fragment color defined
by "gl_FragColor" is written. If a fragment shader writes to gl
FragData, DrawBuffers specifies a set of draw buffers into which
each of the multiple fragment colors defined by "gl_FragData" are
separately written. If a fragment shader writes to neither gl
FragColor nor "gl_FragData", the values of the fragment colors
following shader execution are undefined, and may differ for each
fragment color.
For both window-system-provided and application-created
framebuffers, the constants FRONT, BACK, LEFT, RIGHT, and
FRONT_AND_BACK are not valid in the <bufs> array passed to
DrawBuffers, and will result in the error INVALID_OPERATION. This
restriction is because these constants may themselves refer to
multiple buffers, as shown in table 4.4.
If the GL is bound to the window-system-provided framebuffer and
DrawBuffers is supplied with a constant (other than NONE) that does
not indicate any of the color buffers allocated to the GL context by
the window-system, then the error INVALID_OPERATION results.
If the GL is bound to the application-created framebuffer and
DrawBuffers is supplied with a constant from table 11.nnn, or
COLOR_ATTACHMENTm where m is greater than or equal to
MAX_COLOR_ATTACHMENTS, then the error INVALID_OPERATION results.
If DrawBuffers is supplied with a constant that is neither legal for
the window-system provided framebuffer nor legal for an
application-created framebuffer object, then the error INVALID_ENUM
results.
Indicating a buffer or buffers using DrawBuffer or DrawBuffers
causes subsequent pixel color value writes to affect the indicated
buffers.
Specifying NONE as the draw buffer for a fragment color will inhibit
that fragment color from being written to any buffer.
Monoscopic contexts include only left buffers, while stereoscopic
contexts include both left and right buffers. Likewise, single
buffered contexts include only front buffers, while double buffered
contexts include both front and back buffers. The type of context
is selected at GL initialization.
The state required to handle color buffer selection is an integer
for each supported fragment color. For the default
window-system-provided framebuffer, in the initial state, the draw
buffer for fragment color zero is FRONT if there are no back
buffers; otherwise it is BACK. For application-created framebuffer
objects, the initial value of draw buffer for fragment color zero is
COLOR_ATTACHMENT0_EXT. For both the window-system-provided
framebuffer and application-created framebuffers, the initial state
of draw buffers for fragment colors other then zero is NONE."
Modify section 4.2.2, page 185, third paragraph to read as follows:
"The command
void StencilMask( uint mask );
controls the writing of particular bits into the stencil planes. The
least significant s bits of mask comprise an integer mask (s is the
number of bits in the stencil buffer), just as for IndexMask. The
initial state is for the stencil plane mask to be 32 ones."
In section 4.3.2, page 190, modify the first two paragraphs of the
definition of ReadBuffer to read as follows:
"The command
void ReadBuffer( enum src );
takes a symbolic constant as argument. <src> must be one of the
values from tables 4.4 or 10.nnn. Otherwise, INVALID_ENUM is
generated. Further, the acceptable values for <src> depend on
whether the GL is using the default window-system-provided
framebuffer (i.e., FRAMEBUFFER_BINDING_EXT is zero), or an
application-created framebuffer object (i.e.,
FRAMEBUFFER_BINDING_EXT is non-zero). For more information about
application-created framebuffer objects, see section 4.4.
If the object bound to FRAMEBUFFER_BINDING_EXT is not "framebuffer
complete" (as defined in section 4.4.4.2), then ReadPixels generates
the error INVALID_FRAMEBUFFER_OPERATION_EXT. If ReadBuffer is
supplied with a constant that is neither legal for the window-system
provided framebuffer, nor legal for an application-created
framebuffer object, then the error INVALID_ENUM results.
When FRAMEBUFFER_BINDING_EXT is zero, i.e. the default
window-system-provided framebuffer, <src> must be one of the values
listed in table 4.4. FRONT and LEFT refer to the front left buffer,
BACK refers to the back left buffer, and RIGHT refers to the front
right buffer. The other constants correspond directly to the
buffers that they name. If the requested buffer is missing, then the
error INVALID_OPERATION is generated. For the default
window-system-provided framebuffer, the initial setting for
ReadBuffer is FRONT if there is no back buffer and BACK otherwise.
When the GL is using an application-created framebuffer object,
<src> must be one of the values listed in table 10.nnn, including
NONE. In a manner analogous to how the DRAW_BUFFERs state is
handled, specifying COLOR_ATTACHMENTi_EXT enables reading from the
image attached to the framebuffer at COLOR_ATTACHMENTi_EXT.
ReadPixels generates INVALID_OPERATION if it attempts to select a
color buffer while READ_BUFFER is NONE. For application-created
framebuffer objects, the initial setting for ReadBuffer is
COLOR_ATTACHMENT0_EXT.
ReadPixels obtains values from the selected buffer from each pixel
with lower left hand corner at (x+i, y+j) for (0 <= i < width) and
(0 <= j < height); this pixel is said to be the ith pixel in the jth
row. If any of these pixels lies outside of the window allocated to
the current GL context, or outside of the image attached to the
currently bound framebuffer object, then the values obtained for
those pixels are undefined. When FRAMEBUFFER_BINDING_EXT is zero,
results are also undefined for individual pixels that are not owned
by the current context. Otherwise, ReadPixels obtains values from
the selected buffer, regardless of how those values were placed
there."
In section 4.3.2, "Reading Pixels", add a paragraph before
"Conversion of RGBA values" on page 191:
"When FRAMEBUFFER_BINDING is non-zero, the red, green, blue, and
alpha values are obtained by first reading the internal component
values of the corresponding value in the image attached to the
selected logical buffer. The internal component values are
converted to red, green, blue, and alpha values as specified in the
row of table 12.nnn corresponding to the internal format of the
image attached to READ_BUFFER."
Add the following text to section 4.3.3, page 194, inside the
definiton of CopyPixels:
"Furthermore, the behavior of several GL operations is specified "as
if the arguments were passed to CopyPixels." These operations
include: CopyTex{Sub}Image*, CopyColor{Sub}Table, and
CopyConvolutionFilter*. INVALID_FRAMEBUFFER_OPERATION_EXT will be
generated if an attempt is made to execute one of these operations,
or CopyPixels, while the object bound to FRAMEBUFFER_BINDING_EXT is
not "framebuffer complete" (as defined in section 4.4.4.2)."
Add a new section "Framebuffer Objects" after section 4.3:
"4.4 Framebuffer Objects
As described in chapters 1 and 2, GL renders into (and reads values
from) a framebuffer. GL defines two classes of framebuffers:
window-system-provided framebuffers and application-created
framebuffers. For each GL context, there is a single framebuffer
provided by the window-system, and there may also be one or more
framebuffer objects created and managed by the application.
By default, the GL uses the window-system-provided framebuffer. The
storage, dimensions, allocation, and format of the images attached
to this framebuffer are managed entirely by the window-system.
Consequently, the state of the window-system-provided framebuffer,
including its images, can not be changed by the GL, nor can the
window-system-provided framebuffer itself, or its images, be deleted
by the GL.
The routines described in the following sections, however, can be
used to create, destroy, and modify the state and attachments of
application-created framebuffer objects.
Application-created framebuffer objects encapsulate the state of a
framebuffer in a similar manner to the way texture objects
encapsulate the state of a texture. In particular, a framebuffer
object encapsulates state necessary to describe a collection of
color, depth, stencil, accum, and aux logical buffers. For each
logical buffer, a framebuffer-attachable image can be attached to
the framebuffer to store the rendered output for that logical
buffer. Examples of framebuffer-attachable images include texture
images and renderbuffer images. Renderbuffers are described further
in section 4.4.2.1
By allowing the images of a renderbuffer to be attached to a
framebuffer, the GL provides a mechanism to support "off-screen"
rendering. Further, by allowing the images of a texture to be
attached to a framebuffer, the GL provides a mechanism to support
"render to texture".
4.4.1 Binding and Managing Framebuffer Objects
The operations described in chapter 4 affect the images attached to
the framebuffer object bound to the target FRAMEBUFFER_EXT. By
default, framebuffer bound to the target FRAMEBUFFER_EXT is zero,
specifying the default implementation dependent framebuffer provided
by the windowing system. When the framebuffer bound to target
FRAMEBUFFER_EXT is not zero, but instead names an
application-created framebuffer object, then the operations
described in chapter 4 affect the application-created framebuffer
object rather than the default framebuffer.
The namespace for framebuffer objects is the unsigned integers, with
zero reserved by the GL to refer to the default framebuffer. A
framebuffer object is created by binding an unused name to the
target FRAMEBUFFER_EXT. The binding is effected by calling
void BindFramebufferEXT(enum target, uint framebuffer);
with <target> set to FRAMEBUFFER_EXT and <framebuffer> set to the
unused name. The resulting framebuffer object is a new state
vector, comprising all the state values listed in table 4.nnn, as
well as one set of the state values listed in table 5.nnn for each
attachment point of the framebuffer. There are
MAX_COLOR_ATTACHMENTS_EXT color attachment points, plus one each for
the depth and stencil attachment points.
BindFramebufferEXT may also be used to bind an existing framebuffer
object to <target>. If the bind is successful no change is made to
the state of the bound framebuffer object and any previous binding
to <target> is broken. The current FRAMEBUFFER_EXT binding can be
queried using GetIntegerv(FRAMEBUFFER_BINDING_EXT).
While a framebuffer object is bound to the target FRAMEBUFFER_EXT,
GL operations on the target to which it is bound affect the images
attached to the bound framebuffer object, and queries of the target
to which it is bound return state from the bound object. In
particular, queries of the values specified in table 6.31
(Implementation Dependent Pixel Depths) and table 8.nnn
(Framebuffer-Dependent State Variables) are derived from the
currently bound framebuffer object. The framebuffer object bound to
the target FRAMEBUFFER_EXT is used as the destination of fragment
operations and as the source of pixel reads such as ReadPixels, as
described in chapter 4.
In the initial state, the reserved name zero is bound to the target
FRAMEBUFFER_EXT. There is no application-created framebuffer object
corresponding to the name zero. Instead, the name zero refers to
the window-system-provided framebuffer. All queries and operations
on the framebuffer while the name zero is bound to the target
FRAMEBUFFER_EXT operate on this default framebuffer. On some
implementations, the properties of the default
window-system-provided framebuffer can change over time (e.g., in
response to window-system events such as attaching the context to a
new window-system drawable.)
Application-created framebuffer objects (i.e., those with a non-zero
name) differ from the default window-system-provided framebuffer in
a few important ways. First and foremost, unlike the
window-system-provided framebuffer, application-created-framebuffers
have modifiable attachment points for each logical buffer in the
framebuffer. Framebuffer-attachable images can be attached to and
detached from these attachment points, which are described further
in section 4.4.2. Also, the size and format of the images attached
to application-created framebuffers are controlled entirely within
the GL interface, and are not affected by window-system events, such
as pixel format selection, window resizes, and display mode changes.
Additionally, when rendering to or reading from an application
created-framebuffer object,
- The pixel ownership test always succeeds. In other words,
application-created framebuffer objects own all of their
pixels.
- There are no visible color buffer bitplanes. This means
there is no color buffer corresponding to the back, front,
left, or right color bitplanes.
- The only color buffer bitplanes are the ones defined by the
framebuffer attachment points named COLOR_ATTACHMENT0_EXT
through COLOR_ATTACHMENTn_EXT.
- The only depth buffer bitplanes are the ones defined by the
framebuffer attachment point DEPTH_ATTACHMENT_EXT.
- The only stencil buffer bitplanes are the ones defined by
the framebuffer attachment point STENCIL_ATTACHMENT_EXT.
- There is no multisample buffer so the value of the
implementation-dependent state variables SAMPLES and
SAMPLE_BUFFERS are both 0
- There are no accum buffer bitplanes, so the value of the
implementation-dependent state variables ACCUM_RED_BITS,
ACCUM_GREEN_BITS, ACCUM_BLUE_BITS, and ACCUM_ALPHA_BITS, are
all zero.
- There are no AUX buffer bitplanes, so the value of the
implementation-dependent state variable AUX_BUFFERS is zero.
Framebuffer objects are deleted by calling
void DeleteFramebuffersEXT(sizei n, uint *framebuffers);
<framebuffers> contains <n> names of framebuffer objects to be
deleted. After a framebuffer object is deleted, it has no
attachments, and its name is again unused. If a framebuffer that is
currently bound to the target FRAMEBUFFER_EXT is deleted, it is as
though BindFramebufferEXT had been executed with the <target> of
FRAMEBUFFER_EXT and <framebuffer> of zero. Unused names in
<framebuffers> are silently ignored, as is the value zero.
The command
void GenFramebuffersEXT(sizei n, uint *ids);
returns <n> previously unused framebuffer object names in <ids>.
These names are marked as used, for the purposes of
GenFramebuffersEXT only, but they acquire state and type only when
they are first bound, just as if they were unused.
4.4.2 Attaching Images to Framebuffer Objects
Framebuffer-attachable images may be attached to, and detached from,
application-created framebuffer objects. In contrast, the image
attachments of the window-system-provided framebuffer may not be
changed by the GL.
A single framebuffer-attachable image may be attached to multiple
application-created framebuffer objects, potentially avoiding some
data copies, and possibly decreasing memory consumption.
For each logical buffer, the framebuffer object stores a set of
state which defines the logical buffer's "attachment point". The
"attachment point" state contains enough information to identify the
single image attached to the attachment point, or to indicate that
no image is attached. The per-logical buffer "attachment point"
state is listed in table 5.nnn
There are two types of framebuffer-attachable images: the image of a
renderbuffer object, and an image of a texture object.
4.4.2.1 Renderbuffer Objects
A renderbuffer is a data storage object containing a single image of
a renderable internal format. GL provides the methods described
below to allocate and delete a renderbuffer's image, and to attach a
renderbuffer's image to a framebuffer object.
The name space for renderbuffer objects is the unsigned integers,
with zero reserved for the GL. A renderbuffer object is created by
binding an unused name to RENDERBUFFER_EXT. The binding is effected
by calling
void BindRenderbufferEXT( enum target, uint renderbuffer );
with <target> set to RENDERBUFFER_EXT and <renderbuffer> set to the
unused name. If <renderbuffer> is not zero, then the resulting
renderbuffer object is a new state vector, initialized with a
zero-sized memory buffer, and comprising the state values listed in
Table 8.nnn. Any previous binding to <target> is broken.
BindRenderbufferEXT may also be used to bind an existing
renderbuffer object. If the bind is successful, no change is made
to the state of the newly bound renderbuffer object, and any
previous binding to <target> is broken.
While a renderbuffer object is bound, GL operations on the target to
which it is bound affect the bound renderbuffer object, and queries
of the target to which a renderbuffer object is bound return state
from the bound object.
The name zero is reserved. A renderbuffer object cannot be created
with the name zero. If <renderbuffer> is zero, then any previous
binding to <target> is broken and the <target> binding is restored
to the initial state.
In the initial state, the reserved name zero is bound to
RENDERBUFFER_EXT. There is no renderbuffer object corresponding to
the name zero, so client attempts to modify or query renderbuffer
state for the target RENDERBUFFER_EXT while zero is bound will
generate GL errors, as described in section 6.1.3.
Using GetIntegerv, the current RENDERBUFFER_EXT binding can be
queried as RENDERBUFFER_BINDING_EXT.
Renderbuffer objects are deleted by calling
void DeleteRenderbuffersEXT( sizei n, const uint *renderbuffers );
where <renderbuffers> contains n names of renderbuffer objects to be
deleted. After a renderbuffer object is deleted, it has no
contents, and its name is again unused. If a renderbuffer that is
currently bound to RENDERBUFFER_EXT is deleted, it is as though
BindRenderbufferEXT had been executed with the <target>
RENDERBUFFER_EXT and <name> of zero. Additionally, special care
must be taken when deleting a renderbuffer if the image of the
renderbuffer is attached to a framebuffer object. (See section
4.4.2.2 for details). Unused names in <renderbuffers> are silently
ignored, as is the value zero.
The command
void GenRenderbuffersEXT( sizei n, uint *renderbuffers );
returns <n> previously unused renderbuffer object names in
<renderbuffers>. These names are marked as used, for the purposes
of GenRenderbuffersEXT only, but they acquire renderbuffer state
only when they are first bound, just as if they were unused.
The command
void RenderbufferStorageEXT(enum target, enum internalformat,
sizei width, sizei height);
establishes the data storage, format, and dimensions of a
renderbuffer object's image. <target> must be RENDERBUFFER_EXT.
<internalformat> must be color-renderable, depth-renderable, or
stencil-renderable (as defined in section 4.4.4). <width> and
<height> are the dimensions in pixels of the renderbuffer. If
either <width> or <height> is greater than
MAX_RENDERBUFFER_SIZE_EXT, the the error INVALID_VALUE is generated.
If the GL is unable to create a data store of the requested size,
the error OUT_OF_MEMORY is generated. RenderbufferStorageEXT deletes
any existing data store for the renderbuffer and the contents of the
data store after calling RenderbufferStorageEXT are undefined.
Sized Base S
Internal Format Internal format Bits
--------------- --------------- ----
STENCIL_INDEX1_EXT STENCIL_INDEX 1
STENCIL_INDEX4_EXT STENCIL_INDEX 4
STENCIL_INDEX8_EXT STENCIL_INDEX 8
STENCIL_INDEX16_EXT STENCIL_INDEX 16
------------------------------------------------------------------
Table 2.nnn Desired component resolution for each sized internal
format that can be used only with renderbuffers.
A GL implementation may vary its allocation of internal component
resolution based on any RenderbufferStorage parameter (except
target), but the allocation and chosen internal format must not be a
function of any other state and cannot be changed once they are
established. The actual resolution in bits of each component of the
allocated image can be queried with GetRenderbufferParameteriv as
described in section 6.1.3.
4.4.2.2 Attaching Renderbuffer Images to a Framebuffer
A renderbuffer can be attached as one of the logical buffers of the
currently bound framebuffer object by calling
void FramebufferRenderbufferEXT(enum target,
enum attachment,
enum renderbuffertarget,
uint renderbuffer);
<target> must be FRAMEBUFFER_EXT. INVALID_OPERATION is generated if
the current value of FRAMEBUFFER_BINDING_EXT is zero when
FramebufferRenderbufferEXT is called. <attachment> should be set to
one of the attachment points of the framebuffer listed in table
1.nnn. <renderbuffertarget> must be RENDERBUFFER_EXT and
<renderbuffer> should be set to the name of the renderbuffer object
to be attached to the framebuffer. <renderbuffer> must be either
zero or the name of an existing renderbuffer object of type
<renderbuffertarget>, otherwise INVALID_OPERATION is generated. If
<renderbuffer> is zero, then the value of <renderbuffertarget> is
ignored.
If <renderbuffer> is not zero and if FramebufferRenderbufferEXT is
successful, then the renderbuffer named <renderbuffer> will be used
as the logical buffer identified by <attachment> of the framebuffer
currently bound to <target>. The value of
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT for the specified attachment
point is set to RENDERBUFFER_EXT and the value of
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT is set to <renderbuffer>. All
other state values of the attachment point specified by <attachment>
are set to their default values listed in table 5.nnn. No change is
made to the state of the renderbuffer object and any previous
attachment to the <attachment> logical buffer of the framebuffer
object bound to framebuffer <target> is broken. If, on the other
hand, the attachment is not successful, then no change is made to
the state of either the renderbuffer object or the framebuffer
object.
Calling FramebufferRenderbufferEXT with the <renderbuffer> name zero
will detach the image, if any, identified by <attachment>, in the
framebuffer currently bound to <target>. All state values of the
attachment point specified by <attachment> in the object bound to
<target> are set to their default values listed in table 5.nnn.
If a renderbuffer object is deleted while its image is attached to
one or more attachment points in the currently bound framebuffer,
then it is as if FramebufferRenderbufferEXT() had been called, with
a <renderbuffer> of 0, for each attachment point to which this image
was attached in the currently bound framebuffer. In other words,
this renderbuffer image is first detached from all attachment points
in the currently bound framebuffer. Note that the renderbuffer
image is specifically *not* detached from any non-bound
framebuffers. Detaching the image from any non-bound framebuffers
is the responsibility of the application.
Name of attachment
--------------------------------------------------------------------------------------
COLOR_ATTACHMENT0_EXT ... COLOR_ATTACHMENTn_EXT (where n is from 0 to MAX_COLOR_ATTACHMENTS_EXT-1)
DEPTH_ATTACHMENT_EXT
STENCIL_ATTACHMENT_EXT
--------------------------------------------------------------------------------------
Table 1.nnn: "List of framebuffer attachment points"
4.4.2.3 Attaching Texture Images to a Framebuffer
GL supports copying the rendered contents of the framebuffer into
the images of a texture object through the use of the routines
CopyTexImage{1D|2D}, and CopyTexSubImage{1D|2D|3D}. Additionally,
GL supports rendering directly into the images of a texture object.
To render directly into a texture image, a specified image from a
texture object can be attached as one of the logical buffers of the
currently bound framebuffer object by calling one of the following
routines, depending on the type of the texture:
void FramebufferTexture1DEXT(enum target, enum attachment,
enum textarget, uint texture,
int level);
void FramebufferTexture2DEXT(enum target, enum attachment,
enum textarget, uint texture,
int level);
void FramebufferTexture3DEXT(enum target, enum attachment,
enum textarget, uint texture,
int level, int zoffset);
In all three routines, <target> must be FRAMEBUFFER_EXT.
INVALID_OPERATION is generated if the current value of
FRAMEBUFFER_BINDING_EXT is zero when FramebufferTexture{1D|2D|3D}EXT
is called. <attachment> must be one of the attachment points of the
framebuffer listed in table 1.nnn.
In all three routines, if <texture> is zero, then <textarget>,
<level>, and <zoffset> are ignored. If <texture> is not zero, then
<texture> must either name an existing texture object with an target
of <textarget>, or <texture> must name an existing cube map texture
and <textarget> must be one of: TEXTURE_CUBE_MAP_POSITIVE_X,
TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_POSITIVE_Z,
TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_Y, or
TEXTURE_CUBE_MAP_NEGATIVE_Z. Otherwise, GL_INVALID_OPERATION is
generated.
<level> specifies the mipmap level of the texture image to be
attached to the framebuffer.
If <textarget> is TEXTURE_RECTANGLE_ARB, then <level> must be zero.
If <textarget> is TEXTURE_3D, then <level> must be greater than or
equal to zero and less than or equal to log base 2 of
MAX_3D_TEXTURE_SIZE. If <textarget> is one of
TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y,
TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_X,
TEXTURE_CUBE_MAP_NEGATIVE_Y, or TEXTURE_CUBE_MAP_NEGATIVE_Z, then
<level> must be greater than or equal to zero and less than or equal
to log base 2 of MAX_CUBE_MAP_TEXTURE_SIZE. For all other values of
<textarget>, <level> must be greater than or equal to zero and no
larger than log base 2 of MAX_TEXTURE_SIZE. Otherwise,
INVALID_VALUE is generated.
<zoffset> specifies the z-offset of a 2-dimensional image within a
3-dimensional texture. INVALID_VALUE is generated if <zoffset> is
larger than MAX_3D_TEXTURE_SIZE-1.
For FramebufferTexture1DEXT, if <texture> is not zero, then
<textarget> must be TEXTURE_1D.
For FramebufferTexture2DEXT, if <texture> is not zero, then
<textarget> must be one of: TEXTURE_2D, TEXTURE_RECTANGLE_ARB,
TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y,
TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_X,
TEXTURE_CUBE_MAP_NEGATIVE_Y, or TEXTURE_CUBE_MAP_NEGATIVE_Z.
For FramebufferTexture3DEXT, if <texture> is not zero, then
<textarget> must be TEXTURE_3D.
If <texture> is not zero, and if FramebufferTexture{1D|2D|3D}EXT is
successful, then the specified texture image will be used as the
logical buffer identified by <attachment> of the framebuffer
currently bound to <target>. The value of
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT for the specified attachment
point is set to TEXTURE and the value of
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT is set to <texture>.
Additionally, the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL for
the named attachment point is set to <level>. If <texture> is a
cubemap texture then, the value of
FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE the named attachment
point is set to <textarget>. If <texture> is a 3D texture, then the
value of FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET for the named
attachment point is set to <zoffset>. All other state values of the
attachment point specified by <attachment> are set to their default
values listed in table 5.nnn. No change is made to the state of the
texture object, and any previous attachment to the <attachment>
logical buffer of the framebuffer object bound to framebuffer
<target> is broken. If, on the other hand, the attachment is not
successful, then no change is made to the state of either the
texture object or the framebuffer object.
Calling FramebufferTexture{1D|2D|3D}EXT with <texture> name zero
will detach the image identified by <attachment>, if any, in the
framebuffer currently bound to <target>. All state values of the
attachment point specified by <attachment> are set to their default
values listed in table 5.nnn.
If a texture object is deleted while its image is attached to one or
more attachment points in the currently bound framebuffer, then it
is as if FramebufferTexture{1D|2D|3D}EXT() had been called, with a
<texture> of 0, for each attachment point to which this image was
attached in the currently bound framebuffer. In other words, this
texture image is first detached from all attachment points in the
currently bound framebuffer. Note that the texture image is
specifically *not* detached from any other framebuffer objects.
Detaching the texture image from any other framebuffer objects is
the responsibility of the application.
4.4.3 Rendering When an Image of a Bound Texture Object is Also
Attached to the Framebuffer
Special precautions need to be taken to avoid attaching a texture
image to the currently bound framebuffer while the texture object is
currently bound and enabled for texturing. Doing so could lead to
the creation of a "feedback loop" between the writing of pixels by
the GL's rendering operations and the simultaneous reading of those
same pixels when used as texels in the currently bound texture. In
this scenario, the framebuffer will be considered framebuffer
complete (see section 4.4.4), but the values of fragments rendered
while in this state will be undefined. The values of texture
samples may be undefined as well, as described in section 3.8.8.
Specifically, the values of rendered fragments are undefined if all
of the following conditions are true:
- an image from texture object <T> is attached to the currently
bound framebuffer at attachment point <A>, and
- the texture object <T> is currently bound to a texture unit
<U>, and
- the current fixed-function texture state or programmable
vertex and/or fragment processing state makes it possible(*)
to sample from the texture object <T> bound to texture unit
<U>
while either of the following conditions are true:
- the value of TEXTURE MIN FILTER for texture object <T> is
NEAREST or LINEAR, and the value of
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT for attachment point
<A> is equal to the value of TEXTURE_BASE_LEVEL for the
texture object <T>, or
- the value of TEXTURE_MIN_FILTER for texture object <T> is one
of NEAREST_MIPMAP_NEAREST, NEAREST_MIPMAP LINEAR, LINEAR
MIPMAP_NEAREST, or LINEAR_MIPMAP_LINEAR, and the value of
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT for attachment point
<A> is within the the range specified by the current values of
TEXTURE_BASE_LEVEL to q, inclusive, for the texture object
<T>. (q is defined in the Mipmapping discussion of section
3.8.8),
(*) For the purpose of this discussion, we consider it "possible"
to sample from the texture object <T> bound to texture unit <U>"
if any of the following are true:
- programmable vertex and fragment processing is disabled
and the target of texture object <T> is enabled according
to the texture target precedence rules of section 3.8.15,
or
- if FRAGMENT_PROGRAM_ARB is enabled and the currently bound
fragment program contains any instructions that
sample from the texture object <T> bound to <U>,
or
- if the active fragment or vertex shader contains
any instructions that might sample from the texture object <T> bound
to <U> if even those instructions might only be executed
conditionally.
Note that if TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL exclude any
levels containing image(s) attached to the currently bound
framebuffer, then the above conditions will not be met, (i.e., the
above rule will not cause the values of rendered fragments to be
undefined.)
4.4.4 Framebuffer Completeness
A framebuffer object is said to be "framebuffer complete" if all of
its attached images, and all framebuffer parameters required to
utilize the framebuffer for rendering and reading, are consistently
defined and meet the requirements defined below. The rules of
framebuffer completeness are dependent on the properties of the
attached images, and on certain implementation dependent
restrictions. A framebuffer must be complete to effectively be used
as the destination for GL framebuffer rendering operations and the
source for GL framebuffer read operations.
The internal formats of the attached images can affect the
completeness of the framebuffer, so it is useful to first define the
relationship between the internal format of an image and the
attachment points to which it can be attached.
* The following base internal formats from table 3.15 are
"color-renderable": RGB, RGBA, FLOAT_R_NV, FLOAT_RG_NV,
FLOAT_RGB_NV, and FLOAT_RGBA_NV. The sized internal formats
from table 3.16 that have a color-renderable base internal
format are also color-renderable. No other formats, including
compressed internal formats, are color-renderable.
* An internal format is "depth-renderable" if it is
DEPTH_COMPONENT, or if it is one of the sized internal formats
from table 3.16 that has a depth-renderable base internal
format. No other formats are depth-renderable.
* An internal format is "stencil-renderable" if it is
STENCIL_INDEX, or if it is one of the sized internal formats
from table 2.nnn that has a stencil-renderable base internal
format. No other formats are stencil-renderable.
4.4.4.1 Framebuffer Attachment Completeness
If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT for the
framebuffer attachment point <attachment> is not NONE, then it is
said that a framebuffer-attachable image, named <image>, is attached
to the framebuffer at the attachment point. <image> is identified
by the state in <attachment> as described in section 4.4.2.
The framebuffer attachment point <attachment> is said to be
"framebuffer attachment complete" if the value of
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT for <attachment> is NONE
(i.e., no image is attached), or if all of the following conditions
are true:
* <image> is a component of an existing object with the name
specified by FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, and of the
type specified by FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT.
* The width and height of <image> must be non-zero.
* If FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is TEXTURE and
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT names a 3-dimensional
texture, then FRAMEBUFFER_ATTACHMENT_TEXTURE_ZOFFSET_EXT must be
smaller than the depth of the texture.
* If <attachment> is one of COLOR_ATTACHMENT0_EXT through
COLOR_ATTACHMENTn_EXT, then <image> must have a color-renderable
internal format.
* If <attachment> is DEPTH_ATTACHMENT_EXT, then <image> must have
a depth-renderable internal format.
* If <attachment> is STENCIL_ATTACHMENT_EXT, then <image> must
have a stencil-renderable internal format.
4.4.4.2 Framebuffer Completeness
In this subsection, each rule is followed by an error enum enclosed
in { brackets }. Sections 4.4.4.2 and 4.4.4.3 explains the
relevance of the error enums.
The framebuffer object <target> is said to be "framebuffer complete"
if it is the window-system-provided framebuffer, or if all the
following conditons are true:
* All framebuffer attachment points are "framebuffer attachment
complete".
{ FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT }
* There is at least one image attached to the framebuffer.
{ FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT }
* All attached images have the same width and height.
{ FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT }
* All images attached to the attachment points
COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT must have
the same internal format.
{ FRAMEBUFFER_INCOMPLETE_FORMATS_EXT }
* The value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must not be
NONE for any color attachment point(s) named by DRAW_BUFFERi.
{ FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT }
* If READ_BUFFER is not NONE, then the value of
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must not be NONE for the
color attachment point named by READ_BUFFER.
{ FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT }
* The combination of internal formats of the attached
images does not violate an implementation-dependent set of
restrictions.
{ FRAMEBUFFER_UNSUPPORTED_EXT }
The enum in { brackets } after each clause of the framebuffer
completeness rules specifies the return value of
CheckFramebufferStatusEXT (see below) that is generated when that
clause is violated. If more than one clause is violated, it is
implementation-dependent exactly which enum will be returned by
CheckFramebufferStatusEXT.
Performing any of the following actions may change whether the
framebuffer is considered complete or incomplete.
- Binding to a different framebuffer with BindFramebufferEXT.
- Attaching an image to the framebuffer with
FramebufferTexture{1D|2D|3D}EXT or FramebufferRenderbufferEXT.
- Detaching an image from the framebuffer with
FramebufferTexture{1D|2D|3D}EXT or FramebufferRenderbufferEXT.
- Changing the width, height, or internal format of a texture
image that is attached to the framebuffer by calling
{Copy|Compressed}TexImage{1D|2D|3D}.
- Changing the width, height, or internal format of a renderbuffer
that is attached to the framebuffer by calling
RenderbufferStorageEXT.
- Deleting, with DeleteTextures or DeleteRenderbuffers, an object
containing an image that is attached to a framebuffer object
that is bound to the framebuffer.
- Changing READ_BUFFER or one of the DRAW_BUFFERS.
Although GL defines a wide variety of internal formats for
framebuffer-attachable images, such as texture images and
renderbuffer images, some implementations may not support rendering
to particular combinations of internal formats. If the combination
of formats of the images attached to a framebuffer object are not
supported by the implementation, then the framebuffer is not
complete under the clause labeled FRAMEBUFFER_UNSUPPORTED_EXT. There
must exist, however, at least one combination of internal formats
for which the framebuffer cannot be FRAMEBUFFER_UNSUPPORTED_EXT.
Because of the "implementation-dependent" clause of the framebuffer
completeness test in particular, and because framebuffer
completeness can change when the set of attached images is modified,
it is strongly advised, though is not required, that an application
check to see if the framebuffer is complete prior to rendering. The
status of the framebuffer object currently bound to <target> can be
queried by calling
enum CheckFramebufferStatusEXT(enum target);
If <target> is not FRAMEBUFFER_EXT, INVALID_ENUM is generated. If
CheckFramebufferStatusEXT is called within a Begin/End pair,
INVALID_OPERATION is generated. If CheckFramebufferStatusEXT
generates an error, 0 is returned.
Otherwise, an enum is returned that identifies whether
or not the framebuffer bound to <target> is complete, and if not
complete the enum identifies one of the rules of framebuffer
completeness that is violated. If the framebuffer is complete, then
FRAMEBUFFER_COMPLETE_EXT is returned.
4.4.4.3 Effects of Framebuffer Completeness on Framebuffer Operations
If the currently bound framebuffer is not framebuffer complete, then
it is an error to attempt to use the framebuffer for writing or
reading. This means that rendering commands such as Begin,
RasterPos, any command that performs an implicit Begin, as well as
commands that read the framebuffer such as ReadPixels and
CopyTex{Sub}Image will generate the error
INVALID_FRAMEBUFFER_OPERATION_EXT if called while the framebuffer is
not framebuffer complete.
4.4.5 Effects of Framebuffer State on Framebuffer Dependent Values
The values of the state variables listed in table 9.nnn (Framebuffer
Dependent Values) may change when a change is made to
FRAMEBUFFER_BINDING_EXT, to the state of the currently bound
framebuffer object, or to an image attached to the currently bound
framebuffer object.
When FRAMEBUFFER_BINDING_EXT is zero, the values of the state
variables listed in table 9.nnn are implementation defined.
When FRAMEBUFFER_BINDING_EXT is non-zero, if the currently bound
framebuffer object is not framebuffer complete, then the values of
the state variables listed in table 9.nnn are undefined.
When FRAMEBUFFER_BINDING_EXT is non-zero and the currently bound
framebuffer object is framebuffer complete, then the values of the
state variables listed in table 9.nnn are completely determined by
FRAMEBUFFER_BINDING_EXT, the state of the currently bound
framebuffer object, and the state of the images attached to the
currently bound framebuffer object.
XXX [from jon leech] describe derivation of red green and blue size
4.4.6 Mapping between Pixel and Element in Attached Image
When FRAMEBUFFER_BINDING_EXT is non-zero, an operation that writes
to the framebuffer modifies the image attached to the selected
logical buffer, and an operation that reads from the framebuffer
reads from the image attached to the selected logical buffer.
If the attached image is a renderbuffer image, then the window
coordinates (x[w], y[w]) corresponds to the value in the
renderbuffer image at the same coordinates.
If the attached image is a texture image, then the window
coordinates (x[w], y[w]) correspond to the texel (i, j, k), from
figure 3.10, as follows:
i = (x[w] - b)
j = (y[w] - b)
k = (zoffset - b)
where b is the texture image's border width, and zoffset is the
value of FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET for the selected
logical buffer. For a two-dimensional texture, k and zoffset are
irrelevant; for a one-dimensional texture, j, k, and zoffset are
both irrelevant.
(x[w], y[w]) corresponds to a border texel if x[w] or y[w] or
zoffset is less than the border size, or if x[w] or y[w] or zoffset
is greater than the border size plus the width or height or depth,
resp., of the texture image.
Conversion to Framebuffer-Attachable Image Components
When an enabled color value is written to the framebuffer while
FRAMEBUFFER_BINDING is non-zero, for each draw buffer the R, G, B,
and A values are converted to internal components as described in
table 3.15, according to the table row corresponding to the internal
format of the framebuffer-attachable image attached to the selected
logical buffer, and the resulting internal components are written to
the image attached to logical buffer. The masking operations
described in section 4.2.2 are also effective.
Conversion to RGBA Values
When a color value is read or is used as the source of a logical
operation or blending, while FRAMEBUFFER_BINDING is non-zero, the
components of the framebuffer-attachable image that is attached to
the logical buffer selected by READ_BUFFER are first converted to R,
G, B, and A values according to table 3.21 and the internal format
of the attached image."
Additions to Chapter 5 of the OpenGL 1.5 Specification (Special Functions)
Added to section 5.4, as part of the discussion of which commands
are not compiled into display lists:
"Certain commands, when called while compiling a display list, are
not compiled into the display list but are executed immediately.
These are: ..., GenFramebuffersEXT, BindFramebufferEXT,
DeleteFramebuffersEXT, CheckFramebufferStatusEXT,
GenRenderbuffersEXT, BindRenderbufferEXT, DeleteRenderbuffersEXT,
RenderbufferStorageEXT, FramebufferTexture1DEXT,
FramebufferTexture2DEXT, FramebufferTexture3DEXT,
FramebufferRenderbufferEXT, GenerateMipmapEXT..."
Additions to Chapter 6 of the OpenGL 1.5 Specification (State and State
Requests)
Add to section 6.1.3, Enumerated Queries:
In the list of state query functions, add:
"void GetFramebufferAttachmentParameterivEXT(enum target,
enum attachment,
enum pname,
int *params);
<target> must be FRAMEBUFFER_EXT. <attachment> must be one
of the attachment points of the framebuffer listed in table
1.nnn. <pname> must be one of the following:
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT.
If the framebuffer currently bound to <target> is zero, then
INVALID_OPERATION is generated.
Upon successful return from
GetFramebufferAttachmentParameterivEXT, if <pname> is
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT, then param will
contain one of NONE, TEXTURE, or RENDERBUFFER_EXT,
identifying the type of object which contains the attached
image.
If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is
RENDERBUFFER_EXT, then
If <pname> is FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
<params> will contain the name of the renderbuffer
object which contains the attached image.
Otherwise, INVALID_ENUM is generated.
If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is
TEXTURE, then
If <pname> is FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
then <params> will contain the name of the texture
object which contains the attached image.
If <pname> is FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
then <params> will contain the mipmap level of the
texture object which contains the attached image.
If <pname> is
FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT and the
texture object named
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT is a cube map
texture, then <params> will contain the cube map face of
the cubemap texture object which contains the attached
image. Otherwise <params> will contain the value zero.
If <pname> is
FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT and the
texture object named
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT is a
3-dimensional texture, then <params> will contain the
zoffset of the 2D image of the 3D texture object which
contains the attached image. Otherwise <params> will
contain the value zero.
Otherwise, INVALID_ENUM is generated.
void GetRenderbufferParameterivEXT(enum target, enum pname,
int* params);
<target> must be RENDERBUFFER_EXT. <pname> must be one of
the symbolic values in table 8.nnn.
If the renderbuffer currently bound to <target> is zero,
then INVALID_OPERATION is generated.
Upon successful return from GetRenderbufferParameterivEXT,
if <pname> is RENDERBUFFER_WIDTH_EXT,
RENDERBUFFER_HEIGHT_EXT, or
RENDERBUFFER_INTERNAL_FORMAT_EXT, then <params> will contain
the width in pixels, height in pixels, or internal format,
respectively, of the image of the renderbuffer currently
bound to <target>.
Upon successful return from GetRenderbufferParameterivEXT,
if <pname> is RENDERBUFFER_RED_SIZE_EXT,
RENDERBUFFER_GREEN_SIZE_EXT, RENDERBUFFER_BLUE_SIZE_EXT,
RENDERBUFFER_ALPHA_SIZE_EXT, RENDERBUFFER_DEPTH_SIZE_EXT, or
RENDERBUFFER_STENCIL_SIZE_EXT, then <params> will contain
the actual resolutions, (not the resolutions specified when
the image array was defined), for the red, green, blue,
alpha depth, or stencil components, respectively, of the
image of the renderbuffer currently bound to <target>.
Otherwise, INVALID_ENUM is generated."
After section 6.1.13 and before section 6.1.14 (which should be
renumbered 6.1.16), add two new sections:
6.1.14 Framebuffer Object Queries
The command
boolean IsFramebufferEXT( uint framebuffer );
returns TRUE if <framebuffer> is the name of an framebuffer
object. If <framebuffer> is zero, or if <framebuffer> is a
non-zero value that is not the name of an framebuffer object,
IsFramebufferEXT return FALSE.
6.1.15 Renderbuffer Object Queries
The command
boolean IsRenderbufferEXT( uint renderbuffer );
returns TRUE if <renderbuffer> is the name of a renderbuffer
object. If <renderbuffer> is zero, or if <renderbuffer> is a
non-zero value that is not the name of a renderbuffer object,
IsRenderbufferEXT return FALSE.
Errors
The error INVALID_OPERATION is generated if FRAMEBUFFER_BINDING_EXT
is zero and DrawBuffer or DrawBuffers is called with a <buf>
constant (other than NONE) that does not correspond to a buffer
allocated to the GL by the window-system, including the constants
COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT, where n is
MAX_COLOR_ATTACHMENTS_EXT - 1.
The error INVALID_OPERATION is generated if FRAMEBUFFER_BINDING_EXT
is non-zero and DrawBuffer, DrawBuffers, or ReadBuffer is called
with a <buf> constant (other than NONE) that is not in the range
COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT, where n is
MAX_COLOR_ATTACHMENTS_EXT - 1.
The error INVALID_ENUM is generated if DrawBuffer or ReadBuffer is
called with a <buf> constant that is not listed in table 4.4 or
10.nnn.
The error INVALID_ENUM is generated if DrawBuffers is called with a
<buf> constant that is not listed in table 10.nnn or 11.nnn.
The error INVALID_FRAMEBUFFER_OPERATION_EXT is generated if the
value of FRAMEBUFFER_STATUS_EXT is not FRAMEBUFFER_COMPLETE_EXT when
any attempts to render to or read from the framebuffer are made.
The error INVALID_OPERATION is generated if
GetFramebufferAttachmentParameterivEXT is called while the value of
FRAMEBUFFER_BINDING_EXT is zero.
The error INVALID_OPERATION is generated if
FramebufferRenderbufferEXT or FramebufferTexture{1D|2D|3D}EXT is
called while the value of FRAMEBUFFER_BINDING_EXT is zero.
The error INVALID_OPERATION is generated if RenderbufferStorageEXT
or GetRenderbufferParameterivEXT is called while the value of
RENDERBUFFER_BINDING_EXT is zero.
The error INVALID_ENUM is generated if
GetFramebufferAttachmentParameterivEXT is called with an
<attachment> other than COLOR_ATTACHMENT0_EXT through
COLOR_ATTACHMENTn_EXT, where n is MAX_COLOR_ATTACHMENTS_EXT - 1.
The error INVALID_ENUM is generated if
GetFramebufferAttachmentParameterivEXT is called with a <pname>
other than FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT when the type of
the attached object at the named attachment point is
RENDERBUFFER_EXT.
The error INVALID_ENUM is generated if
GetFramebufferAttachmentParameterivEXT is called with a <pname>
other than FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT, or
FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT when the type of the
attached object at the named attachment point is TEXTURE.
The error INVALID_ENUM is generated if GetRenderbufferParameterivEXT
is called with a <pname> other than RENDERBUFFER_WIDTH_EXT,
RENDERBUFFER_HEIGHT_EXT, or RENDERBUFFER_INTERNAL_FORMAT_EXT,
GL_RENDERBUFFER_RED_SIZE, GL_RENDERBUFFER_GREEN_SIZE,
GL_RENDERBUFFER_BLUE_SIZE, GL_RENDERBUFFER_ALPHA_SIZE,
GL_RENDERBUFFER_DEPTH_SIZE, or GL_RENDERBUFFER_STENCIL_SIZE.
The error INVALID_VALUE is generated if RenderbufferStorageEXT is
called with a <width> or <height> that is greater than
MAX_RENDERBUFFER_SIZE_EXT.
The error INVALID_ENUM is generated if RenderbufferStorageEXT is
called with an <internalformat> that is not RGB, RGBA,
DEPTH_COMPONENT, STENCIL_INDEX, or one of the internal formats from
table 3.16 or table 2.nnn that has a base internal format of RGB,
RGBA, DEPTH_COMPONENT, or STENCIL_INDEX.
The error INVALID_OPERATION is generated if
FramebufferRenderbufferEXT is called and <renderbuffer> is not the
name of a renderbuffer object or zero.
The error INVALID_OPERATION is generated if
FramebufferTexture{1D|2D|3D}EXT is called and <texture> is not the
name of a texture object or zero.
The error INVALID_VALUE is generated if
FramebufferTexture{1D|2D|3D}EXT is called with a <level> that is
less than zero and <texture> is not zero.
The error INVALID_VALUE is generated if FramebufferTexture2DEXT is
called with a <level> that is not zero and <textarget> is
TEXTURE_RECTANGLE_ARB and <texture> is not zero.
The error INVALID_VALUE is generated if FramebufferTexture{1D|2D}EXT
is called with a <level> that is greater than the log base 2 of
MAX_TEXTURE_SIZE and <texture> is respectively a non-zero 1D or 2D
texture object name.
The error INVALID_VALUE is generated if FramebufferTexture2DEXT
is called with a <level> that is greater than the log base 2 of
MAX_CUBE_MAP_TEXTURE_SIZE and <texture> is a non-zero cubemap
texture object name.
The error INVALID_VALUE is generated if FramebufferTexture3DEXT is
called with a <level> greater than the log base 2 of the
MAX_3D_TEXTURE_SIZE and <texture> is not zero.
The error INVALID_VALUE is generated if FramebufferTexture3DEXT is
called with a <zoffset> that is larger than MAX_3D_TEXTURE_SIZE-1
and <texture> is not zero.
The error INVALID_ENUM is generated if CheckFramebufferStatusEXT is
called and <target> is not FRAMEBUFFER_EXT.
The error INVALID_OPERATION is generated if
CheckFramebufferStatusEXT is called within a Begin/End pair.
The error OUT_OF_MEMORY is generated if the GL is unable to create a
data store of the required size when calling RenderbufferStorageEXT.
The error INVALID_OPERATION is generated if GenerateMipmapEXT is
called with a <target> of TEXTURE_CUBE_MAP and the texture object
currently bound to TEXTURE_CUBE_MAP is not "cube complete" as
defined in section 3.8.10
New State
(add new table 3.nnn, "Framebuffer (state per framebuffer target binding point)")
Get Value Type Get Command Initial Value Description Section Attribute
------------------------------- ------ ------------- -------------- -------------------- ------------ ---------
FRAMEBUFFER_BINDING_EXT Z GetIntegerv 0 name of framebuffer 4.4.1 -
object bound to
FRAMEBUFFER_EXT
target
(insert new table 4.nnn, "Framebuffer (state per framebuffer object)")
Get Value Type Get Command Initial Value Description Section Attribute
---------------- ------ ------------- ------------- -------------------- ------------ ---------
DRAW_BUFFERi [1] 1 + xZ(10*) GetIntegerv see 4.2.1 draw buffer selected 4.2.1 color-buffer
for color output i
READ_BUFFER [2] Z(3) GetIntegerv see 4.3.2 read source 4.3.2 pixel
[1] prior to this extension, the DRAW_BUFFERi state was described in table 6.21 "Framebuffer Control" (of OpenGL 2.0 spec)
[2] prior to this extension, the READ_BUFFER state was described in table 6.26 "Pixel" (of OpenGL 2.0 spec)
(insert new table 5.nnn, "Framebuffer (state per framebuffer object attachment point)")
Get Value Type Get Command Initial Value Description Section Attribute
------------------------------- ------ ------------- ------------- -------------------- ------------ ---------
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT Z GetFramebufferAttachmentParameterivEXT NONE type of 4.4.2.2 and -
image attached to 4.4.2.3
framebuffer attachment
point
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT Z GetFramebufferAttachmentParameterivEXT 0 name of object 4.4.2.2 and -
attached to 4.4.2.3
framebuffer attachment
point
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT Z GetFramebufferAttachmentParameterivEXT 0 mipmap level of 4.4.2.2 and -
texture image 4.4.2.3
attached, if object
attached is texture.
FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT Z+ GetFramebufferAttachmentParameterivEXT TEXTURE_ cubemap face of 4.4.2.2 and -
CUBE_MAP_ texture image 4.4.2.3
POSITIVE_X attached, if object
attached is cubemap
texture.
FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT Z GetFramebufferAttachmentParameterivEXT 0 zoffset of 4.4.2.2 and -
texture image 4.4.2.3
attached, if object
attached is 3D
texture.
(insert new table 7.nnn, "Renderbuffers (state per renderbuffer target and binding point)")
Get Value Type Get Command Initial Value Description Section Attribute
------------------------------- ------ ------------- ------------- -------------------- ------------ ---------
RENDERBUFFER_BINDING_EXT Z GetIntegerv 0 renderbuffer object 4.4.2.1 -
bound to
RENDERBUFFER_EXT
(insert new table 8.nnn, "Renderbuffers (state per renderbuffer object)")
Get Value Type Get Command Initial Value Description Section Attribute
------------------------------- ------ ------------- ------------- -------------------- ------------ ---------
RENDERBUFFER_WIDTH_EXT Z GetRenderbufferParameterivEXT 0 width of renderbuffer 4.4.2.1 -
RENDERBUFFER_HEIGHT_EXT Z GetRenderbufferParameterivEXT 0 height of renderbuffer 4.4.2.1 -
RENDERBUFFER_INTERNAL_FORMAT_EXT Z+ GetRenderbufferParameterivEXT RGBA internal format 4.4.2.1 -
of renderbuffer
RENDERBUFFER_RED_SIZE_EXT Z GetRenderbufferParameterivEXT 0 size in bits of 4.4.2.1 -
renderbuffer image's
red component
RENDERBUFFER_GREEN_SIZE_EXT Z GetRenderbufferParameterivEXT 0 size in bits of 4.4.2.1 -
renderbuffer image's
green component
RENDERBUFFER_BLUE_SIZE_EXT Z GetRenderbufferParameterivEXT 0 size in bits of 4.4.2.1 -
renderbuffer image's
blue component
RENDERBUFFER_ALPHA_SIZE_EXT Z GetRenderbufferParameterivEXT 0 size in bits of 4.4.2.1 -
renderbuffer image's
alpha component
RENDERBUFFER_DEPTH_SIZE_EXT Z GetRenderbufferParameterivEXT 0 size in bits of 4.4.2.1 -
renderbuffer image's
depth component
RENDERBUFFER_STENCIL_SIZE_EXT Z GetRenderbufferParameterivEXT 0 size in bits of 4.4.2.1 -
renderbuffer image's
stencil component
Move the following existing state from "Implementation Dependent
Values", tables 6.31-6.36 to into a new table called "Framebuffer
Dependent Values", table 9.nnn.
Get Value
---------
AUX_BUFFERS
MAX_DRAW_BUFFERS
RGBA_MODE
INDEX_MODE
DOUBLEBUFFER
STEREO
SAMPLE_BUFFERS
SAMPLES
RED_BITS
GREEN_BITS
BLUE_BITS
ALPHA_BITS
DEPTH_BITS
STENCIL_BITS
ACCUM_RED_BITS
ACCUM_GREEN_BITS
ACCUM_BLUE_BITS
ACCUM_ALPHA_BITS
To the same table called "Framebuffer Dependent Values", table 9.nnn
add the following new framebuffer dependent state.
Get Value Type Get Command Minimum Value Description Section Attribute
--------- ---- ----------- ------------- ------------------- ------- ---------
MAX_COLOR_ATTACHMENTS_EXT Z+ GetIntegerv 1 Maximum number of 4.4.2.2 -
attachment points
for color buffers
when using framebuffer
objects
New Implementation Dependent State
Get Value Type Get Command Minimum Value Description Section Attribute
--------- ---- ----------- ------------- ------------------- ------- ---------
MAX_RENDERBUFFER_SIZE_EXT Z+ GetIntegerv 1 Maximum width and 4.4.2.1 -
height of
renderbuffers
supported by
the implementation
Additions to the AGL/GLX/WGL Specifications and dependencies on
WGL_ARB_make_current_read, GLX_SGI_make_current_read, and GLX 1.3
The color, depth, stencil, aux, and accum logical buffers defined by
the <draw> and <read> drawables passed to glXMakeContextCurrent,
glXMakeCurrent, and glXMakeCurrentRead are ignored while the value
of FRAMEBUFFER_BINDING_EXT is non-zero.
Dependencies on ATI_draw_buffers and ARB_draw_buffers
If neither ATI_draw_buffers nor ARB_draw_buffers are supported, then
all discussions of DrawBuffers should be ignored.
In addition, the language describing DrawBuffers are derived from a
combination of the ARB_draw_buffers specification and section 4.2.1
of the OpenGL 2.0 specification.
Dependencies on ARB_fragment_program, ARB_fragment_shader, and
ARB_vertex_shader
If ARB_fragment_program, ARB_fragment_shader, and ARB_vertex_shader
are all not supported, then all references to the currently bound
program or shader should be ignored.
Dependencies on ARB_framebuffer_object and OpenGL 3.0
Framebuffer objects created with the commands defined by the
GL_EXT_framebuffer_object extension are defined to be shared, while
FBOs created with commands defined by the OpenGL core or
GL_ARB_framebuffer_object extension are defined *not* to be shared.
However, the following functions are viewed as aliases (in particular
the opcodes for X are also the same) between the functions of
GL_EXT_framebuffer_object and GL_ARB_framebuffer_object:
IsRenderbufferEXT / IsRenderbuffer
DeleteRenderbuffersEXT / DeleteRenderbuffers
GenRenderbuffersEXT / GenRenderbuffers
RenderbufferStorageEXT / RenderbufferStorage
GetRenderbufferParameterivEXT / GetRenderbufferParameteriv
IsFramebufferEXT / IsFramebuffer
DeleteFramebuffersEXT / DeleteFramebuffers
GenFramebuffersEXT / GenFramebuffers
CheckFramebufferStatusEXT / CheckFramebufferStatus
FramebufferTexture1DEXT / FramebufferTexture1D
FramebufferTexture2DEXT / FramebufferTexture2D
FramebufferRenderbufferEXT / FramebufferRenderbuffer
GenerateMipmapEXT / GenerateMipmap
GetFramebufferAttachmentParameterivEXT / GetFramebufferAttachmentParameteriv
Since the above pairs are aliases, the functions of a pair are
equivalent. Note that the functions BindFramebuffer and
BindFramebufferEXT are not aliases and neither are the functions
BindRenderbuffer and BindRenderbufferEXT. Because object creation
occurs when the framebuffer object is bound for the first time, a
framebuffer object can be shared across contexts only if it was first
bound with BindFramebufferEXT. Framebuffers first bound with
BindFramebuffer may not be shared across contexts. Framebuffer
objects created with BindFramebufferEXT may subsequently be bound
using BindFramebuffer. Framebuffer objects created with
BindFramebuffer may be bound with BindFramebufferEXT provided they are
bound to the same context they were created on.
Dependencies on ARB_texture_rectangle
If ARB_texture_rectangle is not supported, then all references to
TEXTURE_RECTANGLE_ARB should be ignored.
Dependencies on EXT_packed_depth_stencil
If EXT_packed_depth_stencil is not supported, then all references to
DEPTH_STENCIL internal formats should be ignored.
Dependencies on NV_float_buffer
If NV_float_buffer is not supported, then all references to the
following internal formats should be ignored: FLOAT_R_NV,
FLOAT_RG_NV, FLOAT_RGB_NV, and FLOAT_RGBA_NV.
Dependencies on NV_texture_shader
The following base internal formats are not color-renderable,
depth-renderable, or stencil-renderable: HILO_NV, DSDT_NV,
DSDT_MAG_NV, and DSDT_MAG_INTENSITY_NV.
GLX Protocol
Seventeen new GL commands are added.
The following ten rendering commands are sent to the sever as part
of a glXRender request:
BindRenderbufferEXT
2 12 rendering command length
2 4316 rendering command opcode
4 ENUM target
4 CARD32 renderbuffer
DeleteRenderbufferEXT
2 8+n*4 rendering command length
2 4317 rendering command opcode
4 CARD32 n
n*4 LISTofCARD32 renderbuffers
RenderbufferStorageEXT
2 20 rendering command length
2 4318 rendering command opcode
4 ENUM target
4 ENUM internalFormat
4 CARD32 width
4 CARD32 height
BindFramebufferEXT
2 12 rendering command length
2 4319 rendering command opcode
4 ENUM target
4 CARD32 framebuffer
DeleteFramebufferEXT
2 8+n*4 rendering command length
2 4320 rendering command opcode
4 CARD32 n
n*4 LISTofCARD32 framebuffers
FramebufferTexture1DEXT
2 24 rendering command length
2 4321 rendering command opcode
4 ENUM target
4 ENUM attachement
4 ENUM textarget
4 CARD32 texture
4 CARD32 level
FramebufferTexture2DEXT
2 24 rendering command length
2 4322 rendering command opcode
4 ENUM target
4 ENUM attachement
4 ENUM textarget
4 CARD32 texture
4 CARD32 level
FramebufferTexture3DEXT
2 28 rendering command length
2 4323 rendering command opcode
4 ENUM target
4 ENUM attachement
4 ENUM textarget
4 CARD32 texture
4 CARD32 level
4 CARD32 zoffset
FramebufferRenderbufferEXT
2 20 rendering command length
2 4324 rendering command opcode
4 ENUM target
4 ENUM attachment
4 ENUM renderbuffertarget
4 CARD32 renderbuffer
GenerateMipmapEXT
2 8 rendering command length
2 4325 rendering command opcode
4 ENUM target
The remaining seven commands are non-rendering commands. These
commands are sent separately (i.e., not as part of a glXRender or
glXRenderLarge request), using the glXVendorPrivateWithReply
request:
IsRenderbufferEXT
1 CARD8 opcode (X assigned)
1 17 GLX opcode (X_GLXVendorPrivateWithReply)
2 4 request length
4 1422 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 CARD32 renderbuffer
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 0 reply length
4 BOOL32 return value
20 unused
GenRenderbuffersEXT
1 CARD8 opcode (X assigned)
1 17 GLX opcode (X_GLXVendorPrivateWithReply)
2 4 request length
4 1423 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 CARD32 n
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length
4 unused
4 CARD32 n
16 unused
n*4 LISTofCARD32 renderbuffers
GetRenderbufferParameterivEXT
1 CARD8 opcode (X assigned)
1 17 GLX opcode (X_GLXVendorPrivateWithReply)
2 5 request length
4 1424 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m = (n == 1 ? 0 : n)
4 unused
4 CARD32 n
if (n = 1) this follows:
4 CARD32 params
12 unused
otherwise this follows:
16 unused
n*4 LISTofCARD32 params
IsFramebufferEXT
1 CARD8 opcode (X assigned)
1 17 GLX opcode (X_GLXVendorPrivateWithReply)
2 4 request length
4 1425 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 CARD32 framebuffer
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 0 reply length
4 BOOL32 return value
20 unused
GenFramebuffersEXT
1 CARD8 opcode (X assigned)
1 17 GLX opcode (X_GLXVendorPrivateWithReply)
2 4 request length
4 1426 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 CARD32 n
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 n reply length
4 unused
4 CARD32 n
16 unused
n*4 LISTofCARD32 framebuffers
CheckFramebufferStatusEXT
1 CARD8 opcode (X assigned)
1 17 GLX opcode (X_GLXVendorPrivateWithReply)
2 4 request length
4 1427 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 0 reply length
4 ENUM return value
20 unused
GetFramebufferAttachementParameterivEXT
1 CARD8 opcode (X assigned)
1 17 GLX opcode (X_GLXVendorPrivateWithReply)
2 6 request length
4 1428 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
4 ENUM attachment
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m = (n == 1 ? 0 : n)
4 unused
4 CARD32 n
if (n = 1) this follows:
4 CARD32 params
12 unused
otherwise this follows:
16 unused
n*4 LISTofCARD32 params
Usage Examples
The following examples use a helper macro for
CHECK_FRAMEBUFFER_STATUS, defined below.
Example (6) gives a (very slightly) more robust example of handling
the possible return values for glCheckFramebufferStatusEXT.
#define CHECK_FRAMEBUFFER_STATUS() \
{ \
GLenum status; \
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); \
switch(status) { \
case GL_FRAMEBUFFER_COMPLETE_EXT: \
break; \
case GL_FRAMEBUFFER_UNSUPPORTED_EXT: \
/* choose different formats */ \
break; \
default: \
/* programming error; will fail on all hardware */ \
assert(0); \
}
}
(1) Render to 2D texture with a depth buffer
// Given: color_tex - TEXTURE_2D color texture object
// depth_rb - GL_DEPTH renderbuffer object
// fb - framebuffer object
// Enable render-to-texture
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
// Set up color_tex and depth_rb for render-to-texture
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_tex, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb);
// Check framebuffer completeness at the end of initialization.
CHECK_FRAMEBUFFER_STATUS();
<draw to the texture and renderbuffer>
// Re-enable rendering to the window
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, color_tex);
<draw to the window, reading from the color_tex>
(2) Application that supports both RBBCTT (render back buffer, copy to
texture) and RTT (render to texture). The migration path from RBBCTT
to RTT is easy.
if (useFramebuffer) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_tex, 0);
CHECK_FRAMEBUFFER_STATUS();
}
draw_to_texture();
glBindTexture (GL_TEXTURE_2D, color_tex);
if (useFramebuffer) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
} else { // copy tex path
glCopyTexSubImage(...);
}
(3) Simple render-to-texture loop with initialization. Create an
RGB8 texture, a 24-bit depth renderbuffer, and a stencil
renderbuffer. In a loop, alternate between rendering to, and
texturing out of, the color texture.
glGenFramebuffersEXT(1, &fb);
glGenTextures(1, &color_tex);
glGenRenderbuffersEXT(1, &depth_rb);
glGenRenderbuffersEXT(1, &stencil_rb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
// initialize color texture
glBindTexture(GL_TEXTURE_2D, color_tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0,
GL_RGB, GL_INT, NULL);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_tex, 0);
// initialize depth renderbuffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
GL_DEPTH_COMPONENT24, 512, 512);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb);
// initialize stencil renderbuffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, stencil_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
GL_STENCIL_INDEX, 512, 512);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, stencil_rb);
// Check framebuffer completeness at the end of initialization.
CHECK_FRAMEBUFFER_STATUS();
loop {
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
<draw to the texture>
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, color_tex);
<draw to the window, reading from the color texture>
}
(4) Render-to-texture loop with automatic mipmap generation. There
are N framebuffers, N mipmap color textures, and a single shared
depth renderbuffer. The depth renderbuffer is not a mipmap.
GLuint fb_array[N];
GLuint color_tex_array[N];
GLuint depth_rb;
glGenFramebuffersEXT(N, fb_array);
glGenTextures(N, color_tex_array);
glGenRenderbuffersEXT(1, &depth_rb);
// initialize color textures
for (int i=0; i<N; i++) {
glBindTexture(GL_TEXTURE_2D, color_tex_array[N]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0,
GL_RGB, GL_INT, NULL);
// establish a mipmap chain for the texture
glGenerateMipmapEXT(GL_TEXTURE_2D);
}
// initialize depth renderbuffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
GL_DEPTH_COMPONENT24, 512, 512);
// setup framebuffers, sharing depth
for (int i=0; i<N; i++) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_array[i]);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_tex_array[i], 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb);
}
// Check framebuffer completeness at the end of initialization.
CHECK_FRAMEBUFFER_STATUS();
loop {
glBindTexture(GL_TEXTURE_2D, 0);
for (int i=0; i<N; i++) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_array[i]);
<draw to texture i>
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
// automatically generate mipmaps
for (int i=0; i<N; i++) {
glBindTexture(GL_TEXTURE_2D, color_tex_array[i]);
glGenerateMipmapEXT(GL_TEXTURE_2D);
}
<draw to the window, reading from the color textures>
}
(5) Render-to-texture loop with custom mipmap generation.
The depth renderbuffer is not a mipmap.
glGenFramebuffersEXT(1, &fb);
glGenTextures(1, &color_tex);
glGenRenderbuffersEXT(1, &depth_rb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
// initialize color texture and establish mipmap chain
glBindTexture(GL_TEXTURE_2D, color_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0,
GL_RGB, GL_INT, NULL);
glGenerateMipmapEXT(GL_TEXTURE_2D);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_tex, 0);
// initialize depth renderbuffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
GL_DEPTH_COMPONENT24, 512, 512);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb);
// Check framebuffer completeness at the end of initialization.
CHECK_FRAMEBUFFER_STATUS();
loop {
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_tex, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb);
<draw to the base level of the color texture>
// custom-generate successive mipmap levels
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, color_tex);
foreach (level > 0, in order of increasing values of level) {
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_tex, level);
glTexParameteri(TEXTURE_2D, TEXTURE_BASE_LEVEL, level-1);
glTexParameteri(TEXTURE_2D, TEXTURE_MAX_LEVEL, level-1);
<draw to level>
}
glTexParameteri(TEXTURE_2D, TEXTURE_BASE_LEVEL, 0);
glTexParameteri(TEXTURE_2D, TEXTURE_MAX_LEVEL, max);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
<draw to the window, reading from the color texture>
}
(6) Pseudo-code example of one method of responding to
FRAMEBUFFER_UNSUPPORTED_EXT
bool done = false;
bool success = false;
int configurationNumber = 0;
GLenum status;
while (!done)
{
for (each framebuffer-attachable image)
{
ChooseInternalFormatForFramebufferAttachableImage(configurationNumber);
CreateFramebufferAttachableImage();
AttachFramebufferAttachableImageToFramebuffer();
}
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status)
{
case GL_FRAMEBUFFER_COMPLETE_EXT:
success = true;
done = true;
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
if (configCount < MAX_NUM_CONFIGS_I_WANT_TO_TRY)
{
printf("current config not supported, trying again);
configurationNumber++;
}
else
{
printf("couldn't find a supported config\n");
success = false;
done = true;
}
break;
default:
// programming error; will fail on all hardware
FatalError();
exit(1);
}
}
if (!success)
{
printf("couldn't find a supported config\n");
FatalError();
exit(1);
}
// Current framebuffer is supported and complete!!
Draw();
(7) Render to depth texture with no color attachments
// Given: depth_tex - TEXTURE_2D depth texture object
// fb - framebuffer object
// Enable render-to-texture
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
// Set up depth_tex for render-to-texture
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, depth_tex, 0);
// No color buffer to draw to or read from
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
// Check framebuffer completeness at the end of initialization.
CHECK_FRAMEBUFFER_STATUS();
<draw something>
// Re-enable rendering to the window
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, depth_tex);
<draw to the window, reading from the depth_tex>
(8) FBO and ARB_draw_buffers
// Given: color_texA - TEXTURE_2D color texture object
// Given: color_texB - TEXTURE_2D color texture object
// depth_rb - GL_DEPTH renderbuffer object
// fb - framebuffer object
// Set up the framebuffer object
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, color_texA, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT1_EXT,
GL_TEXTURE_2D, color_texB, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_rb);
// Enable both attachments as draw buffers
GLenum drawbuffers = {GL_COLOR_ATTACHMENT0_EXT,
GL_COLOR_ATTACHMENT1_EXT};
glDrawBuffers(2, drawbuffers);
// Check framebuffer completeness at the end of initialization.
CHECK_FRAMEBUFFER_STATUS();
// Enable fragment program that writes to both gl_FragData[0]
// and gl_FragData[1]
<draw something>
// Disable fragment program
// Re-enable rendering to the window
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
// Bind both textures, each to a different texture unit
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, color_texA);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, color_texB);
<draw to the window>
Issues
(1) We obviously won't call this "ARB_compromise_buffers", so
what name should we use?
RESOLUTION: resolved, EXT_framebuffer_object
Possibilities considered include:
EXT_framebuffer
EXT_framebuffer_object
EXT_renderable_buffers
EXT_renderbuffer
EXT_superbuffers (hah!)
EXT_renderable_image
EXT_render_image
The lead candidates were EXT_renderable_image and
EXT_framebuffer_object Since this extension introduced both
new concepts into OpenGL, this was a bit of a toss up.
EXT_framebuffer_object was chosen based on a weak precedent
given by EXT_texture_object and ARB_vertex_buffer_object
(2) Many developers complain about the OpenGL/glX/WGL/agl pbuffer
API, which they use both to do "render to texture" and to do
general offscreen (non-windowed) accelerated rendering. This
extension is intended to subsume, some and perhaps all of, the
functionality currently handled by pbuffers. Should this
extension (initially?) support only render-to-texture or should
it try to provide an OpenGL API to fully replace the pbuffer
API?
RESOLUTION: This extension should fully replace the pbuffer API.
The implication of this decision is that this API should provide
a way to support rendering to offscreen buffers that are not
textures.
(3) As a consequence of issue (2), this extension adds the concept of
share-able, non-texturable renderable entitites that can be
used as color buffers, depth buffers, stencil buffers, etc.
The OpenGL spec refers to these entities as "logical buffers".
What should this spec call them?
RESOLUTION: "renderbuffer", (one word)
We could just call them "logical buffers", but is there a
better name?
The group considered:
logical buffer - possible, kind of general
render buffer - clear, (one word or two?)
renderable - clear, but may conflict with glx "drawable"
drawable - confusing: glx "drawable" == gl "framebuffer"
render surface - possible
render target - possible
image buffer - may get confused with Tex"Image"
image - may get confused with Tex"Image"
surface buffer - too verbose?
surface - too general
others???
The group felt "render buffer " (or possibly "renderbuffer")
provides for the clearest expression of the purpose for
these buffers.
We finally decided on "renderbuffer" because we didn't want
to use "render" as an adjective to describe a generic
buffer, but rather decided to coin a new compound word to
describe this concept.
(4) How should the specification refer to the group of
various types of objects that can be attached to the framebuffer
attachment points?
RESOLUTION: The specification will use the phrase
"framebuffer-attachable images" to mean the 2D array of
pixels (image) of a "renderbuffer", a "texture", or any
other items that could be attached to a framebuffer.
Options considered include:
"render target"
"renderable image"
"framebuffer-attachable
Initially, we chose the phrase "render target" for this but
felt it didn't accurately capture the concept of a 2D array
of pixels that was simultaneously useable as the storage of
a texture object and the destination of rendering.
We then tried to borrow the "image" language of OpenGL which
describes texture's pixel arrays as "images" and we chose
the term "renderable image".
However, in the end, we felt that the salient characteristic
of these images was that we could attach them to a
framebuffer and settled on the term "framebuffer-attachable
image".
(5) How should the specification refer to the places in a framebuffer
that can hold a framebuffer-attachable image?
RESOLUTION: This state is called an "attachment point" of
the framebuffer.
"attachment points" will be be used to describe the
framebuffer state that holds a connection to a given
framebuffer-attachable image (a renderbuffer image or a
texture image). The framebuffer attachment points include
the framebuffer's color buffers, stencil buffer, depth
buffer, and aux buffer.
The word "attach" is being used to refer to connecting one
object to another. "bind" refers to connecting an object to
the context state. A texture image can be attached to a
framebuffer object, but a framebuffer object is bound into
the context state vector.
(6) This extension adds the concept of collections of "logical
buffers", to replace the window-system provided collection
(drawable, or window) of logical buffers. What should we call
these?
RESOLUTION: "framebuffer"
For the "collection of logical buffers" object, the group
considered the names: "framebuffer", "renderTarget",
"drawable". We chose "framebuffer" since this is consistent
with how the OpenGL specification already uses the word
framebuffer.
(7) This extension introduces two new object types into the OpenGL:
renderbuffer objects and framebuffer objects. For handling
these objects, there are two main object manipulation
methodology precedents to choose from:
1) "texture/program/vbo" object model:
app-supplied int handles,
Gen/is/Bind/Delete functions
2) "GLSL" object model:
driver-supplied GLhandle handles,
Create/Delete/Attach, etc
Which methodology should this extension use for each new object?
RESOLUTION: Use Option (1), "texture" object methodology,
for both "renderbuffer" objects and framebuffer objects.
This is consistent with the June, 2004 ARB meeting vote to
use the "texture" object methodlogy as the default object
methodology.
(8) Do we need separate framebuffer objects?
RESOLUTION: yes.
The framebuffer object is an object to encapsulate the state
of the framebuffer and the collection of
framebuffer-attachable images attached to the logical buffer
attachment points. A question was raised early on about
whether we should have separate, shareable framebuffer
objects or we should fold a single framebuffer "object"
state vector into the context.
We decided to leave framebuffer objects in the API, with the
understanding that we could easily remove them from the API
and the spec later if a convincing case was argued for
removing it.
There are several reasons why framebuffer objects were
introduced:
FB1. It can be "expensive" (for some definition of
expensive) to validate the framebuffer and all its
attached objects. There is a desire to be able to
easily recognize that a particular state. combination
has been seen and validated previously.
FB2. There is some subset of GL context state which only
makes sense in its relationship to the current
framebuffer and attached images (red bits, green
bits, blue bits, etc, presence or absence of aux
buffers or depth buffers, current value of draw
buffer(s), read buffer, etc. etc). It would be nice
if this state "tracked" changes to the current
framebuffer configuration by being part of the
framebuffer object state.
FB3. For a while, we considered adding "intrinsic" or
"implicit" buffer storage to the framebuffer. This
would be used for buffers that were either hidden
from the user, like the multisample buffer, or
perhaps needed to be explicitly formatted by the
driver. If we did have this kind of "intrinsic"
storage, then framebuffers would be a lot like
textures and would have the same kinds of pressures
to minimize vram, sharing storage across objects and
contexts as textures did. In fact, they would be
similar to cube map texture objects which had 6
attached face images, or mipmaped textures which had
a set of mipmap level images. In the end we decided
not to use intrinsic buffers, - see issue (13) - but
we might decide to add them back in the future. For
instance, one option for supporting multisampling is
to use an implicit multisample buffer.
FB4. We realized that most of the "hard" issues introduced
by this extension were completely orthogonal to the
presence or absence of framebuffer objects. All of
the same issues apply regardless of whether there is
a single non-default framebuffer as part of the
context or multiple framebuffer objects. These
issues about attaching, (binding) objects,
reformatting attached (or bound) images via
TexImage/RenderbufferStorage, pixel format
combinations, framebuffer completeness, and the
relationship between a non-"default" framebuffer and
the legacy window sytem framebuffer and pixel format
all come in to play either way. So there is actually
little implementation or conceptual cost incurred by
the introduction of these framebuffer objects.
There were also a few reasons why we considered *not* adding
framebuffer objects:
NoFB1. In the absence of "intrinsic" buffers, framebuffer
objects only really consist of the attachment
state. It is convenient to encapsulate this state
into an object, but one could ask if it's any more
convenient than say a "blend state" object or a
"texture unit attachment state" object, which to
date, we have chosen not to add into OpenGL.
NoFB2. As a "state-only" object, there's a question about
how much state should be included - at least the
attachment state should be included, but what about
draw buffers state, what about the viewport state,
what about other state? Since drawing the line is
hard, we questioned whether we needed these
objects.
NoFB3. Some amount of the functionality of the framebuffer
objects could be implemented by the application
with the appropriate use of display lists.
In weighing (FB1), expense of validating framebuffer state,
versus (NoFB1), not wanting to introduce "state only"
objects, we realized that framebuffer validation is more
expensive than the blend state (for which there is no object
in GL) and less expensive than a fragment program (for which
there is an object in GL). While it's not exactly clear
precisely where on the spectrum of "expense" the framebuffer
validation lies, we decided that it may be expensive enough
to justify creating a new object type. So we retained
framebuffer objects in the API now, with the understanding
that if we change our minds it's easier to rip them out
later than it is to add them back in later.
(9) Should the routine which allocates a renderbuffer accept an
image to initialize the buffer, analogous to how TexImage
works?
RESOLUTION: no, it should allocate uninitialized storage
We could have allowed a renderbuffer "image" specification
routine, but this would essentially serve the same purpose
as a combined "allocate renderbuffer followed by DrawPixels"
routine so we decided it was extraneous. The primary
purpose of these buffers is to store rendered output anyway,
so there was not sufficient demand to support an optimized
path for data initialization. See related issue (10).
(10) What should we call the routine that allocates storage for the
renderbuffer? This routine would be the moral equivalent of
glTexImage.
RESOLUTION: RenderbufferStorage()
Options included:
RenderbufferStorage()
RenderbufferImage()
others???
This is really a function of how we resolve issue (9).
RenderbufferImage would be appropriate if the allocation
routine could take an image to initialize the renderbuffer.
RenderbufferStorage would be more appropriate if the
allocation routine does not take an image.
Since the group decided supporting an "initialization" image
for a "renderbuffer" was too much overlapping functionality
with DrawPixels, RenderbufferStorage was chosen.
(11) The routine(s) which attach a texture to a framebuffer
attachment point need to describe which image in the texture
they are using, i.e., which cube map face, mipmap level, or 3D
texture z-slice/depthoffset/image. Should we have one routine
that handles all of these with some arguments ignored for
specific texture types/targets? Or should we have a parallel
set of routines for 1D/2D/3D, like TexImage does?
RESOLUTION: Option (b) 3 routines for texture, 1 for
renderbuffer
Originally, we chose option (b) for reasons of
similarity to glTexImage1D/2D/3D. For TexImage2D and
FramebufferTexture2D, the texture target was used to
select a face on a cube map texture object. Since
glTexImage1D/3D used TEXTURE_1D/TEXTURE_3D texture
targets, we did the same for FramebufferTexture1D/3D. We
also included the texture target in case it was needed
for future expandability.
However, some felt uncomfortable with this resolution
since it adds 3 framebuffer attachment calls for
textures, so we reopened the issue.
Originally we just considered options (a) and (b). We
then reconsidered a few additional flavors: (c), (d),
and (e)
Options include:
a) one routine with arguments that are sometimes "ignored"
For instance <image> is ignored for non-3D textures
and <face> is ignored for non-cube maps, etc.
This gives us:
void FramebufferTexture(enum target, enum attachment,
uint texture,
uint level, enum face, uint image);
b) routines for 1D/2D/3D, use FramebufferTexture2D for 2D,
Cube, Rectangle
Requires use of a texture target to distinguish cube map
faces on FramebufferTexture2D
Includes "redundant" texture target for 1D/3D variants
for consistency and precedent with TexImage1D/3D.
This gives us:
void FramebufferTexture1D(enum target, enum attachment,
enum textarget, uint texture, uint level);
void FramebufferTexture2D(enum target, enum attachment,
enum textarget, uint texture, uint level);
void FramebufferTexture3D(enum target, enum attachment,
enum textarget, uint texture, uint level, uint image);
c) same as (b) but add a dedicated routine for Cubemaps
Question: since we added a Cubemap version, do we need a
Rectangle variant as well?
This gives us:
void FramebufferTexture1D(enum target, enum attachment,
enum textarget, uint texture, uint level);
void FramebufferTexture2D(enum target, enum attachment,
enum textarget, uint texture, uint level);
void FramebufferTextureCubemap(enum target, enum attachment,
enum textarget, uint texture, uint level);
void FramebufferTexture3D(enum target, enum attachment,
enum textarget, uint texture, uint level, uint image);
d) same as (c) but with no texture target parameter
Question: since we added a Cubemap version, do we need a
Rectangle variant as well?
This gives us:
void FramebufferTexture1D(enum target, enum attachment,
uint texture, uint level);
void FramebufferTexture2D(enum target, enum attachment,
uint texture, uint level);
void FramebufferTextureCubemap(enum target, enum attachment,
uint texture, enum face, uint level);
void FramebufferTexture3D(enum target, enum attachment,
uint texture, uint level, uint image);
e) one FramebufferTexture routine with additional arguments
passed in via another routine.
There are no "ignored" arguments in this routine.
The arguments which would be "ignored" by this function
are passed in as selector state by a separate function.
These could be specified as a FramebufferParameter
(implying that they are stored as framebuffer state), or
as a piece of context state that is copied into the
framebuffer attachment point at FramebufferTexture time.
Of the two, context state is much more desirable since
ARB_render_texture made the mistake of putting the
selection state in the pbuffer, and this has real
usability issues for multicontext applications.
This gives us (two routines)
void FramebufferTexture(enum target, enum attachment,
uint texture, uint level);
and
void FramebufferParameter(enum target, enum pname, uint param);
where pname can be one of
GL_{attachment}_TEXTURE_CUBEMAP_FACE
GL_{attachment}_TEXTURE_3D_IMAGE
and param represents the cube map face or z-slice image.
Also, option (e) raises 2 questions:
1. Since the rest of the selection state would come in
through another function, we have to ask when can
these selector state variables be changed?
We had previously decided that we want to pass
selection state in atomically with the attachment
request. To be consistent with this earlier
decision, this would imply that these variables could
not be changed dynamically but would be "snapshotted"
into the framebuffer attachment point at at
FramebufferTexture time. This snapshot could be
thought of as similar to the way ActiveTexture works.
This is also similar to the snapshot of the
transformed raster pos vertex that occurs at
glRasterPos time. It is a copy of one piece of state
into another piece of state, not just a "switch" than
can be updated later that indicates where other state
should be stored.
2. Is the rationale to consolidate FramebufferTexture
from 3 routines to 1 also a reason to consolidate
FramebufferTexture and FramebufferRenderbuffer into a
single attachment routine? I.e., should there just
be one routine called FramebufferAttachableImage()?
If we did this, then we could also move <level> out
of the argument list and rename the function to,
perhaps, FramebufferAttach.
void FramebufferAttach(enum target, enum attachment,
enum objectType, uint name);
and we'd need to create another enum for
FramebufferParameter
GL_{attachment}_TEXTURE_LEVEL
or, avoiding the use of verbs in the function
name, perhaps:
void FramebufferAttachableImage(enum target, enum attachment,
enum objectType, uint name);
Rationale:
(a) was discarded because it was not very extensible in the
event we need to add additional texture selection state in
the future (for instance, what if we add TEXTURE_4D
targets?)
(c) and (d) were discarded because the introduction of a
special cubemap routine was undesirable since we were
considering issue in an attempt to *reduce* the number of
entry points. Additionally, (d) was discarded because it
was felt the texture targets were still required.
(e) was discarded because the intent was that attachment
(and the consequent framebuffer validation) was a
"heavy-weight" operation. By using a separate routine to
set part of the attachment state, developers may be
incorrectly encouraged to assume some attachment state could
be changed more easily than others. It was felt it wasn't
worth this possible misunderstanding just to save some
function entry points.
In the end, it was determined that (b) was the lesser of two
(five?) evils. (b) also has precedent in the specification
of texture images via gl{Copy}TexImage. Finally, (b) is
pretty clearly extensible to new attachment routines for
future object types.
(12) Do we need a "format group" or "format restriction" API?
RESOLUTION: Yes, but put it in a separate extension for
reasons of schedule.
This extension introduces the ability to construct a
collection of logical buffers using images of various
formats into a framebuffer in a very flexible manner. It is
by design more flexible than used to be possible to do by
querying for available pixel formats in the window-system
glX/WGL/agl API's. As a result, it is possible to construct
a framebuffer that is actually not supportable by the
implementation and the reasons for the configuration being
unsupportable are entirely implementation dependent.
This is why we originally added the CheckFramebufferStatus
API. So that the application at least has the ability to
determine that a particular, otherwise legal, configuration
of framebuffer attachments actually will not work on this
implementation.
However, this extension does not provide any very helpful
mechanism to find out why things are not supported or what
to do to reconfigure the attachments into a supported
configuration.
This is a very difficult problem to solve. glX/WGL/agl
solved this problem by allowing the application to specify a
request for a configuration and letting implementation
provide a "best match". Additionally, glX and WGL also
allow for the enumeration of all possible supported
configurations.
Various schemes like these were considered but they were all
quite complicated (possibly as complicated as the windowing
system API's we are trying to replace). Consequently, we
decided to investigate some additional approaches.
One of these approaches is to specify "allocation and usage"
hints prior to the routines which allocate buffers
(TexImage/RenderbufferStorage) that will somehow indicate an
intended configuration and then let the implementation use
this additional information when selecting internal formats
for textures and renderbuffers. The GL already has the
freedom to pick any internal format it wants for textures
and renderbuffers (subject to invariance requirements), and
so we would like to leverage this freedom and influence the
choice with an additional channel of information.
One example, though not the only one, is some API to let the
application specify it would like to be able to use a color
buffer, depth, and stencil buffer. The implementation would
take advantage of this information when allocating textures
and renderbuffers and only choose internal formats for
color, depth, and stencil textures and renderbuffers that
could be guaranteed to be used together. For instance, the
user could call:
FormatRestriction(GL_COLOR | GL_DEPTH | STENCIL);
or perhaps
FormatRestriction(GL_32_BITS_COLOR_DEPTH_STENCIL);
and then when the user called TexImage with a color buffer,
the GL would only pick color formats that could definitely
be used with depth and stencil buffers. The effect of this
API would be to "restrict" the avaible choices to the GL to
the subset of compatible formats. In this way, the
possibility of encountering an implementation-dependent
reason for failing "framebuffer completeness" would be
greatly reduced or perhaps entirely eliminated.
In any event, specifying this "FormatRestriction" API was
going to take additional time and we wished to get this base
EXT_framebuffer_object specification done and shipping as
soon as possible. So we agreed to defer this "format
restriction" API specification to a later extension, with
the intent to develop this API or some other solution to
this problem as soon as possible.
(13) Do we need intrinsic buffers in addition to renderbuffers?
RESOLUTION: no
When intrinsic buffers were initially proposed, the format
and dimensions of an intrinsic buffer could mutate in order
to provide compatibility with the other images attached to a
framebuffer object. After much debate and a series of
votes, intrinsic buffers had lost both of those properties.
(See issue 36.) In the end the working group decided that
the crippled form of intrinsic buffers do not provide enough
added value to justify their existence.
(14) Is it necessary to require that all the logical buffers of a
framebuffer object have the same dimensions?
RESOLUTION: Yes. Matching dimensions are required for
simplicity. If the dimensions do not match, the framebuffer
object will not be "framebuffer complete".
It could be useful to use a single large depth buffer when
rendering to many textures of several different sizes. This
is something that could be added later by a layered
extension that relaxes the matching dimension restriction.
Supporting heterogeneous sized logical buffers requires
defining where in a larger buffer the smaller results are
written, and deciding what guarantees can be made and what
should be left undefined.
(15) What happens when TexImage or CopyTexImage is called on a
texture image that is attached as an image of the
currently bound framebuffer object?
RESOLUTION: resolved, {Copy}TexImage will redefine the
texture image, which can affect the completeness of the
framebuffer to which it is attached, and possibly cause the
currently bound framebuffer to start failing the framebuffer
completeness test.
As far as {Copy}TexImage (or RenderbufferStorage) are
concerned, there is nothing "special" about a texture image
(or renderbuffer) attached to a framebuffer object. Attempts
to redefine attached images in this manner should succeed.
However, if the redefined image is no longer appropriate for
the relevant attachment point in the framebuffer it is
attached to, then it's possible the framebuffer may start
failing the framebuffer completeness test.
Another option that was considered involved having TexImage
and CopyTexImage result in INVALID_OPERATION and do nothing
when the target texture is bound for render-to-texture. This
idea was rejected because, in the multicontext case, one
context could change the attachments of a shared framebuffer
and cause another context to suddenly start generating
errors on {Copy}TexImage calls. This extension has tried to
avoid introducing asynchronous generation of gl errors.
Still another option that was considered was "orphaning" the
old texture memory such that it could still be used as a
framebuffer attachment but the texture would get newly
allocated storage. However, this implied a side-ways copy
of the texture object memory or the image for its continued
use as a framebuffer-attachable image, and was therefore
rejected.
For the purposes of comparison, consider that
ARB_render_texture faced a similar question and resolved it
by implicitly unbinding the texture from the pbuffer when
TexImage is called.
(16) What happens when TexImage or CopyTexImage is called on a
texture object that is attached as an image of a
framebuffer object that is not bound to the current context?
RESOLUTION: resolved, {Copy}TexImage will redefine the
texture image, which can affect the completeness of the
framebuffer object to which it is attached. When the
framebuffer object is bound to the context, it may start
failing the framebuffer completeness test. If the
framebuffer object is bound in another context at the time
{Copy}TexImage is called, then the framebuffer object may
start failing the framebuffer completeness test in the other
context.
The rationale for this decision is the same as for issue
(15).
However, since in this case the relevant framebuffer is not
current, there is no guarantee that this framebuffer
revalidation or invalidation will happen until the next time
the framebuffer is bound to a context.
The texture (or renderbuffer) state is changed immediately,
regardless of whether the texture image (or renderbuffer) is
attached to a framebuffer object. However, a context other
than the one issuing the {Copy}TexImage operation might not
notice the state change until after it has (re)bound the
framebuffer object or reattached the texture image.
This is intended to be similar to what happens in the
multicontext case when the state of a shared texture object
is changed by another context. There is no guarantee that
texture state change will be visible in the current context
until the current context binds the texture object again.
(17) Why is render to vertex array missing?
RESOLUTION: Render to vertex array is separate functionality
from render to logical buffer or render to texture. RTVA
can be added as a separate extension. The framework is
general enough to support more than one way of adding RTVA,
without deciding today on the details of a particular RTVA
implementation.
One idea is to define a way to interpret a vertex array or
buffer object, which is inherently byte-oriented linear, as
a framebuffer, which is inherently component-oriented and
dimensioned, and then call FramebufferArrayEXT like this:
FramebufferArrayEXT(FRAMEBUFFER_EXT, COLOR, buffer_obj);
Another idea is to define a general way to interpret a
component-oriented dimensioned image, such as a texture or a
color buffer, as a byte-oriented vertex stream. Using this
approach one would render vertex attributes to a
renderbuffer, to a texture image, or to an AUX buffer, and
then use the image data directly as a vertex array.
There is controversy over which RTVA method(s) should be
supported. One goal of EXT_framebuffer_object is to ship
render-to-texture and render-to-logical-buffer functionality
today while leaving the door open to add one or more RTVA
solutions in the future.
(18) What function should perform the action of attaching a texture
image to a framebuffer for rendering purposes?
RESOLUTION: The new FramebufferTexture*EXT functions perform
this action.
Options that were considered include overloading
BindTexture, using a FramebufferParameter function, and
adding a new function.
BindTexture is problematic because it creates a new texture
object with default state if the name is previously unused,
but the default state has no dimensions, dimensionality, or
format.
One reason that FramebufferTexture*EXT was well-received is
because it sets, in one atomic operation, all framebuffer
attachment state for both texture image and renderbuffer
type of attachments. Given the polymorphic nature of
framebuffer-attachable images, this guarantees that all
framebuffer attachment state is in a consistent
configuration, without having to define confusing precedent
rules between competing (texture image and renderbuffer)
pieces of framebuffer attachment state, or having to create
enables (either a tri-state enable or separate enables again
with precedence) to select texture image or renderbuffer
attachment state as the "active" set of state.
This decision also makes it simpler to specify how a
framebuffer-attachable image is detached from a
framebuffer--it would be confusing if detaching a texture
image resulted in *attaching* a renderbuffer simply because
texture image attachment state takes precedence over
renderbuffer image attachment state.
(19) What should happen if the texture argument given to
FramebufferTextureEXT is an unused texture name? And
similarly, what should happen if the renderbuffer argument
given to FramebufferRenderbufferEXT is an unused renderbuffer
name?
RESOLUTION: resolved, (a) this is an error.
Options included:
a) throw an error at Framebuffer{Texture|Renderbuffer}
b) texture/renderbuffer is created just like
Bind{Texture|Renderbuffer}
c) no error, but the framebuffer cannot be "framebuffer
complete" until a texture/renderbuffer by that name
has been created and satisfies the rules of
framebuffer completeness.
This is interesting because on the one hand we might like to
adopt the model that we simply catch all the invalid state
combinations when determining framebuffer completeness,
i.e., option (c). This has a certain consistency but then
what does it mean to call FramebufferTexture{1D|2D|3D} when
the target of the texture name is not yet known? How should
the other arguments to those calls be validated?
Option (b) was rejected as it would introduce a second way
to create a texture/renderbuffer object. I.e., both
BindTexture and FramebufferTexture would create the texture
object.
Since there are "target aware" FramebufferTexture{1D|2D|3D}
calls, the app already has to know the target prior to
calling FramebufferTexture. Also, the texture target of a
given object is immutable once set. An app can not set it
and then change it later so this is really just an issue
with the order in which they call the relevant functions.
Consequently, requiring that the user call BindTexture prior
to calling FramebufferTexture does not seem to be a burden.
So this should be an error, since it's probably a mistake on
the user's part in the first place.
(20) What should happen if the texture argument given to
FramebufferTextureEXT is the name of an existing texture
object, but the texture has no texture image (i.e., TexImage
has never been called)? Similarly what should happen if the
renderbuffer argument given to FramebufferRenderbufferEXT is
the name of an existing renderbuffer, but the named
renderbuffer has no storage (i.e., RenderbufferStorage has
never been called?)
RESOLUTION: resolved, option (c) - no error, but the
framebuffer object cannot be "framebuffer complete" until
the state of the texture image satisfies the rules of
framebuffer completeness.
Same options as issue (19), these include:
a) throw an error at Framebuffer{Texture|Renderbuffer}
b) texture/renderbuffer is created just like
Bind{Texture|Renderbuffer}
c) no error, but the framebuffer cannot be "framebuffer
complete" until the texture image or renderbuffer
satisfies the rules of framebuffer completeness.
This is an issue because you could be attempting to attach a
texture (or renderbuffer) to a framebuffer attachment point
prior to the application having called TexImage (or
RenderbufferStorage) to define the width/height/format of
the framebuffer-attachable image.
At first, this seems similar to issue (19), so we could
throw an error in this case too. It is different for two
reasons however. First, there are default values for the
texture object and renderbuffer object state. Second, the
values of the width/height/format/etc for the texture object
are mutable, unlike the texture target of the texture
object. There is really no difference between the case
where GL uses the default values for an object, and the case
where the user explictly set the state equivalent to the
default values using TexImage (or RenderbufferStorage).
Because this state is mutable, it must be tested anyway when
framebuffer completeness is determined.
Therefore, we simply defer the check for whether the
texture/renderbuffer state is appropriate for the
framebuffer attachment point until determination of
framebuffer completeness. If the state is not valid, then
the framebuffer will not be complete, regardless of whether
or not TexImage/RenderbufferStorage has been used to create
storage for the texture level (renderbuffer).
(21) What happens when DeleteTextures is called on a texture that is
attached to a framebuffer object? Similarly, what happens when
DeleteRenderbuffers is called on a renderbuffer that is
attached to a framebuffer object?
RESOLUTION: resolved, see issue (77)
(22) How do you detach a texture or renderbuffer from a framebuffer
object? Should we use two routines or create a detach routine?
RESOLUTION: resolved, 2 routines
If the user calls either FramebufferTexture with a zero
texture name, or FramebufferRenderbuffer with a zero
renderbuffer name, then the it as if nothing is attached to
the specified attachment point.
There was a concern that having two routines be able to set
the framebuffer attachment state to "none" was confusing.
However, the idea is simply that for any object that can be
attached to a framebuffer, there should be a routine that
can set up the attachment and return the framebuffer to the
default "nothing attached" state.
The implication here is that the default state for
framebuffer attachments is:
attachment object type = GL_NONE, and
attached object name = 0
(23) Should it be legal for the framebuffer state to pass through
invalid configurations? (I.e., depth and color buffer sizes
don't match, etc)
RESOLUTION: resolved, "yes"
It's easier for the application if the render target state
is allowed to pass through invalid configurations when
transitioning between two valid configurations. A
consistency check is defined to determine if a configuration
is valid.
As long as everything is valid at render time, transient
invalid states are allowed.
(24) What happens when you try to draw to a framebuffer that
is not "framebuffer complete"?
RESOLUTION: resolved, rendering is disabled, and an error is
generated. See issue (64) as this issue is essentially a
duplicate of that one.
(25) What should happen on a query of framebuffer state while the
framebuffer is invalid? For instance, what does a query of
RED_BITS return if the currently bound framebuffer is not
"framebuffer complete"?
RESOLUTION: resolved, there's no issue here. Attempts to
query bit depths should return the "real" answers.
For instance, if there's no color buffer attached to the
framebuffer attachment point, then attempts to return
RED_BITS could return zero. If there is a color-renderable
image attached, then RED_BITS would return whatever the
RED_BITS are, regardless of the valid/invalid state of the
framebuffer.
Other options include returning some kind of magic value or
generating an error if the framebuffer is invalid. However,
any "magic value" would simply be a duplicated query for the
framebuffer completeness status. Also, returning an error
would be problematic because another context can make a
framebuffer invalid and we have been trying to avoid any API
in which one context can cause another context to start
generating errors asynchronously.
(26) What happens when you try to read (e.g. ReadPixels) from a
framebuffer that is not "framebuffer complete"? Reads cannot
be "disabled" or "ignored" in the same way that rendering can.
RESOLUTION: resolved, generate a GL error. See issue (65).
Originally this was resolved as "undefined pixels are
generated, but no error"
Initially, generating an error was rejected for a few
reasons. First, it is asymmetric with the behavior for
drawing - when the framebuffer is not complete, drawing is
disabled. We would like to be consistent here. Second,
there are no other cases where ReadPixels or
CopyTex{Sub}Image will generate an error based on the state
of the framebuffer and we didn't want to introduce one.
Third, there is already a pixel ownership requirement in
order to get defined results back from reading the
framebuffer, so if we simply behave as if incomplete
framebuffer fails ths pixel ownership test, then we can
leverage that already specified behavior for reading the
framebuffer.
For these reasons, we initially choose to have reads from an
incomplete framebuffer return undefined pixel values and not
generate a GL error.
However, once we subsequntly resolved issue (64) to say that
rendering with an incomplete framebuffer generates an error,
we decided again for reasons of symmetry that reading from
an incomplete framebuffer should also generate an error.
(And most likely the same error.)
So in the end, we decided that reads (e.g., ReadPixels and
CopyTex{Sub}Image) in this case would result in an error to
be named in issue (65).
See also related issue (73), describing ReadPixels of color
data from a complete framebuffer while READ_BUFFER is NONE.
(27) What happens when you query the number of bits per channel
(e.g., DEPTH_BITS) prior to the consistency check being run
when intrinsic buffers are in use, since implementations are
allowed to select a number of bits for an intrinsic buffer at
consistency check time to give a better chance of a consistent
state being reached?
RESOLUTION: This is not an issue since we don't have
intrinsic buffers, see issue (13). We are keeping this
issue in the issues list just in case we ever go back and
add something like this to a future API.
If we would have retained the intrinsic buffer api (i.e.,
glFramebufferStorage) or if some future API adds it back in,
then one possible resolution of this problem would have been
to simply say that a query of the number of bits prior to
the consistency check being run will produce an answer that
is subject to change.
This is preferable to some other possible resolutions that
have been discussed (e.g., having the query cause a
validation to occur implicitly, thereby "baking" in the
answer) because it is the one least likely to introduce
unexpected side-effects to an operation as seemingly
innocuous as a query.
A possible variant of this proposed resolution would have
been to have the query return a number of bits that is
guaranteed to be less than or equal to the actual number of
bits that will eventually be used. This may or may not be a
useful guarantee. We could have also had the query return 0
or -1 as a signal that the framebuffer is incomplete.
Again, this is all moot since we decided against this style
of intrinsic buffers in this extension.
(28) What should the <image> parameter to FramebufferTexture3DEXT
actually be called?
RESOLUTION: resolved, "zoffset"
This parameter could have been called <image> or <slice>.
<depth> or <zoffset> might also be appropriate. The reason
the answer here is non-obvious is that normally 3D textures
are specified all at once, not one 2D "slice" at a time
(TexImage3D takes one big array that represents all three
dimensions at once, for example), and because texture
coordinates for TEXTURE_3D targets are normalized
floating-point numbers, just as they are with TEXTURE_2D
targets, not integer indices.
The GL uses the term "image" to mean "slice" in a few
instances. For example, pixel unpack parameters
UNPACK_SKIP_IMAGE and UNPACK_IMAGE_HEIGHT describe state
related to the "slices" a 3d texture.
However, in some ways the act of rendering into a texture is
most similar to CopyTexSubImage3D, which also redefines a
texture's contents (but never its format or dimensions) based
on the contents of the framebuffer. The "zoffset" parameter
to CopyTexSubImage selects a particular 2D image (depth
"slice") of a 3-dimensional texture. "zoffset" is a
coordinate, and the parameter to FramebufferTexture3DEXT is
also a coordinate. "Image" typically refers to an array of
pixels.
We already use the term "image" throughout this extension to
talk about 2d arrays of pixels beyond their use in 3D
textures. It is a little confusing to overload "image" to
also mean Z coordinate in FramebufferTexture3DEXT.
For the sum of these reasons, we decided "zoffset" is a
better name than "image", for the parameter to
FramebufferTexture3DEXT.
(29) Should GenerateMipmap functionality be included in this
extension or put in it's own extension?
RESOLUTION: resolved, yes, include this functionality
It is arguably useful separately, i.e., without all this
machinery. However, it's also kind of required here to have
some kind of way to deal with the interaction with
SGIS_generate_mipmap. Probably we should just include it
here. (maybe also a separate extension?)
It's easier to define when automatic mipmap generation
happens for a traditional non-rendered texture than it is
for a texture that is modified by rendering-to-texture. If
GENERATE_MIPMAP were to cause a rendered-texture's mipmaps
to be automatically generated, presumably generation would
occur when either the texture is detached from the
framebuffer or when the framebuffer is unbound. If neither
of these events occur, should automatic mipmap generation
also occur when the texture is bound to a texture unit (of
same or different context?)
It's believed the recommended way of achieving maximum
performance using this extension is to make all attachments
during initialization, and then not change attachments in
the steady state. This reasoning is, after all, a major
reason for introducing framebuffer objects. If an
application does not detach textures from framebuffers, then
what event triggers mipmap generation? An explicit
GenerateMipmap works well here.
Would the base level have to actually be modified in order
for mipmap generation to occur? How should "modified" be
defined?
If the application rendered to each level of the texture
before detaching the texture or unbinding the framebuffer,
would automatic mipmap generation happen anyway? (This
implies the application needs to set GENERATE_MIPMAP to
FALSE before rendering to the texture, but maybe that's OK.)
Historical background: One reason for introducing
GenerateMipmap in the context of the original uber_buffers
proposal was that uber_buffers lacked a Begin-time
consistency check, but instead prevented the framebuffer
from ever getting into an inconsistent state (once
validated). Operations such as TexImage that can change the
dimensions and format of a tetxture's levels were disallowed
when the texture was attached to a framebuffer. Since
automatic mipmap generation can change the dimensions and
format of a texture's levels, that meant that automatic
mipmap generation could not be performed in some cases, but
there was no good way to communicate this error to the
application. Hence there really was a need for a separate
GenerateMipmap function. This restriction does not apply
to the current API because the semantics of an incomplete
framebuffer are different now. Nevertheless, we decided to
retain this manual mipmap generation as part of this
extension.
(30) Do the calls to deal with renderbuffers need a target
parameter? It seems unlikely this will be used for anything.
RESOLUTION: resolved, yes
Whether we call it a "target" or not, there is *some* piece
of state in the context to hold the current renderbuffer
binding. This is required so that we can call routines like
RenderbufferStorage and {Get}RenderbufferParameter() without
passing in an object name. It is also possible we may
decide to use the renderbuffer target parameter to
distinguish between multisample and non multisample buffers.
Given those reasons, the precedent of texture objects, and
the possibility we may come up with some other renderbuffer
target types in the future, it seems prudent and not all
that costly to just include the target type now.
(31) What should happen if you call FramebufferTexture{1D|2D|3D}
with a texture name of zero?
RESOLUTION: This will detach the image from the specified
attachment point in the currently bound framebuffer object.
For reference, this reason this is problematic because there
is not really a "texture object zero"
Texture name zero does not define an object but defines
context state (one texture named zero, per target, per
context). The textures referred to by the name zero are
never shared across contexts. So the behavior of
framebuffer objects shared by multiple contexts where each
is attached to the context's texture named zero seems odd at
best, and confusing at worst. As such, it was decided to
not allow a framebuffer to attach to texture named zero.
Another option would have been to make this an error. If we
had done this, then we would need a specific function to
detach a texture from an attachment point. That is, we
would have needed to create something like a dedicated
DetachFramebufferAttachableImage() entry point.
(32) Should there be a renderbuffer object with the name of zero?
RESOLUTION: NO.
By way of symmetry with textures, renderbuffer zero, if it
existed, would not be an object. It would be a
non-shareable piece of the context state. There would be
one renderbuffer named zero per target per context.
If we can't share renderbuffer name zero, then also by way
of symmetry with textures, we would not want to support
attaching renderbuffer name zero to a framebuffer.
So, if it can't be used as a rendering destination, then a
renderbuffer name zero would seem to serve no purpose as a
state container.
However, we'd like to retain the use of name zero in certain
routines with special semantics, particularly for detaching
non-zero renderbuffer objects from the framebuffer and
context. See issue (33).
On implication of this decision is that state
setting/getting routines that operate on the currently bound
renderbuffer should throw a GL error if no renderbuffer is
bound/attached. A similar choice was made in the
ARB_vertex_buffer_objects specification which also had
special semantics for object zero.
Also note, another option considered was making object zero
a full fledged, shareable object just like the non-zero
object names. This was rejected as being too different from
texture/program vbo's/etc., possibly leading to confusion.
(33) What should happen if you call FramebufferRenderbuffer or
BindRenderbuffer with a renderbuffer name of zero?
RESOLUTION: This will detach the image from the
specified attachment point in the currently bound
framebuffer object.
This is resolved exactly the same way as issue (31) was
resolved for textures, and for the same reasons.
Similarly, calling BindRenderbuffer with a name of zero will
unbind the currently bound renderbuffer from the context.
(34) Should there be a way to query a framebuffer object for its
attached texture and/or renderbuffers? If so, how, and
what should be the query result when attached textures or
renderbuffers have been deleted?
RESOLUTION: resolved, yes
In general, OpenGL lets you query settable state, so
we allow this.
To see what this query should look like, see related
issue (51)
This issue also raises the question about what values should
be returned for attached objects if the named objects have
since been deleted. This can happen if the textures were
attached to non-currently bound framebuffers or attached to
framebuffers in other contexts. Three possible solutions
include:
a) Don't support this query.
b) Return zero if no texture has ever been attached.
Return zero if the attached texture has been deleted.
c) Return zero if no texture has ever been attached.
Return the name of the texture that was attached even
though it has been deleted.
Option (a) was rejected as we would like settable state
to be queriable.
So, for this extension originally we choose option (c).
However, we have since decided, in issue (21), that
DeleteTexture and DeleteRenderbuffer will first detach
the texture/renderbuffer from any attached framebuffer
objects *in this context*. In principle, the
application can't tell the difference between the
texture getting deleted now or later, so whether the
texture is actually detached from the current
framebuffer now and other framebuffers when they are
bound, or the texture is actually detached from all
framebuffers at once is moot. In practice, this means
that options (b) and (c) are essentially
indistinguishable for a single context case.
However, it's worth noting that if the texture is
deleted and attached to a framebuffer which is current
in another context, the standard rules about undefined
behavior of state modifcations of shared objects in
other contexts will still applye.
This means that the texture may or may not be detached
(and thus deleted) from that other context's current
framebuffer until the next BindFramebuffer (or
FramebufferTexture/FramebufferRenderbuffer?) in the
other context.
(35) Earlier proposals included a way to create some memory and then
attach it to a texture object. Should this extension include
this feature?
RESOLUTION: no.
This was considered when this extension was intended
to be a more general purpose memory manager. Since this
extension has been retasked to focus in on render-to-X
functionality, this feature was not necessary.
(36) Earlier proposals had renderable memory constructs which could
change internal format or dimensions to meet intra-framebuffer
compatibiltiy requirements of individual vendors' hardware
platforms. Should this extension have these kind of malleable
format objects?
RESOLUTION: no.
Such malleability leads to invariance problems when formats
change. For example, if bits per pixel is decreased then
increased back to the original value, some precision is
lost.
Some IHVs wanted to require format conversion of existing
contents in all cases where the format changes. This sort
of invariance would be an acceptable side-effect. The
suggestion was to think of the action of rendering to a
texture as an extended non-atomic TexImage call. TexImage
is allowed to change the format of an existing texture
image. It was claimed that such intrinsic buffers are more
convenient in many applicaitons than are the explicitly
managed renderbuffers.
Other IHVs expressed a strong opinion against implicit
format conversions, but instead wanted to invalidate the
buffer's contents whenever the format changed. It was
difficult to define the set of operations that might cause
the format to change, so it was difficult to define when the
contents could become invalidated. If the contents were
invalidated by a format change, the API under consideration
made it cumbersome for the application to detect and handle
this condition. In the end, under the buffer content
invalidation approach, application code would not be any
better off than if the appliation instead used the explicit
renderbuffers. For the type of intrinsic buffers that could
not change format and dimensions dynamically, the claim that
intrinsic buffers were more convenient than renderbuffers
was no longer true.
The working group voted for the latter: no implicit format
changes. Instead the format would be immutable once it is
known.
A secondary issue is the question: are the buffer contents
invalidated when the dimensions change, are the contents
scaled, or are the contents are clipped/padded (with some
sort of gravity). This issue could be avoided by requiring
explicit, rather than implicit, resize of intrinsic buffers.
The working group voted for no implicit change in the
dimensions of intrinsic buffers, and finally for the removal
of intrinsic buffers altogether.
(37) In order to abstract hardware dependent compatibility
requirements, this API introduces a function called
CheckFramebufferStatus to check for compatibility prior to
rendering. CheckFramebufferStatus returns a value which
indicates whether or not the framebuffer object is "framebuffer
complete", and framebuffer completeness depends in part on
hardware dependent constraints. The hardware dependent aspect
represents a new concept in OpenGL. Therefore, should an app
be required to call this function to help "enforce" the notion
that apps should be on the lookout for failure?