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?
RESOLUTION: no. Calling CheckFramebufferStatus is not
required.
The group considered requiring a call to
CheckFramebufferStatus after changing framebuffer state or
attachment points in order to "enable" rendering. It was
hoped that requiring a call to CheckFramebufferStatus would
push developers to write code which is more platform
independent. Ultimately though, since the API can't require
applications to actually observe and deal with a validation
failure, that it was not worth it to make this function call
required. There was also feedback from some developers that
requiring this call would be cumbersome and undesirable.
Note, however, that the framebuffer is effectively validated
implicitly at every rendering (and reading) entry point.
These include glBegin, gl{Multi}Draw{Arrays|Elements},
gl{Draw|Copy|Read}Pixels, glCopyPixels, glReadPixels,
glCopyTex{Sub}Image, etc.
Applications are strongly advised to test framebuffer
completeness with CheckFramebufferStatus after setting up or
changing the configuration of a framebuffer object, and to
handle the possible failure cases with a fallback plan that
selects a different set of internal formats of attached
images. See usage example 6. Section 4.4.4.2 lists the
operations that can cause the framebuffer's status to
change.
In addition, a "format group" API, has been proposed as a
means of programmatically determining a set of internal
formats that are guaranteed to be compatible with respect to
framebuffer completeness. This API would be specified in a
layered extension as suggested in issue (12)
(38) Do we need to support multiple render targets, i.e.,
ARB_draw_buffers?
RESOLUTION: Yes.
ARB_draw_buffers is going to be part of OpenGL 2.0 so we'd
better support it.
(39) How should we support ARB_draw_buffers?
RESOLUTION: refactored into the following issues:
(53), (54), (55), (56), and (57)
(40) (How) should we support accum buffers?
RESOLUTION: defer this until (shortly) after this extension.
Accum buffers appears to be very simple to specify and
implement. Basically, we would need to add a new internal
ACCUM format that can be passed to RenderbufferStorage. We
would also need to add an ACCUM attachment point in the
framebuffer that could be used to point to one of these
ACCUM format renderbuffers. A new ACCUM format is needed
because the ACCUM buffer is defined by GL to be signed
floating point value, unlike other internal formats.
Also note, the above solution is the exact same one we are
using for STENCIL buffers as well (i.e., an internal format
enum and an attachment point).
We could also decide if this new ACCUM internal format can
be used with textures in addition to renderbuffers, for
creating images that can be attached to the accum buffer
attachment point.
Supporting accum was deferred for this extension, primarily
for time-to-market reasons, and as it was not critical for
most render-to-texture applications. However, we intend to
work on some kind of "EXT_accum_renderbuffer" extension
shortly.
Since this was deferred, we need to define what happens when
you call the various Accum operations on a non-default
framebuffer object. We considered adding spec language that
would generate an error on Accum operations. However, it
seems like we can simply leverage whatever legacy behavior
is currently defined for when the pixel format has no accum
buffer. This is the case in this extension as we have
defined no way to attach or enable an accum buffer. Chapter
4 on page 188 already says that "If there is no accumulation
buffer, or if the GL is in color index mode, Accum generates
the error INVALID OPERATION", so we don't actually need any
additional language of our own.
(41) (How) should we support multisample buffers?
RESOLUTION: defer this until (shortly) after this extension.
Supporting multisample was deferred for this extension,
primarily for time-to-market reasons and because it's not
entirely clear what is the "best" API for exposing
multisample. However, we intend to work on some kind of
"EXT_multisample_renderbuffer" extension shortly.
Since this feature was deferred, we need to define what
happens when you try to enable multisample on a non-default
framebuffer object. For now we need some way to *not* do
multisampling. This can either be that we set SAMPLES 1 and
SAMPLE_BUFFERS to 0, or we say that
Enable/Disable(MULTISAMPLE) is ignored. This is actually
related to issue (62) - should SAMPLE_BUFFERS change when
using a non-default framebuffer or when attachments change?
When/if we define and export "EXT_multisample_renderbuffer"
extension, this state will again have significance.
A discussion of how we might support this feature follows:
There are several considerations here: First, we'd like
something simple to specify, implement, and use. Second,
we'd like to not delay this extension's approval,
implementation or adoption for this particular feature.
Third, we are trying to replace pbuffer functionality, which
does support multisampling (at least in principle), so we'd
like to not take a step backward in functionality if
possible.
However, this extension is *not* trying to "improve" the
traditional multisample support. If we do anything, we will
simply expose the existing multisample buffer semantics
without causing undue implementation burden.
Finally, if an implementation is currently taking short-cuts
to GL's traditional "per-pixel-resolve" multisample
semantics, we'd like for this extension to continue to allow
the exact same short-cuts (to whatever extent the core GL
spec does or does not allow those short-cuts). If someone
later decides to go an revamp multisampling support in
general, they can update this extension at the same time.
Given the above, it appears that the options include:
A) Don't support it. In other words, you can't use
mulitsampling and EXT_framebuffer_object. The
multisample state is either ignored, or causes the
framebuffer to not be complete, or generates some kind
of error.
B) Create a separate multisample renderbuffer that can be
attached to a new framebuffer attachment point.
The reason that we might need a separate
RESOLUTION_BUFFER is that all renderable color buffer
formats might not be usable for multisampling on all
implementations.
Also, this option would allow multiple framebuffers to
share the storage for multisample buffers under the
control of the application.
Depth sample buffers and stencil sample buffers
wouldn't necessarily need resolution buffers, but that
could be added by some future extension.
This option has several variants:
B1) Create MULTISAMPLE and/or RESOLUTION_BUFFER
internal formats for renderbuffer objects that
can be used with RenderbufferStorage. The
samples buffer and the resolution buffer would be
allocated and attached to the framebuffer
separately. Having them be separate allows the
samples to be deleted after rendering if desired.
One issue with this option is that somehow you'd
need to specify the number of samples maybe using
glFramebufferParameter or
glRenderbufferParameter.
B2) Perhaps, instead of using a single internal
format called MULTISAMPLE, use a set of internal
formats like MULTISAMPLE_1_SAMPLE,
MULTISAMPLE_2_SAMPLE, MULTISAMPLE_4_SAMPLE, etc.
This is problematic for supporting depth/stencil
multisampling unless we want an explosion of
color/depth/stencil multisample internal formats.
It's also problematic if MRT draw buffers need to
be multisampled because we'd need a number of
enums able to support 1 to N draw buffers times
the number of sample patterns we support.
B3) Have RenderbufferStorage always take a number of
samples. We could do this if option (B2) is
insufficient due to the need to support DEPTH or
STENCIL multisampling, which we probably will.
We would then allow the internal format to choose
DEPTH, STENCIL, or RGBA/etc. This is clean but
it means that the user would always need to
specify a number of samples even when the value
is "1".
B4) Pass in a variable length argument list to the
renderbuffer allocation routine, and some of the
arguments would indicate intended usage
(COLOR/DEPTH/MULTISAMPLE) others would indicate
internal format (RGBA/DEPTH24) and others would
indicate number of samples. This is how
EXT_compromise_buffers dealt with this problem,
though people didn't seem to like this variable
length argument list. EXT_render_target didn't
deal with this problem so doesn't offer any
guidance here.
B5) Create a new RENDERBUFFER_MULTISAMPLE
renderbuffer target type and a corresponding
allocation routine, perhaps called
RenderbufferMultisampleStorage(). This is
analogous to how textures have their own
allocation routine per target type
(TexImage1D/2D/3D, etc).
With this option, we could preclude
non-multisample targets from being attached to
non-multisample attachment points as well.
B6-B10) Any of the above options can be implemented
with either a single monolithic mulitsample
buffer that contains the samples for all draw
buffers, depth and stencil and a single
attachment point, *OR* with independent
multisample buffers for each draw buffer and
depth and stencil and independent attachment
points for each.
C) Use some kind of "behind the scenes" mulitsample buffer.
This option also has several variants:
C1) An "implicit" multisample buffer that is simply a
property of the framebuffer object. Each
framebuffer object could have its own multisample
buffer(s). Multisampling would be enabled with
some kind of FramebufferParameter call. This
implies that each framebuffer has memory
allocated with it. It further implies that the
contents of the multisample buffer are
framebuffer state and are thus retained with the
framebuffer object.
C2) We don't say anything except that we say the
value of the glEnable(MULTISAMPLE) is still
respected and we render as directed. This is
similar to (C1) but we don't go so far as to say
that the multisample buffer(s) is/are retained
per framebuffer object. In other words, a call
to BindFramebuffer() and changes to framebuffer
attachments may or may not retain multisample
buffer contents. Valid implmentations of this
would include a multisample buffer per
framebuffer or one per context.
D) something else (hopefully simpler?)
(42) What set of framebuffer targets should the initial extension
support?
RESOLUTION: resolved, (D) single target
Basic possibilities include:
(A) DRAW_AND_READ_FRAMEBUFFER_EXT
(B) DRAW_FRAMEBUFFER_EXT
READ_FRAMEBUFFER_EXT
(C) DRAW_FRAMEBUFFER_EXT
READ_FRAMEBUFFER_EXT
DRAW_AND_READ_FRAMEBUFFER_EXT
(D) FRAMEBUFFER_EXT
The fundamental question is: must framebuffer binding points
mimic the expressiveness of the window-system function
MakeContextCurrent, which is described in the glX spec and
the ARB_make_current_read extension?
It was not immediately clear how to specify the distinction
between a READ and a DRAW framebuffer in the context of the
existing read/draw buffer semantics, given that this
extension relaxes the "compatibility" requirement between
read and draw drawables. How would the value of RED_BITS
for the read framebuffer be queried if it is different than
the value of RED_BITS for the draw framebuffer? What
exactly is the set of implementation dependent state (see
the "Implementation Dependent *" state tables in chapter 6)
that can differ between read and draw framebuffer objects?
When using MakeContextCurrent, the context's and drawable's
FBconfig (or pixel format) must be "compatible" or else the
results are implementation dependent. But
EXT_framebuffer_object cannot afford to swing such a large
"undefined" stick, because it is more likely that
framebuffer objects are incompatible in this sense, and
because the "pixel format compatility" of a framebuffer
object is dynamic--by changing attachments or redefining the
internal format of an attached texture image.
The value added by ARB_make_current_read through
MakeContextCurrent is less relevant to
EXT_framebuffer_object. EXT_framebuffer_object enables
rendering to a texture, and textures are objects with a
clearly defined mechanism for use as the source of a pixel
copy: rather than using CopyPixels to move pixels from the
READ_BUFFER to the DRAW_BUFFER(s), an application can simply
use the source data as a texture and then draw a
screen-aligned textured quad to the framebuffer.
Additionally, adding separate DRAW and READ bindings in the
future is pretty straightforward. One solution would be to
say that FRAMEBUFFER_EXT is the DRAW framebuffer, and name
the new READ framebuffer FRAMEBUFFER_READ_EXT. Add a new
BindFramebuffer-like function which takes two framebuffer
names--one for DRAW and one for READ. The current
BindFramebuffer function binds a single object to both
FRAMEBUFFER_EXT and FRAMEBUFFER_READ_EXT.
So, we defer the additional targets until need has been
proven, and go with the simpler option (D) for now.
(43) In order for a framebuffer object to be "framebuffer complete",
must all textures attached to the framebuffer be mipmap
complete (or mipmap cube complete if cubemap texture)?
RESOLUTION: resolved, no
The reason this is a consideration is that some
architectures require framebuffer-attachable images to be
located in graphics memory when rendered to, and it may be
more convenient to allocate and store a texture in graphics
memory only if the texture is mipmap (cube) complete--i.e.,
the size and format of all levels are consistent in the
normal sense of texture compeleteness.
However, since framebuffer attachment points only really
deal with single images of a texture level, it seems
excessive to require the state of the other levels of a
texture to affect the validty of the framebuffer object
itself.
Addtionally, the same difficulties around "incomplete"
textures already apply to traditional CopyTexSubImage, and
we have been trying to make the render-to-texture semantics
similar to CopyTexSubImage.
Therefore, we chose not to treat render to texture any
differently than CopyTexSubImage and do not require that the
attached texture is mipmap (cube) complete.
(44) What should happen if a texture that is currently bound to the
context is also used as an image attached to the
currently bound framebuffer? In other words, what happens if a
texture is used as both a source for texturing and a
destination for rendering?
RESOLUTION: resolved, (b2) - results are undefined because
the framebuffer is not "framebuffer complete".
Originally this was resolved as causing framebuffer to fail
the completeness test--i.e., rendering would be disabled (b1)
As background, the reason this is an issue in the first
place is that simultaneously reading from, and writing to,
the same texture image is likely to be problematic on
multiple vendors' hardware without paying performance
penalties for excessive synchronization and/or data copying.
There are, however, certain cases where this functionality
would arguably be useful, supportable, and well-defined. In
particular, we can consider the case of custom mipmap
generation using one level's image as source data to render
into other levels of the same texture.
So, at a minimum, we would like to support rendering to a
currently bound texture object if the source texture object
has the BASE_LEVEL and MAX_LEVEL texture parameters set such
that the level being used as a framebuffer-attachable image
is excluded from texture fetches.
This was our original rationale:
a1) is problematic because one context could modify the
base/max level on a shared texture causing another
context which is using the texture as a destination to
throw an error. This idea was rejected as it
essentially meant that the error would need to be
thrown at render timer which people found unacceptable.
b1) has the same kind of multicontext behavior but no
error. One context can cause a framebuffer shared in
another context to become invalid, but this is already
true and can happen for a variety of reasons if the
participating framebuffer-attachable images and/or
framebuffer attachments are modified by either context.
At the time, we also considered the following
questions: should the specification require the
framebuffer to fail the framebuffer completeness test?
Or is the framebuffer simply "allowed" to not be
complete in this case? The latter choice would imply
that the framebuffer might still be considered
"framebuffer complete" on some implementations. See
issue (46)
c1) is the easiest to specify and has an advantage that
some implementations may be relying on this behavior
already. However, this was rejected as it is the least
portable of the three options.
We originally chose option (b1), though we considered that
later on, individual hardware vendors may offer layered
extensions that change this "framebuffer completeness"
failure into a success with either defined or undefined
rendering behavior.
However, this issue was re-opened becaues the subsequent
resolution of issue (66) was that there should be no
"context-dependent" reasons for framebuffer incompleteness.
If we had stuck with option (b1), then we would be making
the framebuffer completeness predicated on a piece of
context state (the current texture binding). Consider the
case where texture T is attached to a framebuffer. Then
this would have meant that a framebuffer could be complete
in one context (that didn't have texture T bound as a
texture) and incomplete in another context (that did have
texture T bound).
When reconsidering this issue, we realized that we would not
throw an error at Begin time without disabling rendering, so
we really only considered the following revised set of
options:
a2) throw an error and disable rendering, but don't
affect framebuffer completeness
b2) the behavior is undefined
The issue was resolved the second time as:
b2) Undefined behavior
Another option that was briefly considered was to make this
another type of error (unrelated to trying to render with an
incomplete framebuffer). However, part of the rationale for
throwing an error at glBegin time when trying to render with
an incomplete framebuffer was that if you already have to
test for framebuffer completeness, then throwing an error is
no additional implementation burden. Yet, since it was
decided that the "texture-from-destination" condition is not
part of framebuffer completeness - issue (66) - then it is
an additional burden to perform the
"texture-from-destination" check just so that an error can
be generated. The concern was some implementations might
not need to check for this case at all and we didn't want to
burdern those implementations with an additional Begin-time
error check.
Also, for what it's worth, if we had left the
"texture-from-destination" case in the framebuffer
completeness test then any language describing how
framebuffer completeness is affected when a currently bound
texture is used as both source and destination needs to be
explicit that the texture has to be currently bound *and*
enabled. For instance, consider the case where a user has a
cubemap texture object name N bound to unit X and a 2D
texture object name M also bound to unit X. What if the
user would like to use the 2D texture M as a source while
rendering to the faces of the cubemap texture N? We would
like to support this scenario, so the language about a
currently bound texture object would have needed to take the
target into account. And to make matters more interesting,
this means we would have needed to take texture enables and
fragment shaders into account in this decision. In the end,
we decided that "context-state" would not affect the
defintion of framebuffer completeness we avoided this
complexity (or at least moved it out of the framebuffer
completeness test).
(45) Are framebuffer configurations with no color attachments allowed?
RESOLUTION: resolved, yes
The reason this is an issue is that the GL spec assumes
there is always a color buffer. If a framebuffer with no
images attached to any of the color buffer attachment points
can be "framebuffer complete", then the core GL spec will
need to be modified to relax the assumption that a color
buffer always exists.
However, since one of the possible likely uses of this
extnesion is to support depth texture rendering and stencil
rendering for shadowing techniques, it seems like requiring
an unused "dummy" color buffer in some cases is both
inconvenient and a waste of memory.
Therefore, framebuffers do not require color attachments to
be valid. Perhaps though we should require that a
framebuffer with *no* attachments is invalid.
It also should be stated that attempting to render without
the "appropriate" buffers attached needs to be defined. For
instance, presumably, for depth rendering with no depth
buffer attached, the depth test is disabled, as it is in
traditional GL.
(46) In the framebuffer completeness criteria, this extension
introduces the idea that rendering can fail for implementation
dependent reasons. Framebuffer completeness also considers
implementation *independent* reasons for failure.
Do we need to make special distinction between the cases where
a framebuffer is not complete because of implementation
dependent or because of implementation indepenent reasons?
RESOLUTION: resolved, yes, though this is really tied into
how we resolve the minimum requirements for supporting this
extension. See issue (61)
Examples where a framebuffer may be incomplete on some
implementations but not others include:
- 16 bit z-buffer used with 8 bit stencil buffer
- 32 bit color buffer with 16 bit depth buffer
- others?
Examples where framebuffer MUST be incomplete on all
implementations include:
- color-renderable image attached to a non-color
attachment point
- depth-renderable image attached to a non-depth
attachment point
- stencil-renderable image attached to a non-stencil
attachment point
- all images attached to a framebuffer do not have the
same dimensions
- multiple render targets of different bit depths
- texture image attached to the framebuffer is part of a
currently bound and enabled texture and the image is
within the range of mipmap levels that can be fetched
by rendering.
To make this determination we need to describe the criteria
we should use to determine whether a framebuffer *can* or
*must* be incomplete.
The arguments for putting state vectors into the "can" fail
case is that a later extension can come along and simply
relax those portions of the framebuffer completeness
definiton with no additional API. State vectors classified
as "must" fail cases would at least require the later
extension to add an additional enable to start passing.
(47) Certain state-modification operations can cause a change to the
validated state of a framebufffer. (I.e., can make a
framebuffer that was complete become incomplete, or
vice-versa). Do we want to list exactly which
state-modification routines can cause this to happen? If so
what is the list?
RESOLUTION: resolved, the answer is: yes we want to
delineate exactly which routines can cause validation state
changes.
Currently any routine which changes any of the following
state can potentially cause framebuffer completness to
change:
framebuffer state
state changes to attached objects
currently bound fragment program
texture enable state
The list of operations that can cause framebuffer a change
to framebuffer completeness are spelled out in section
4.4.4.2.
(48) What information should be returned from
CheckFramebufferStatusEXT()?
New RESOLUTION: resolved: 8 possible enum values, see issue
(55)
Previous RESOLUTION: resolved, return one of three enumerated values:
1. GL_FRAMEBUFFER_COMPLETE_EXT
2. GL_FRAMEBUFFER_UNSUPPORTED_EXT
3. GL_FRAMEBUFFER_INCOMPLETE_EXT
where the three values mean the following:
1. framebuffer is complete and supported
2. framebuffer is not supported for implementation *dependent* reason
3. framebuffer is incomplete for implementation *independent* reason
We considered the following two sets of enums:
Set 1:
GL_FRAMEBUFFER_COMPLETE_EXT
GL_FRAMEBUFFER_NOT_COMPLETE_EXT
GL_FRAMEBUFFER_NOT_SUPPORTED_EXT
Set 2:
GL_FRAMEBUFFER_COMPLETE_EXT
GL_FRAMEBUFFER_INCOMPLETE_EXT
GL_FRAMEBUFFER_UNSUPPORTED_EXT
New resolution is Set 2.
NOTE: In order to fully resolve issue (55), we expanded this set
of enums to identify all of the implementation-independent
causes for a failure of the framebuffer completeness test.
Originally, we had decided to have a query where the
query returns one of three possible values
One possible set of names that could be returned included:
FRAMEBUFFER_COMPLETE, and
FRAMEBUFFER_HW_DEPENDENT, and
FRAMEBUFFER_HW_INDEPENDENT
How much information we return from CheckFramebufferStatus
is a function of how we expect the return value to be used.
A framebuffer object that is not complete for implementation
*indepednent* reasons is really an indication of a
programming error (like mismatched sizes) and should only
occur during development phase of an application. The
correct response to this failure is to modify the
application to fix the bug. After application development,
a framebuffer object that is not complete for implementation
*dependent* reasons is possible. However, it's not yet
clear whether we can easily characterize these reasons for
failure in a programmatic fashion that would really offer
the application enough information to do something different
at runtime. Perhaps a human readable info log, intended
just as an application debugging aid, would be more
appropriate.
We also considered whether we needed two separate queries:
One that queried whether the framebuffer was complete
according to the spec, and one that queried whether the
framebuffer was supported. This was a little problematic as
it might not be possible to answer the
"IsFramebufferSupported" query until the framebuffer was
complete. A possible solution would have been to return
UNKNOWN from the "IsFramebufferSupported" query until the
"IsFramebufferComplete" query returned TRUE.
In any event, we decided a single query was a simpler
solution.
In addition, the proposed "format group / format
restriction" API (see issue 12) should make the
implementation-dependent framebuffer incomplete case much
less likely (and perhaps impossible) to occur.
Note that if a framebuffer's state violates more than one of
the framebuffer completeness rules described in section
4.4.4.2, then it is undefined which of the enumerated value
corresponding to one of the violated rules will be returned
by CheckFramebufferStatusEXT. Since the initial state of a
framebuffer violates multiple rules from section 4.4.4.2,
it is therefore undefined exactly which value is returned if
CheckFramebufferStatusEXT is called while bound to a newly
created framebuffer object.
(49) When this extension is used in conjunction with MRT (multiple
render targets), it would naively be possible to create a
framebuffer that had different color bit depths/formats for
various color attachment points. Should this be allowed?
RESOLUTION: resolved, no, not in this extension.
A soon to follow extension may add this feature.
This feature could be supported by simply not requiring that
all of the FRAMEBUFFER_COLOR_ATTACHMENTn images share the
same internal format. We decided against doing so, however.
ARB_draw_buffers and OpenGL-2.0 do not provide any mechanism
to support rendering to multiple color buffers of different
formats. Consequently, we chose not to extend OpenGL in
this manner as part of the EXT_framebuffer_object extension.
Presumably, a future layered extension could easily add this
feature. There are some open questions about exactly how
this might work. For instance, what should a query of
RED_BITS return if the attached color-renderable images have
different formats? In any event, we leave the details of
rendering to differently formatted MRT for a future
extension to define.
(50) This extension introduces the concept of attaching one GL
object (texture, renderbuffer) to another GL object
(framebuffer). In many ways this situation is analogous to a
previously poorly specified situation where a GL object could
be attached to multiple contexts and the issues this raises
with deletion and state propogation are similar. Several
issues resolutions have been predicated on the assumption that
as we specify this container/member relationship, the
generation of GL errors should never be triggered in one
context based on the asychronous actions of another context.
Is this a valid premise?
In other words, should we be using the prevention of
asynchronously generated GL errors as a design constraint?
RESOLUTION: resolved, no.
We didn't officially decide on this as a design constraint.
However, we essentially decided it by proxy. We decided in
issue (26) and (66) that an incomplete framebuffer can cause
GL errors on rendering or reading the framebuffer.
Consequently, this means a framebuffer shared by two
contexts can be made incomplete by either context, and
therefore each context can effectively cause the other
context to start generating errors asynchronously.
We would expect that the state of framebuffer completness,
like all the state of all shared objects, is not
"guaranteed" to show up in another context until that
context makes an "atomic" request to the server (like a
BindFramebuffer for instance). Until that point, it is
undefined whether the state change will show up in the other
context, just like any state change made on a shared texture
object.
(51) What api should we use to query the attachments of
the currently bound framebuffer?
RESOLUTION: resolved, (b)
This is an issue because the relevant state
for a specific attachment point is a function
of the type of object attached to that that attachment point.
The attachment point state needs to select a
an image from an object which may have
a collection of images, for instance
the faces of a cube map texture.
This introduces a kind of "polymorphism" into the
framebuffer attachment point that is problematic
for queries.
We have a few options:
a) Some kind of single atomic query that
returns a variable number of values in an array:
GetFramebufferParameteriv(enum target,
enum pname,
int* params);
where
<target> = a framebuffer target
<pname> = {attachment_point}
Upon success "params" will contain an array of
values where
params[0] = {NONE | TEXTURE | RENDERBUFFER}
if params[0] == TEXTURE then
params[1] = texture object name
params[2] = level
params[3] = face
params[4] = image
else if params[0] = RENDERBUFFER then
params[1] = renderbuffer name
Elements of the params array not explicitly defined
above will have undefined values.
One problem with (a) is that we would potentially also
need a query to identify how many state variables will
come back in this query. Consider the case where in the
future we add a new attachable object type that needs
more selections tate or even add new selection state to
existing object types. Applications coded to expect a
maximum of n values returned today may break in the
future unless they have a way to dynamically learn how
many attachment state params will come back from the
query.
b) individual queries for all the possible attachment
state values.
We create a new routine to add a new <attachment>
argument, otherwise we'd have an explosion of
permutations of attachment points and possible attachment
selection state values
This could look like
void GetFramebufferAttachmentParameteriv(enum target,
enum attachment,
enum pname,
int *param);
where
<target> = a framebuffer target
<attachment> = {attachment_point}
<pname> = one of
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
Upon success, param will be filled out as follows:
if pname is FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
then param will contain one of:
{ NONE | TEXTURE | RENDERBUFFER },
else if pname is
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, and
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT = TEXTURE,
then param will contain:
{ name of attached texture }
else if pname is
FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, and
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT =
RENDERBUFFER, then param will contain:
{ renderbuffer object name }
else if pname is
FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, and
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT = TEXTURE,
then param will contain:
{ selected mipmap level of attached texture }
else if pname is
FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
and FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT =
TEXTURE, then param will contain:
{ selected face of attached cube map texture }
{ 0 if texture target is not TEXTURE_CUBE_MAP }
else if pname is
FRAMEBUFFER_ATTACHMENT_TEXTURE_ZOFFSET_EXT, and
FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT = TEXTURE,
then param will contain:
{ selected z-slice/image of attached 3D texture }
{ 0 if texture is not 3-dimensional }
otherwise, param will contain the value 0.
One problem with option (b) is that it is a little
heavy-handed as every piece of state needs its own query
and enum
Given the above choices, and the problems of extending option
(a) in the future, (b) is probably the better of the two
choices. It really only adds a few enums, and though it does
require an independent function call to obtain each piece of
state, this is well-precedented behavior throughout GL.
(52) Should manual mimpap generation via GenerateMipmap apply to
textures regardless of whether they are attached to framebuffer
objects? Should automatic mimpap generation apply to all
textures regardless of whether they are attached to framebuffer
objects?
RESOLUTION: resolved, (a) - both apply to both.
This is an issue because the introduction of GenerateMipmap is
intended both to address long standing complaints about the
existing "automatic" mipmap generation API and to provide a
clear trigger for render to texture API's to know when to do
the mipmap generation.
These API's could be considered completely orthogonally. It's
clear how they could interoperate. The question is should they
interoperate, or should one supercede the other?
There are a couple of ways to address this issue:
a) "automatic" mipmap generation applies always and is
triggered by any gl{Copy}Tex{Sub}Image call if
GENERATE_MIPMAP is set to TRUE. "Manual" mipmap
generation applies always and is triggered by a call to
GenerateMipmap
b) "automatic" mipmap generation applies only
to textures which are not attached to framebuffer
objects, calls to GenerateMipmap on "unattached" textures
are ignored.
"manual" mipmap generation applies only to textures which
are attached to framebuffer objects, the value of
GENERATE_MIPMAP for "attached" textures is ignored
c) Like option (b), but allow GenerateMipmap to
apply to all textures and only let automatic mipmap
generation apply to "non-attached" textures.
d) Create an enable or other piece of state
to toggle between allowing automatic and allowing manual
generation.
We disregarded (d) because it's not clear why an application
that had the freedom to set this new enable bit wouldn't
simply just turn off the legacy automatic mimpap generation
to start with.
Of the remaining choices, (a) is the most "orthogonal". The
intent of adding GenerateMipmap is to provide a cleaner and
saner interface to mipmap generation that we would encourage
developers to use over the automatic method. Given that, it
seems like restricting the "manual" generation to certain
cases doesn't serve that goal, so we wish to allow its use
on any textures, attached or not.
(53) When supporting ARB_draw_buffers, do we need the level of
indirection between fragment color outputs and attached
mages provided in that API?
RESOLUTION: yes
ARB_draw_buffers allows the user to set up an "indirection
table" between the fragment color outputs ("result.color[n]"
in ARB_fragment_program, and "gl_FragData[n]" in GLSL) and
the attached draw buffers (FRONT, BACK, LEFT, RIGHT, etc).
Since EXT_framebuffer_object is creating new non-visible
framebuffer objects for which the legacy attachment points
may not be appropriate, we could consider naming the
attachment points by numerical index (COLOR0 ... COLORn) in
which case we could consider dropping this level of
indirection and allowing the fragment shader to output
directly into the numerically specified COLOR0 attachment
point with no indirection.
However, this indirection is deemed to be useful becaues it
allows the application to redirect the fragment color
outputs without changing either the fragment shader itself
or the current framebuffer attachments, both of which are
believed to be heavier-weight state change operations than
simply changing the indirection table via glDrawBuffers..
Therefore, we elect to retain this level of indirection.
This leaves open the question of what to call the attachment
points. See issue (54).
(54) What should we name the logical buffer attachment points,
bearing in mind the relationship to ARB_draw_buffers?
RESOLUTION: resolved, option (E), which is a modified
version of (C). Specifically, we use the names
COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT,
DEPTH_ATTACHMENT_EXT, and STENCIL_ATTACHMENT_EXT (and any
future attachment points also get the ATTACHMENT suffix).
The reason this is an issue is that prior to
EXT_framebuffer_object, the names of the various color
logical buffer "attachment points" were heavily influenced
by their intended usage in a graphical window-system.
Logical buffers for BACK and FRONT_LEFT make sense in the
context of double buffering and stereo presentation, but
their use in off-screen rendering situations is
anachronistic at best and perhaps even confusing.
There are several options:
Option (A): stick with the "legacy" names
This would have us use all of the legacy names which are
used to identify a single buffer: FRONT_LEFT,
FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, and AUX0..AUXn.
This option would require no change to DrawBuffersARB().
Option (B): AUXn names
If we wish to avoid using the legacy names, one option
is to re-use another numerically named set of color
buffers, the AUX buffers, and only allow framebuffer
objects to support AUX0..AUXn attachment points.
This has the advantage of being easy to specify, and
numerically delimit, but is a little strange as
framebuffer objects could conceivably support the same
number of AUX buffers as the implementation supports
multiple render targets. This would have the awkward
consequence of allowing framebuffer objects to support
more AUX buffers than the default framebuffer could
support via the pixel format selection mechanism.
This option would require no specific change to
DrawBuffers but might require non-default framebuffers
to support more AUX buffers than the default framebuffer
controlled by the window-system pixel format.
Option (C): COLORn names
Another option is to rename the color buffer attachment
points for application-created framebuffer objects to
COLOR0..COLORn. This has the advantage of avoiding the
legacy window-centric names, and avoiding the confusion
with AUX buffers. When considered in conjunction with
the decision in issue (53) to support a level of
indirection when using ARB_draw_buffers, however, the
user of the names COLOR0..COLORn may be confusing. For
instance, if an ARB fragment program contains color
output to "result.color[3]", it will not necessarily
output to COLOR3. It will actually write to the buffer
specified by DrawBuffersARB for DRAW_BUFFER3 which may
or may not be COLOR3.
This option would require an update to DrawBuffers to
accept the new COLOR0..COLORn values as valid draw
buffers and would require a change to DrawBuffers to
disallow the "legacy" names. Or at the very least we
would need some language to describe what happens if the
DrawBuffers are using the legacy names when the
currently bound framebuffer is not the default window
system framebuffer.
Option (D): DATAn names
Yet another option is to call these attachment points
DATA0..DATAn. This is the same as option (C) but uses
the word DATA instead of COLOR. This has the advantage
of avoiding the above problems with COLOR0..COLORN, but
introduces a similar conflict with GLSL which uses the
"gl_FragData[n]" name for its output. Additionally,
since we only support multiple render targets for color
logical buffers, it may be that using the word DATA is
considered too abstract/general.
Option (E): add ATTACHMENT to *ALL* names
In order to avoid the confusion of option (C) and (D),
we can choose to be more verbose. We can add the word
_ATTACHMENT to distinguish these enums from the color
outputs of a fragment program or fragment shader. For
symmetry we also add _ATTACHMENT to the DEPTH and
STENCIL (and any other to-be-added) attachment points.
Similar to (C) and (D), this option requires an update
to DrawBuffers to at least accept the new enum values.
We could choose to make it illegal to specify the legacy
values for non-default framebuffers as well. This is
essentially covered by issue (55).
Here is an pseudo-code example using option (E):
// Assume presence of color renderbuffers
// with names 1000, 2000, 3000, 4000
GLuint db[4] =
{ COLOR_ATTACHMENT4, COLOR_ATTACHMENT7,
COLOR_ATTACHMENT1, COLOR_ATTACHMENT2 };
glDrawBuffers(4, db);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, COLOR_ATTACHMENT4,
GL_RENDERBUFFER_EXT, 1000);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, COLOR_ATTACHMENT7,
GL_RENDERBUFFER_EXT, 2000);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, COLOR_ATTACHMENT1,
GL_RENDERBUFFER_EXT, 3000);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, COLOR_ATTACHMENT2,
GL_RENDERBUFFER_EXT, 4000);
Then in ARB_fragment_program
result.color[0] writes to COLOR_ATTACHMENT4 (i.e., renderbuffer 1000)
result.color[1] writes to COLOR_ATTACHMENT7 (i.e., renderbuffer 2000)
result.color[2] writes to COLOR_ATTACHMENT1 (i.e., renderbuffer 3000)
result.color[3] writes to COLOR_ATTACHMENT2 (i.e., renderbuffer 4000)
And in ARB_fragment_shader
gl_FragData[0] writes to COLOR_ATTACHMENT4 (i.e., renderbuffer 1000)
gl_FragData[1] writes to COLOR_ATTACHMENT7 (i.e., renderbuffer 2000)
gl_FragData[2] writes to COLOR_ATTACHMENT1 (i.e., renderbuffer 3000)
gl_FragData[3] writes to COLOR_ATTACHMENT2 (i.e., renderbuffer 4000)
See also issue (57) for discussion on querying the number of
available color buffers.
(55) What should happen if the current DRAW_BUFFER(s) point to a
non-existent logical buffer? Likewise for READ_BUFFER.
RESOLUTION: resolved
partial resolution #1: DrawBuffer(s)/ReadBuffer throws
an error if the buffer does not "exist" for all
framebuffers (default and non-default).
Should it be an error to call drawBuffer on a
non-default framebuffer if named buffer does not
exist?
Resolved: yes
partial resolution #2: The test for having a valid draw
and read buffer should be part of framebuffer
completeness test.
Should be part of completeness test and should all 5
indpenent reasons add 5 enums?
Resolved: yes
partial resolution #3: we should create an enum for
each implementation independent reason for failing
the framebuffer completeness test of section 4.4.4.1
Current names (could change...)
FRAMEBUFFER_COMPLETE_EXT
FRAMEBUFFER_INCOMPLETE_ATTACHMENTS_EXT
FRAMEBUFFER_INCOMPLETE_IMAGES_EXT
FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT
FRAMEBUFFER_UNSUPPORTED_EXT
NOTE: as per resolution of issue (78)
FRAMEBUFFER_INCOMPLETE_ATTACHMENTS_EXT
became
FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
and
FRAMEBUFFER_INCOMPLETE_IMAGES_EXT
was dropped.
This issue is intertwined with issue (56), which discusses
whether the DRAW_BUFFER and READ_BUFFER are context or
framebuffer object state.
First, some background: If DRAW_BUFFER state is part of the
context state vector rather than the framebuffer object
state vector (see issue 56), then there are three ways to
cause DRAW_BUFFER to reference a color buffer attachment
point that "does not exist" in the currently bound
framebuffer. If DRAW_BUFFER is part of the framebuffer
object state vector, then (A) still applies but (B) and (C)
do not.
A) The first case is by detaching, from the currently
bound framebuffer object, the image that is attached to
attachment point named by the value of DRAW_BUFFER. If
an image is attached to COLOR_ATTACHMENTn_EXT in the
current framebuffer object and DRAW_BUFFER is set to
COLOR_ATTACHMENTn_EXT, and then the application
detaches the image from COLOR_ATTACHMENTn_EXT, then
DRAW_BUFFER will end up specifying a buffer that "does
not exist" in the currently bound framebuffer object.
There is no analogue to this case in OpenGL prior to
EXT_framebuffer_object. Before this extension, the
pixel format or fbconfig of a window or pbuffer is
immutable once one of these drawables has been created.
By design, framebuffer objects (which essentially
represent a new type of drawable) have mutable "pixel
formats".
B) The second case is by binding between two user-created
framebuffer objects, where the two framebuffer objects
do not have images attached to the same set of color
attachment points. If an image is attached to
COLOR_ATTACHMENTn_EXT in the current framebuffer object
and DRAW_BUFFER is set to COLOR_ATTACHMENTn_EXT, and
then the user binds to a new framebuffer for which
there is no image attached to COLOR_ATTACHMENTn_EXT,
then DRAW_BUFFER will end up specifying a buffer that
"does not exist" in the newly bound framebuffer object.
This is morally equivalent to calling MakeCurrent to
bind a context to a different drawable (window or
pbuffer) which does not have bitplanes for the color
buffer named by the context's value of DRAW_BUFFER.
For example, MakeCurrent to a double-buffered window,
set DRAW_BUFFER to BACK, then MakeCurrent to a
single-buffered window.
C) The third case is by binding between the default
framebuffer and a user-created framebuffer object. The
attachment points of a user-created framebuffer object
are named COLOR_ATTACHMENTn_EXT, DEPTH_ATTACHMENT_EXT,
STENCIL_ATTACHMENT_EXT, etc. These are also the legal
values of DRAW_BUFFER when a user-created framebuffer
object is bound. The default framebuffer, on the other
hand, does not use the _ATTACHMENT names but instead
uses names such as FRONT_LEFT, BACK_RIGHT, and AUXn as
legal DRAW_BUFFER values. Because the two sets of
names do not overlap, no value of DRAW_BUFFER is valid
for both the default framebuffer and a user-created
framebuffer object.
This is somewhat equivalent to case (B), except that in
case (C) there is a guarantee that DRAW_BUFFER will
become invalid, whereas in case (B) it is only
_possible_ that DRAW_BUFFER will become invalid.
The very problem of invalid DRAW and READ buffers was
already a feature of OpenGL (and the window-system APIs)
before the introduction of the EXT_framebuffer_object
extension. The GLX specification specifically addresses
what happens when MakeCurrent is used to bind a context to a
different drawable (window or pbuffer) which does not
possess one of the color buffers referenced by the context's
current values of DRAW_BUFFER and READ_BUFFER. GLX
addresses this by saying that no GL error is generated, but
invalid DRAW_BUFFER behaves as if DRAW_BUFFER were NONE, and
reads produce undefined results when READ_BUFFER is invalid.
Now, back to the question of how EXT_framebuffer_object
should handle the situation when a framebuffer object is
bound and DRAW_BUFFER or READ_BUFFER is not valid while
bound to a user-created framebuffer object.
Obviously one option is to resolve the issue the same way is
handled by MakeCurrent in the GLX spec. Invalid DRAW_BUFFER
acts as if DRAW_BUFFER were NONE, and invalid READ_BUFFER
causes read operations to generate undefined results.
A second option is to modify the framebuffer completeness
test to fail if the current DRAW_BUFFER or READ_BUFFER
reference an attachment point to which no image is attached.
This solution would also result in no rendering being
performed, but would also generate a GL error when rendering
is attempted while in this state, as determined by issue
(64). When rendering to a framebuffer object, invalid
DRAW_BUFFER would cause generation of GL errors; but when
rendering to a window, invalid DRAW_BUFFER would not cause
generation of GL errors.
Consider also that, because of the resolution of issue (66),
depending on how issue (56) is decided, failing the
framebuffer completeness test due to a "non-existent"
DRAW_BUFFER or READ_BUFFER may not be a viable option,
because the framebuffer completeness test is not allowed to
examine context state.
Additionally, there are two sub-issues that fall out of this
issue:
sub-issue 1: Error at DrawBuffer call time or not?
sub-issue 2: DRAW_BUFFER in or out of completeness test?
[sub-issue 1]: First, what should be the behavior of
DrawBuffer(s) and ReadBuffer if the specified buffer does
not exist at the time DrawBuffer(s) or ReadBuffer is called?
For default framebuffer (window-system drawables), an error
is currently thrown. We can not (or do not wish to) change
this legacy behavior of window-system supplied drawables.
Consequently, we must resolve several questions here:
For instance:
- Should we do the same thing (error at DrawBuffer time)
for user framebuffer objects?
- Is this decision influenced by the fact that
user-created framebuffer objects can change their
attachments one buffer at a time while window-system
supplied drawables can not (i.e., must change all
attachments atomically)?
- Also, on other places in this API, such as assembling
a framebuffer from framebuffer-attachable images, we
have allowed the system to move through "invalid"
states without generating an error as long as the
system was back in a "valid" state by rendering time
(or "validation" time). Should we adhere to that
principle here, or is this case different somehow?
- Do we wish to retain the legacy window-system
DrawBuffer(s) behavior for application-created
framebuffer objects for the sake of maintaining
consistency? i.e., Does the benefit of treating
default and non-default framebuffers consistently
outweigh the earlier decision to delay validation of
"invalid" states?
- Both resolutions are examples of "state combination"
errors where an error may or may not be generated
depending on the order state-changing function calls
are made. For instance, in the legacy behavior
DrawBuffers does or does not throw an error on user
framebuffer objects depending on when you call
DrawBuffer relative to when you made your image
attachments. On the other hand, if we decided to not
throw an error at DrawBuffer time for user framebuffer
objects, then DrawBuffer does or does not throw an
error depending on whether one is bound to a default
or non-default framebuffer. Is one of these "state
combination" errors better or worse than the other?
[sub-issue 2]: Should having a DRAW_BUFFER that names a
non-existent buffer cause the framebuffer completeness test
to fail?
Since image attachments can be changed after
DrawBuffer(s) is called, even if we throw an error at
Drawbuffer(s) time, we still must decide how to handle
having an invalid DRAW_BUFFER at render (or "validation")
time. Our options include failing the completeness test,
(thus disabling rendering and generating an error at render
time) or just behaving as if DRAW_BUFFER is NONE (thus
disabling rendering but generating no error at render time).
If the answer is "fail completeness test", then since
currently framebuffer completeness can only be affected by
framebuffer state, then one of two things has to happen:
Either the drawbuffer state must be framebuffer object
state, or we have to revisit our decision that framebuffer
completeness is solely a property of the framebuffer state
and can not be affected by "per context" state.
If the answer is "do not fail completeness test", then the
practical consequence of this decision is that having an
invalid DRAW_BUFFER behaves as if DRAW_BUFFER is NONE, and
no error is generated at render time. Also, in this case,
DRAW-BUFFER state can be either per-context or
per-framebuffer object state without violating any
previously decided issues.
(56) Should the value of DRAW_BUFFER, the corresponding draw buffers
indirection table for ARB_draw_buffers, and the value of
READ_BUFFER, be part of the context state vector or part of the
the framebuffer object state vector?
RESOLUTION: resolved, per-framebuffer object
This issue is intertwined with issue (55), which discusses
what happens when the DRAW_BUFFER or READ_BUFFER references
a color buffer that "does not exist" in the current
framebuffer.
Please first read the "First, some background" section of
issue (55), which could be, but is not, replicated here.
Note that depending on how issue (56) is decided, cases (B)
and (C) from issue (55) might become moot. Specifically, if
the DRAW_BUFFER and READ_BUFFER state are added to the
framebuffer object state vector, then neither case (B) nor
case (C) remains relevant. Only case (A) would continue to
be an issue.
The discussion over this issue centered around the following
areas:
i) There must be a unique per-context value of DRAW_BUFFER
for the default window-system-provided framebuffer.
In GL, before EXT_framebuffer_object, the DRAW_BUFFER
was considered context state because:
1) When two contexts are rendering to the same drawable,
each context can use a different value of
DRAW_BUFFER.
2) When MakeCurrent alternately binds a single context
to each of two different drawables, after MakeCurrent
DRAW_BUFFER retains the value it had immediately
before calling MakeCurrent. This is true even if the
last time the context was bound to a given drawable,
DRAW_BUFFER had a different value than it does when
that drawable is next bound to the context.
Therefore, a per-context value of DRAW_BUFFER must
exist, and must be in effect when the
FRAMEBUFFER_BINDING_EXT is zero.
Two ways of satisfying this requirement that we have
considered include:
A) DRAW_BUFFER is part of the context state vector, but
is not part of the framebuffer object state vector.
B) Every framebuffer, including the per-context default
window-system-provided framebuffer, has its own value
for DRAW_BUFFER.
ii) MakeCurrent vs. BindFramebuffer
As described above, the context state vector must
contain a value for DRAW_BUFFER that applies to the
default window-system-provided framebuffer, which is
used after a call to BindFramebuffer(0). When
MakeCurrent is used to bind the context to a different
drawable (window or pbuffer), the context's value of
DRAW_BUFFER remains unchanged. In other words, the
choice of drawable does not affect the value of
DRAW_BUFFER.
An application-created framebuffer object is another
type of drawable. When the framebuffer binding is
changed via BindFramebuffer, issue (56) speaks to the
way in which DRAW_BUFFER is or is not updated. If
DRAW_BUFFER is part of the context state vector, then
DRAW_BUFFER remains unchanged after calling
BindFramebuffer, just like it remains unchanged after
calling MakeCurrent. On the other hand, if DRAW_BUFFER
is part of the framebuffer object state vector, then
after calling BindFramebuffer DRAW_BUFFER may change
along with the rest of the per-framebuffer state (i.e.,
the image attachments).
By defining DRAW_BUFFER as context state, the behavior
of BindFramebuffer and MakeCurrent are similar, with
respect to their effect on the value of DRAW_BUFFER.
On the other hand, by defining DRAW_BUFFER as
framebuffer object state, then BindFramebuffer and
MakeCurrent differ in their impact on the value of
DRAW_BUFFER.
iii) Multiple contexts and shared framebuffer objects
If DRAW_BUFFER is part of the framebuffer object state
vector, then a single value of DRAW_BUFFER, like all of
the framebuffer object state, will be shared by any
context bound to a given framebuffer object. This can
be considered either a feature or a restriction
depending on whether or not it is desirable for multiple
contexts to be able to share a single the value of
DRAW_BUFFER.
Note that WGL_ARB_pbuffer plus WGL_ARB_render_texture
API has limitations due to the fact that the texture
image selection state is stored in the pbuffer drawable.
For example, that API does not support six different
contexts (in six different threads) simultaneously
rendering to the six faces of a cube map pbuffer. It
offers no way to share the images without also sharing
the pbuffer, and the pbuffer contains a single set of
texture image selection state.
EXT_framebuffer_object differs from ARB_render_texture,
however, however, in that EXT_framebuffer_object allows
the same images of a texture to be attached to multiple
framebuffer objects. Consequently, the above cubemap
example can be implemented in EXT_framebuffer_object in
one or two ways, depending on the resolution of issue
(56):
1) Create six framebuffer objects. Attach a different
face of a cubemap texture to each of the six
framebuffer objects. Each of the six contexts binds
to a unique framebuffer object. Technically, this
option is available whether DRAW_BUFFER is context or
framebuffer state. However, if it is context state,
then there is no reason to create six framebuffer
objects since the value of the DRAW_BUFFER will
already be unique per context.
2) On the other hand, if DRAW_BUFFER is defined as
context state, then a second option is available.
Using a single framebuffer object, attach each face
of the cube map texture to a different attachment
point in the framebuffer object. Each of the six
contexts binds to the same framebuffer object, but
each context uses a different value of DRAW_BUFFER.
iv) Frequency of DrawBuffer calls:
Whether DRAW_BUFFER is part of context or framebuffer
state will have an effect on how often one must call
DrawBuffer after modifying framebuffer state.
If DRAW_BUFFER is part of the context state vector, then
DRAW_BUFFER is guaranteed to become invalid after
calling BindFramebuffer to switch between the default
framebuffer and a user-created framebuffer object [i.e.,
this is case (C) in issue (55)]. DRAW_BUFFER may become
invalid after switching between two user-created
framebuffer objects if the framebuffer objects do not
have images attached to the same set of color attachment
points. When DRAW_BUFFER is invalid, it is necessary to
call DrawBuffer to set DRAW_BUFFER to a valid value or
else rendering is disabled.
If, on the other hand, DRAW_BUFFER is part of the
framebuffer object state vector, then it should never be
necessary to call DrawBuffer after calling
BindFramebuffer. DRAW_BUFFER would only become invalid
if an image was detached from the framebuffer, or if
MakeCurrent bound the default framebuffer to a drawable
with a different set of color buffers. (The latter was
possible prior to this extension.)
Note that there are several state-modifying routines
that may also need to get called after a framebuffer
state change, like Viewport, Scissor, etc. We are not
proposing that these other routines be part of
framebuffer state. One could think of DrawBuffer as
being similar to these other routines which you may also
need to call when you bind between framebuffer objects.
On the other hand, some have questioned whether an
invalid DRAW_BUFFER is really in the same class of
problems as an out-of-bounds viewport or scissor
because: 1) an invalid viewport or scissor never
generates a GL error, and 2) prior to the
EXT_framebuffer_object extension an invalid DRAW_BUFFER
would generate INVALID_ENUM inside DrawBuffer.
v) Effect on framebuffer completeness test:
By resolution of issue (66), if the draw buffer is
context state, then the fact that the draw buffer names
a non-existent buffer can not affect the result of the
framebuffer completeness test. Note that this still
could be considered a "do not render" case, but would
separate from the framebuffer completeness test.
If the draw buffer(s) and read buffer are part of the
framebuffer object state then having a draw or read
buffer name a non-existent buffer can (if we choose) be
part of the framebuffer (in)completeness test.
Note, by resolution of issue (64), failing the
framebuffer completeness test causes a GL error to be
generated when draw or read operations are attempted.
Prior to EXT_framebuffer_object, it was already possible
to have an invalid value of DRAW_BUFFER if a call to
MakeCurrent bound the context to a drawable that did not
contain a color buffer corresponding to the context's
value of DRAW_BUFFER. However, no GL error would be
generated if DRAW_BUFFER obtained an invalid value
through this method.
vi) Draw buffer(s) error behavior:
Prior to the EXT_framebuffer_object extension, it was an
error to call DrawBuffer or ReadBuffer with a value that
did not correspond to one of the logical color buffers
of the currently bound drawable (window or pbuffer).
Although it was not possible to set DRAW_BUFFER to an
invalid value by calling DrawBuffer, it was actually
possible for DRAW_BUFFER to have an invalid value after
a call to MakeCurrent, as describe in issue (55).
It has not been decided yet whether
EXT_framebuffer_object will relax the requirement that
the argument to DrawBuffer references a color buffer
that "exists" in the currently drawable.
In working group discussions, there was a perception
that such an error during DrawBuffer can be generated
only if DRAW_BUFFER is part of the framebuffer object
state vector. Then when the default framebuffer (window
or pbuffer) is current, the legal values of the argument
to DrawBuffer would be determined by the pixel format or
fbconfig. When a user-created framebuffer object is
current, the legal values of DrawBuffer would either be
any of the COLOR_ATTACHMENTn_EXT names or only the names
of attachment points to which an image is presently
attached.
However, given the precedent set by MakeCurrent and
DRAW_BUFFER, it seems reasonable to retain the
preexisting requirement that the argument to DrawBuffer
names a buffer that "exists" in the current drawable.
In other words, there already exists precedent that says
it is OK for DrawBuffer to generate an error in all the
cases described in the preceeding paragraph, even if
DRAW_BUFFER is defined as part of the context state
vector.
(57) Should we have a query to define the maximum number of
attachable color buffers (to support ARB_draw_buffers)?
RESOLUTION: yes, MAX_COLOR_ATTACHMENTS.
Currently an application can query the GL for the maximum
number of supported AUX buffers. An application can also
query for MAX_DRAW_BUFFERS_ARB in the ARB_draw_buffers
extension. Given that we have named the color logical
buffer attachment points, COLOR_ATTACHMENT0_EXT through
COLOR_ATTACHMENTn_EXT, it seems natural that we should have
a query to find the maximum value "n".
One thought was that we might be able to use
MAX_DRAW_BUFFERS_ARB to store this value, but that value
really describes the maximum number of colors that can be
simultaneously output which is not the same thing as the
number of buffers which can be attached and then selected
among using DrawBuffersARB().
This question is related to issue (54), which covers the
names of the user-created framebuffer object color
attachment points. Using the names COLOR_ATTACHMENT0_EXT
through COLOR_ATTACHMENTn_EXT rather than the legacy color
buffer attachment names (FRONT_LEFT et. al.) for
user-created framebuffer objects has an advantage that the
number of color buffer attachment points could be queried
independent of the number of AUX buffers and existence of
front/back & left/right color buffers as specified in the
pixelformat. The number of available offscreen attachment
points really should be independent of the properties of the
current drawable's pixelformat, especially since MakeCurrent
can bind a context to a drawable with a different
pixelformat and thus different set of color buffers.
One implication of this query is that the value of
MAX_COLOR_ATTACHMENTS_EXT is possibly still dependent on the
context/pixel format but independent of the currently bound
framebuffer. In other words, MAX_COLOR_ATTACHMENTS_EXT can
not change simply because the user called BindFramebuffer().
Or can it? See issue (62)
(58) What should we do about rendering to textures with borders?
(besides attempt to fervently wish them out of existence, I mean)
RESOLUTION: resolved, borders are fully supported
Should we allow rendering to textures with borders at
all?
Resolved: yes
If we allow this, can you render to the border pixels?
Resolved: yes
The reason this is an issue is that (a) everyone hates
supporting borders, and (b) it's not clear what it means to
render to a texture with borders.
To disallow rendering to a texture image with non-zero
border size, we could add a test for non-zero border size to
the definition framebuffer completeness. This might be
preferrable to an error at FramebufferTexture, since the
user could always redefine the texture to have borders after
attachment, and so the framebuffer completeness test is
necessary anyway.
However, since borders do exist today and we are not
planning to rip them out of OpenGL everywhere else, we
decided to support them. It seemed odd that you could still
specify borders via TexImage but not render into the same
texture so we leave them supported. Note that it's quite
possible that implementations which don't support borders
may continue to either not support them or fall to software
rasterization.
If someday we decide to disallow borders in general, they
will be disallowed from this extension as well.
One additional note: section 3.8.2, page 137, of the OpenGL
1.5 specification, states that {Copy}TexSubImage uses
negative offsets to refer to border texels. We choose not
to do this because negative window-coordinates are
undefined. (NOTE: Are negative window coordinates actually
undefined? Or are they just not commonly used in practice?)
(59) Should we support named bit depths for stencil renderbuffers?
RESOLUTION: resolved, yes, choose 4 common formats.
We intend to support using renderbuffers to store stencil
data. This means we need to consider what kind of "internal
format" request we provide for stencil formatted
renderbuffers.
We choose to allow a "named" format request for the internal
format. This is essentially equivalent to the named
internal format request of the TexImage calls. It is merely
a request and the driver will attempt to satisfy it as best
as possible but may approximate the requested format with
another format. Additionally, this request is subject to
the same invariance constraints as the texture internal
format requests.
For the initial extension we choose the following four sized
internal formats, as well as the base internal format
STENCIL_INDEX:
STENCIL_INDEX1_EXT
STENCIL_INDEX4_EXT
STENCIL_INDEX8_EXT
STENCIL_INDEX16_EXT
(60) If depth buffer is disabled when a user-created framebuffer
object is bound and an image is attached to GL_DEPTH, does the
depth buffer factor into framebuffer validity determination or
is the depth buffer ignored? Similar for other types of
logical buffers.
RESOLUTION: resolved, consider all attached images when
determining framebuffer completeness, even if the images are
"irrelevant" based on the state of the framebuffer.
The main reason to consider not paying attention to certain
images (i.e., ignoring the image attached to the depth
buffer when depth test is disabled) would be developer
convenience. The developer wouldn't need to explicitly
detach a buffer, but could set the state to ignore it
(disable depth test, or disable color mask, reset draw
buffer, etc).
However, this raises the possibility that by simply changing
this other state (depth test, stencil test, color mask, etc)
the query for framebuffer completeness could change values.
This was deemed undesirable. We'd like to be able to
minimize the amount of state changes that can cause the
framebuffer completeness query to change.
Another strange effect of ignoring "irrelevant" images when
considering framebuffer completeness is that we could get an
undesirable interaction between draw buffer and the pixel
format for the framebuffer. A framebuffer is considered
incomplete if the color buffers do not all have the same
internal format. But, consider the following case:
- an application attaches a floating point
color-renderable image to COLOR_ATTACHMENT1, and
- the application attaches a fixed point
color-renderable image to COLOR_ATTACHMENT2 and
- the application sets the DRAW_BUFFER to
COLOR_ATTACHMENT1, then
If we ignored the attached images not pointed to by
DRAW_BUFFER(s} when evalutating framebuffer completeness, we
could consider this framebuffer complete. This framebuffer
would use floating point rendering. Now, if the application
simply changes the DRAW_BUFFER to COLOR-ATTACHMENT2, then we
would also say the framebuffer is complete but now the
framebuffer would be using fixed point rendering. We didn't
want to allow a change to DRAW_BUFFER to effectively change
the pixel format. On the other hand if we always considered
all attached images, then in this case described above, the
framebuffer would always be incomplete while the formats of
the color-renderable images were inconsistent.
To avoid the above complications, we choose to have
framebuffer completeness queries consider all attached
buffers, regardless of whether they would be "used"
according to the current state vector or not.
(61) What are the "minimum requirements" to support this extension?
RESOLUTION: resolved, language added to end of 4.4.4.2
For instance, is it a requirement that there must be at
least one renderable color, depth, and stencil format that
can all work together? is it a requirement that you must be
able to render to *any* "color-renderable" texture format?
Since this extension specifically pulling in functionality
that used to be in the domain of the window sytem, we would
like to use as a starting point for our requrirements, the
language from the GLX 1.3 spec, page 15, which lists the
minimum requirements langauge for a conformant GLX
implementation.
Questions to answer:
- is the GLX spec a good starting point?
- do we want the same requirements as the GLX spec?
- do we want stronger requirements than the GLX spec?
- do we want some kind of requirement that states that
to support this extension, there must be at least one
"gl conformant" framebuffer configuration that can be
constructed on a given implementation? If so, how do
we phrase this?
Anyway, the GLX spec states:
"Servers are required to export at least one GLXFBConfig
that supports RGBA rendering to windows and passes
OpenGL conformance (i.e., the GLX RENDER TYPE attribute
must have the GLX RGBA BIT set, the GLX DRAWABLE TYPE
attribute must have the GLX WINDOW BIT set and the GLX
CONFIG CAVEAT attribute must not be set to GLX NON
CONFORMANT CONFIG). This GLXFBConfig must have at least
one color buffer, a stencil buffer of at least 1 bit, a
depth buffer of at least 12 bits, and an accumulation
buffer; auxiliary buffers are optional, and the alpha
buffer may have 0 bits. The color buffer size for this
GLXFBConfig must be as large as that of the deepest
TrueColor, DirectColor, PseudoColor, or StaticColor
visual supported on framebuffer level zero (the main
image planes), and this confguration must be available
on framebuffer level zero."
So if we did a direct translation of these requirements into
our spec, we'd end up with something approximately like the
following:
Although GL defines a wide variety of internal formats
for textures and renderbuffers, some implementations may
not support particular combinations of internal formats
for the images attached to the framebuffer. For a
framebuffer with these unsupported combinations of
internal formats, calls to CheckFramebufferStatusEXT()
will return FRAMEBUFFER_UNSUPPORTED_EXT.
There must exist, however, at least one combinations of
internal formats for the images attached to the
framebuffer for which CheckFramebufferStatusEXT() will
*not* return FRAMEBUFFER_UNSUPPORTED_EXT.
Specifically, implementations are required to support at
least one set of internal formats for the images
attached to a framebuffer such that
- the image attached to the color buffer supports
RGBA rendering, and
- the image attached to the color buffer has at
least as many bits as the deepest visual supported
by the window-system, although the alpha buffer
can have 0 bits, and
- the image attached to the depth buffer has at
least 12 bits, and
- the image attached to the stencil buffer has at
least 1 bit, and
- rendering to this framebuffer passes OpenGL
conformance."
However, it looks like no one is seriously using the
NON_CONFORMANT_CONFIG bit under GLX or AGL, and on WGL,
there is no such bit, so we'd like to "assume" conformance
and drop the last clause. Additionally, we'd like to just
piggy back on the existing requirements without duplicating
them here so we will simplify this language to leave out the
last paragraph and list of clauses altogether.
We do wish to retain the notion that there must be some
configuration for which FRAMEBUFFER_UNSUPPORTED_EXT is not
returned.
(62) Exactly which, if any, queriable state can change after a call
to BindFramebuffer and/or a change in framebuffer attachments?
RESOLUTION: resolved, at the Sept. 2004 ARB meeting we
resolved in principle that there is a small subset of
"framebuffer-related" state that can change. We just need
to define exactly the subset. The current subset as listed
in section 4.4.5 is below:
AUX_BUFFERS
MAX_DRAW_BUFFERS
MAX_COLOR_ATTACHMENTS
RGBA_MODE
INDEX_MODE
DOUBLEBUFFER
STEREO
SAMPLE_BUFFERS
SAMPLES
{RED|GREEN|BLUE|ALPHA}_BITS
DEPTH_BITS
STENCIL_BITS
ACCUM_{RED|GREEN|BLUE|ALPHA}_BITS
The reason this is an issue is that traditionally there are
some GL context state queries that are dependent on pixel
format and window-system state. For instance, doing a
GetIntegerv of DEPTH_BITS returns the bit depth of the
window-system allocated depth buffer which is a function of
the pixel format. If DEPTH_BITS is zero, this means that no
depth buffer was present in the pixel format. Other context
state queries like MAX_DRAW_BUFFERS, MAX_ACCUM_BUFFERS,
SAMPLES, etc are all possibly functions of the current pixel
format, and have traditionally been constant over the
lifetime of a given context.
However, this extension specifically subsumes some of the
operations and state of the window-system pixel format
mechanism. So an obvious question is: what should these
queries return for things like DEPTH_BITS and
MAX_DRAW_BUFFERS when using a non-default framebuffer
object?
If we allow these queries to return a value that is a
function of the current framebuffer object, then a
consequence is that the values returned by these queries can
change after a call to BindFramebuffer and/or a change in
the attachments of the currently bound framebuffer object.
This may be desirable: for instance, a user may rightly
expect that querying RED_BITS returns the red bits of the
currently attached color buffer(s). But is the user also
expecting that MAX_DRAW_BUFFERS might change? What about
SAMPLES or SAMPLE_BUFFERS? What about
MAX_COLOR_ATTACHMENTS?
Consider that in developing ARB_draw_buffers it was stated
that some implementations might want to set MAX_DRAW_BUFFERS
to 1 for pixel formats that also supported multisampling.
This would allow implementations to control which
capabilities they exported. What facilities do we have for
this in this extension - can MAX_DRAW_BUFFERS change if we
supported multisampling on a non-default framebuffer object?
Fundamentally, all of the state in table 6.28-6.31 of the
OpenGL 1.5 spec (the MAX_* queries) can in theory change as
the result of the pixel format changing. Since this
extension does an effective pixel format change, what if any
of this state can/should be allowed to change when
framebuffer attachments are changed?
(63) Should we change ValidateFramebuffer into an explicit
enum-based query for framebuffer completeness?
RESOLUTION: resolved, separate API function rather than a
Get query, to emphasize the "on-demand" state examination.
We did choose a different name for ValidateFramebuffer().
In issue (67) we decided to rename this function
CheckFramebufferStatus().
For reference the reason this is an issue is that, as
originally described, ValidateFramebuffer (now called
CheckFramebufferStatus) served three purposes:
First, it forced an "on-demand" examination of the current
framebuffer state (including framebuffer attachment state)
and the state of the attached images. On some
implementations this examination might be expensive, and
therefore there was a desire to control exactly when the
operation would occur.
Second, because of the implementation dependent reasons that
a framebuffer might be considered not complete,
ValidateFramebuffer served as a query for an application to
determine at run-time if a seemingly compatible combination
of attached images is actually incompatible on the current
GL implementation.
Third, ValidateFramebuffer was more than just a query. It
was a function that would set a piece of framebuffer state
that "enabled" rendering if the framebuffer was determined
to be complete. After certain changes to framebuffer state,
or in the initial default state, unless ValidateFramebuffer
was called prior to rendering, and unless framebuffer
validation "passed", rendering would be disabled.
However, now that it is no longer required to call
ValidateFramebuffer prior to rendering, ValidateFramebuffer
doesn't really set any state. The third reason is no longer
pertinent.
This leaves us with the first and second reasons. The first
reason in particular seems to be driven by convenience. It
is convenient to be able to control when this operation
happens, but it is arguably also convenient to be able to
force the examination/validation of a wide variety of other
pieces of GL state, yet we don't have specific on-demand
"ValidateTexture" or "ValidateBlendState" routines. In
addition, on some implementations framebuffer validation may
be less expensive than originally thought.
So if we ignore the first reason for a moment, we are left
the second reason for ValidateFramebuffer - a query of the
framebuffer completeness. We do wish to retain this query
somehow, so we could choose to leave it in its current form,
or we could choose to make it look like other more
traditional queries, i.e., some kind of GetInteger,
GetFramebuffer, or GetFramebufferParameter call.
If we feel like the first reason is still valid, we could
also choose to retain a ValidateFramebuffer call to get the
"on-demand" state examination and still choose to make
separate query for the framebuffer completeness.
Either way, if we decide to make an enum-based query we need
to choose the form. We could choose to use GetInteger and
query for COMPLETENESS. (If we do this, we'd need a
"per-target" variant of the enum, i.e.,
FRAMEBUFFER_COMPLETE, and if a read framebuffer target is
added later, READ_FRAMEBUFFER_COMPLETE would need to be
added as well.) This would be similar to how texture
bindings are queried on a per target basis as in
GetIntegerv(TEXTURE_BINDING_2D, &param). Another option is
to add a target-aware query routine, i.e.,
GetFramebufferiv(FRAMEBUFFER, COMPLETE, &param); this is
similar to what the ARB vertex/fragment program API's did to
query per-target state like PROGRAM_NATIVE_INSTRUCTIONS_ARB.
(64) Should it be a GL error to attempt to render with an incomplete
framebuffer?
RESOLUTION: resolved, "YES"
In looking at other GL resources that can be considered
"incomplete" for rendering, there were two precedents to
draw on here: (a) textures and (b) programs/shaders.
a) For textures, the GL behaves as if the incomplete
resource is simply not available. That is, if an
application attempts to render with an incomplete texture,
then the GL behaves as if texturing is simply disabled. No
error is thrown.
b) For ARB_vertex_program and ARB_fragment_program, and GLSL
shaders, if a program or shader is invalid, then the GL
throws an error at "Begin" time.
Originally, we choose style (a): treat an incomplete
framebuffer similar to a "pixel ownership test failure".
This means that no fragments are generated, reads of the
framebuffer generate undefined pixels, and no error is
thrown.
[NOTE: Technically, according to the GL spec, the fate of
rendered fragments that fail the pixel ownership test is
left up to the window-system and is therefore implementation
dependent. A better way to handle this is to mimic
make_current_read's language "as if DRAW_BUFFER is NONE"]
However, since the a query of framebuffer completeness can
only answer the question "is the framebuffer complete right
now?", but doesn't indicate whether the application may have
attempted to render with an incomplete framebuffer earlier,
we decided to throw an error in this case as an aid to the
developer. Throwing an error has an advantage in that the
error state is retained, like all GL errors until the user
calls GetError().
Another option that was considered was to extend the
framebuffer completeness query to indicate that the
framebuffer is complete now, but was incomplete during
earlier rendering. The downside of this option was that
then there would then be two return values for the query
that would mean "framebuffer complete right now". So in the
end, we simply decided to leverage the existing GetError
semantics to capture this "sticky" error behavior.
One additional concern was that gl errors are traditionally
only used to indicate programming errors on the part of the
application, but the framebuffer completeness test may have
failed simply because of implementation dependencies through
no fault of the application. We decided to adopt the notion
is that it is an error to attempt to render with an
incomplete framebuffer, on all implementations, and so it
actually *is* a programming error if an application does not
attempt to deal with an incomplete framebuffer prior to
rendering.
(65) If it is an error to render to or read from an incomplete
framebuffer, should we use INVALID_OPERATION or create a new
error?
RESOLUTION: resolved, INVALID_FRAMEBUFFER_OPERATION_EXT
We resolved to create a new error at the September ARB
meeting and then resolved the name of the error within
the work group.
We agreed that if we throw an error here, we'd like a
new error enum, particularly because the error may have
been triggered by a framebuffer which is incomplete for
implementation dependent reasons.
Some options for the new error name which were discussed:
OPERATION_ON_INCOMPLETE_FRAMEBUFFER
INCOMPLETE_FRAMEBUFFER
IMPLEMENTATION_DEPENDENT_FAILURE
INVALID_FRAMEBUFFER
INVALID_FRAMEBUFFER_OPERATION
(66) There are several issues related to how we treat DrawBuffer(s)
and other context state with respect to framebuffer
completeness. We'd like a self-consistent model here and this
may affect the resolution of issue (8), (44), (55), and (56).
RESOLUTION: resolved, (d) - no context state in framebuffer
completeness test, but context state can affect whether
rendering takes place, does not take place, or is undefined.
Note option (d) required us to revisit issue (44).
The first question we had to answer was:
Is it desireable that "framebuffer completeness" be
purely a property of the set of framebuffer state (which
includes the state of the images attached to the
framebuffer)? Or can a framebuffer's completeness
depend on "non-framebuffer" context state as well?
For instance, there are currently two pieces of context
state that can affect framebuffer completeness: texture
binding state and draw buffer state.
First, in issue (44), we decided that attaching an image of
a currently bound and enabled texture to a framebuffer can
cause a framebuffer to be incomplete. The texture binding
is context state and there are pieces of the texture object
state (base level, max level) that can also affect the
determination of framebuffer completeness. (Additionally if
we add render-to-vertex-array functionality later, we might
expect to have a framebuffer completeness requirement that
examines the state of the currently bound vertex array.)
One way to avoid this context dependency is to revisit issue
(44) and say that this "texture-from-destination" case
simply generates undefined rendering but does not affect
framebuffer completeness. This would replace the "expressly
disabled" rendering and framebuffer incompleteness with
"undefined rendering", but would also let implementations
avoid checking context state during the validation of the
framebuffer state.
The second piece of context state that might cause
framebuffer validation failures is the draw buffer(s) and/or
read buffer state. It has been suggested in issue (55) that
if the draw buffers specify attachment points with no
attached images, then the framebuffer might be considered
incomplete. If we choose to do this, then we would have
context state influencing framebuffer completeness state.
However, if we resolve issue (56) to say that the draw
buffer state is part of the framebuffer object state, then
the draw buffer is no longer context state and this
particular dependency of framebuffer completeness on context
state goes away.
The above discussion leaves us with several self-consistent,
but different sets of decisions:
(a) Remove context dependencies from framebuffer
completeness.
To do this we would:
- Move draw buffer state from context into
framebuffer: issue (56)
- Make "texture-from-destination" undefined instead
of a reason for framebuffer incompleteness: issue
(44)
- Presumably, if we created a render-to-vertex-array
extension layered on this one, we would likely
also make rendering into the currently bound
vertex array undefined as well.
With option (a), we can say that having draw buffer
set to an non-existent buffer is a reason for
framebuffer incompleteness and there are no context
dependencies. This would resolve issue (55).
(b) Allow context dependencies in framebuffer
completeness.
Essentially this means that the result of a query of
framebuffer completeness is dependent on the context
making the query - or put another way, the
framebuffer completeness state is context state not
framebuffer state.
If we choose this option (b), then we are esentially
free to resolve issues (44), (55), and (56)
however we want. In other words:
- draw buffer can be either context or
framebuffer state: issue (56)
- "texture-from-destination" can be either
undefined or a reason for framebuffer
incompleteness
- draw buffer specifying a non-existent buffer
can be a reason for framebuffer incompleteness
or could result in undefined behavior: issue
(55)
(c) Remove the framebuffer object and make the
framebuffer state part of the context.
This option redefines the issue by not making a
distinction between framebuffer "object" state and
"context" state, therefore framebuffer completeness
depends only on "context" state because all of the
"framebuffer" state is now "context" state.
This would mean that there is now a subset of state
in the context that can be considered the
"framebuffer state" of the context. This is the set
of state that would presumably be pushed/popped
under a theoretical FRAMEBUFFER_BIT for
PushAttrib().
Regardless of whether there is a framebuffer object,
framebuffer completeness may or may not still depend
on pieces of other "context" state that are not part
of subset of context state related to the
"non-default" framebuffer (for instance, texture
bindings and/or draw buffer state).
If we choose this option (c),
- we remove the framebuffer object: issue (8)
This means:
- removing gen/is/bind/delete framebuffer
object
- moving the attachment state into the
context
- creating new context bind points for
framebuffer attachments and creating new
BindFramebufferAttachableImage calls or
using the FramebufferTexture() calls to do
context binds of framebuffer-attachable
images
- we decide whether there is a single set of
draw/read buffer context state or a 2nd set of
draw/read buffer context state to be used for
"non-default" framebuffer objects. Either way
it's "context" state but we need to know if we
have one set of state or two. This is a
variation on issue (56).
- as in option (b), "texture-from-destination"
can be either undefined or a reason for
framebuffer incompleteness
- as in option (b), a draw buffer specifying a
non-existent buffer can either be a reason for
framebuffer incompleteness or could result in
undefined behavior: issue (55)
- all the framebuffer attachments become context
state
- we add a framebuffer enable/disable bit to use
to distinguish between the "default" and
"non-default" framebuffer
(d) Create a new category of reasons that you can't use
a framebuffer for rendering in a specific context,
but that are not part of the test for "framebuffer
completeness"
Essentially, this is a kind of hybrid of options (a)
and (b). There are no context dependent reasons for
framebuffer incompleteness, but at the same time
there are some additional context-dependent
constraints on using a framebuffer. In other words,
a framebuffer can be complete but still not suitable
for rendering by a given context.
This creates two categories of tests that can be
used to disable rendering - the set of
context-independent test that are used to determine
framebuffer completeness, and the set of tests that
are context-dependent and not used to determine
framebuffer completeness.
An open question is: should we add a separate query
for this second set of context-dependent tests
and/or a "meta-query" that would cover both sets.
This "meta-query" would return "true" if and only if
the framebuffer is complete *and* it can be used in
this context.
Note that while the "is framebuffer complete" query
is required by the fact that a framebuffer can be
incomplete because of implementation dependent
reasons, the second query of the context-dependent
test results and the "meta query" are primarily
debugging aids, though perhaps convenient ones.
The framebuffer completeness query is analogous to
asking if a texture is "mipmap complete". The
question, "can I render into my framebuffer", is
analgous to asking the question, "is texturing
enabled." A bound texture may be "complete", but
texturing can still be disabled due to an
unfortunate combination of non-texture-object
context state. Option (d) is basically saying the
same thing of framebuffer objects.
To implement option (d), we'd do the following:
- If draw buffer is defined as "context state" it
can not affect framebuffer completeness, but if
draw buffer is defined as framebuffer state it
might affect framebuffer completeness. See issues
(55) and (56).
- Make "texture-from-destination" undefined instead
of a reason for framebuffer incompleteness: issue
(44). Technically, this could still be an error
unrelated to framebuffer completeness, but we are
trying to avoid creating a precedent for arbitrary
"errors at begin time". When this case was
included in the "framebuffer completeness"
validation, the additional cost of generating the
error was free. But if this
"texture-from-destination" case is not part of
framebuffer completeness, then it is an additional
cost at begin time to detect this in order to flag
an error (and/or disable rendering). To avoid
this cost, we would make this undefined.
- Presumably, if we later create a
render-to-vertex-array extension layered on this
one, we would likely also choose the same
resolution for rendering into the currently bound
vertex array as we choose for the currently bound
texture.
(67) In issue (63) we decided we want to use a dedicated API
function to test framebuffer completeness. We might want to
change the name of "ValidateFramebuffer" however. If so, what
name should we use?
RESOLUTION: resolved, CheckFramebufferStatus()
One reason we decided to retain an explicit API function
instead of just using a GetInteger style query is to
emphasis the "on-demand" state examination that takes place
when making this query.
However, some were uncomfortable with the name
ValidateFramebuffer for this purpose. Some felt that it
implied a requirement to call the function, and others felt
it was too similar in name to the GLSL function
ValidateProgram which served a related but slightly
different purpose. So we chose a new name.
Some options we considered:
ValidateFramebufferCompleteness()
CheckFramebufferCompleteness()
CheckFramebufferStatus()
IsFramebufferComplete()
(68) Exactly which levels should by generated by GenerateMipmapEXT?
RESOLUTION: resolved, from TEXTURE_BASE_LEVEL+1 through q
Automatic mipmap generation via GENERATE_MIPMAP generates
from TEXTURE_BASE_LEVEL+1 through p, which is the 1x1 level.
However, applications frequently don't want to waste
computation generating past q, which is the min of
TEXTURE_MAX_LEVEL and p. The only recourse is to accept the
performance hit or to not use GENERATE_MIPMAP.
Arguably GENERATE_MIPMAP should have been specified to
generate only through q. We have the opportunity to "fix"
this problem by "correctly" specifying the new function
GenerateMipmapEXT to generate only from TEXTURE_BASE_LEVEL+1
through q.
As the specification of GenerateMipmapEXT is currently
written, GenerateMipmapEXT only generates levels
TEXTURE_BASE_LEVEL+1 through q.
(69) What should we call the framebuffer objects to distinguish
them from the default framebuffer?
RESOLUTION: resolved, "application-created"
Currently we call these "application-created" framebuffers
Some places in the spec have also referred these as
"GL-allocated" framebuffers. Whichever term we use, we
should use it consistently.
Some terms we considered:
"application-created" framebuffers
"application-allocated" framebuffers
"non-default" framebuffers
"GL-created" framebuffers
"GL-allocated" framebuffers
"dynamically-created" framebuffers
etc.
The GL spec already talks about "creating" textures, not
"allocating" them, so "*-created" seems like a better
choice.
It's a bit of a toss-up between "GL-created" and
"application-created". Technically, the "GL" really creates
and manages these objects but it only does so at the request
of the application. Going with "application-created" for
now.
(70) With which, if any, attribute bit does the framebuffer binding
push and pop? The same question applies to the current
renderbuffer?
RESOLUTION: resolved, don't push/pop framebuffer binding
bit for now. If desired, we may add this in the ARB/core
update of this spec.
There are a few precedents to choose from.
The ARB_vertex/fragment_program extensions chose to *not*
push/pop the current program object binding. It's not clear if
this was intentional or which existing attribute bit was
appropriate to use or if there was a desire to not create a new
attribute bit.
ARB_vertex_buffer_object buffer objects and GL core texture
objects do push/pop the bindings with the existing VERTEX_ARRAY
and TEXTURE bits respectively. In addition, the texture enables
are push/pop'ed with the TEXTURE bit.
If we do wish to push/pop the FRAMEBUFFER_BINDING_EXT state we
probably need a new FRAMEBUFFER bit.
We could also consider adding a RENDERBUFFER_BIT to cover the
current renderbuffer binding or allow this renderbuffer binding
to push/pop with the FRAMEBUFFER bit. However, it's less clear
that push/pop'ing the renderbuffer binding is useful since the
renderbuffer binding is not used for rendering. The
renderbuffer binding is only used to set the current
renderbuffer for renderbuffer storage allocation and queries.
Also, there are a related set of questions about how much state
should push/pop with a new FRAMEBUFFER bit. Should we push/pop
all of the framebuffer object state in addition to the current
binding? Similar to the way vertex array's can be attached to
VBO's, use of VBO, framebuffers can be attached to other GL
objects. The TEXTURE_BIT covers both per object (min/mag
filter) and per context (texture environment and enable) state.
It's not clear if this is useful or desirable to have per-object
state push/pop. With the addition of object semantics, it seems
like the need for push/pop of object state is reduced.
In the end, since we'd need to create a new bit anyway, we
decided to defer adding push/pop semantics until we understand
the implementation ramifications better. If we decide to create
the bit later on in the ARB or Core revision of this extension,
we can add it in a backward-compatible fashion.
(71) Should we spell out precisely which rendering and reading
routines can cause us to generate an error at the time the
rendering or reading functions are called?
RESOLUTION: resolved, keep the same language as ARB
vertex/fragment program and GLSL for now, with the
addtitions relevant for reading the framebuffer, but
recommend the ARB look at this when doing the next core GL
spec revision.
Currently GL has a few cases that can cause errors at render
time. Specifically, attempting to render with a mapped vertex
buffer object, an invalid low-level vertex or fragment program,
or an invalid GLSL program object all generate errors at "Begin"
time.
This extension adds a new error at "begin" time. Attempting to
render with an "incomplete" framebuffer generates
INVALID_FRAMEBUFFER_OPERATION_EXT. In addition, this extension
adds the same error at "read" time if the application tries to
read from an "incomplete" framebuffer.
The ARB vertex program, ARB fragment program, and GLSL extension
specs state that an app which tries to use an "invalid" object
can generate errors when Begin, RasterPos, or any command that
performs an explicit Begin is called.
This extension has adopted similar language. So the question
asked by this issue is: do we need ot be more explicit.
There are some ambiguities. For instance, it is an error to
write pixels using an "implicit Begin" operation like DrawArrays
if the current vertex program is invalid, but it is not an error
to do an Accum operation which also writes pixels to the
framebuffer.
This issue applies to all of these extensions.
Options include:
- listing all routines which can render or read from the
framebuffer and stating that they can cause an error if
the framebuffer is incomplete, solving the problem for
this extension only.
- adding to the GL core a table of "routines that read
pixels" and "routines that write pixels" and referencing
those tables in the language for each of these extensions.
Because each extension is doing something a little different,
it's not even clear if the second option is a viable option.
It's possible each extension would need its own list of routines
which can generate errors anyway.
Basically, this is a larger problem than this
EXT_framebuffer_object extension. For now, we choose to use the
same (vague-ish) language adopted by the
ARB_vertex/fragment_program and GLSL extnesions.
We do recommend, however, that the ARB address this issue in the
next GL core revision.
(72) Should the framebuffer completeness test include a clause that
says "at least one color attachment" has been made? Or "at
least one attachment of any type"? Or is the framebuffer
still complete when there are no attachments at all?
RESOLUTION: resolved, a framebuffer must have at least one
color-renderable, depth-renderable, or stencil-renderable
image attached to be complete.
While a framebuffer with only depth, or only color
attachments seems plausible, we couldn't come up with a
sensible use for a framebuffer with no attachments at all,
so the assumption is that this is an unintended error on the
part of the application. Therefore, we choose to make it
part of the framebuffer completeness test.
We could make this its own clause in the framebuffer
completeness test. If we choose to do so, we should
probably come up with a new FRAMEBUFFER_INCOMPLETE_* to
conform to our previous practice of keeping one enum per
clause.
However, since this is really related to the attachment
state, we could just piggy back this on the first clause and
same all the attachment points must be "attachment complete"
and there must be at least one color, depth, or stencil
buffer attached.
If we choose this latter option, we can continue to use the
FRAMEBUFFER_INCOMPLETE_ATTACHMENT enum to cover this case.
(73) This clause from framebuffer completeness (before it was
reworded, see below):
* The value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT must
not be NONE for any color attachment point named by
READ_BUFFER.
basically requires at least one color attachment is non-NULL.
But this is not what we want. So what should we do?
RESOLUTION: resolved, (4a) READ_BUFFER can be NONE
The reason is: READ_BUFFER is not allowed to be NONE, which in
turn means to be framebuffer complete, READ_BUFFER must be
COLOR_ATTACHMENTn_EXT for some n which has an image attached.
However, we don't wish to preclude a no-color framebuffer.
What should we do?
Options include:
4a) Allow READ_BUFFER of NONE, reads of color from the
framebuffer when read buffer is none, generate error
INVALID_OPERATION
4b) Generate an error when a read operation (ReadPixels,
CopyPixels, etc) is attempted while the color
attachment point referenced by the READ_BUFFER does
not have an attached image.
4c) Reverse earlier decision to allow complete
framebuffer not to have any color attachments.
Instead, require at least one color attachment.
READ_BUFFER must point to a valid color attachment
or else the framebuffer object is incomplete.
(4c) seems to require the user attach a color buffer just to be
able to read the depth buffer of a depth-only framebuffer.
(4b) seems to suffer from the same problem (unless we move the
"valid read buffer" test out of the completeness test).
Of these choices, (4a) seems to be the most palatable. We
choose the allow the value of READ_BUFFER to be NONE, but reads
of color buffers when READ_BUFFER is NONE will generate an
error, in order to be consistent with the decision in issues
(26) and (65).
Note: that clause was eventually reworded to say:
* 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.
(74) What should CheckFramebufferStatusEXT return if
FRAMEBUFFER_BINDING_EXT is zero?
Secondary question: what should CheckFramebufferStatusEXT
return if there is an error?
RESOLUTION: resolved, default fb returns COMPLETE always,
and CheckFramebufferStatusEXT returns
FRAMEBUFFER_STATUS_ERROR if there is an error (bad target)
This goes to a larger question of whether all framebuffers
including the default window-system-provided framebuffer
have a "completeness" state, or if "completeness" is only a
property which applies to application-created framebuffers.
For the case where the current FRAMEBUFFER_BINDING_EXT is
zero, options include:
- CheckFramebufferStatusEXT returns an error when
FRAMEBUFFER_BINDING_EXT is zero.
- CheckFramebufferStatusEXT always returns
FRAMEBUFFER_COMPLETE_EXT when FRAMEBUFFER_BINDING_EXT
is zero.
For the case CheckFramebufferStatusEXT generates an error,
options include:
- reworking CheckFramebufferStatus into a "get" style
routine that returns a value (or not) in an input
parameter like GetIntegerv
- returning a known value like NONE or 0
- returning undefined results
(75) How are state values for the stencil index write mask and
stencil reference value affected by this extension?
RESOLUTION:
a) index write mask is stored as 32 bit value, default
is all 1's, and
b) reference value is not clamped on specification but
rather is clamped on use and query, and
c) we need to add the stencil reference value
to the state table that lists the state values that
might change after a framebuffer state change
The reason this is an issue is that the current GL
specification indicates that the stencil index write mask
and the stencil reference value are masked/clamped according
to the number of stencil bitplanes. However, in this
extension the number of stencil bitplanes can now change
dynamically as the image attached to the framebuffer is
changed.
For instance, if these values are clamped/masked according
to the bitdepth of the currently attached stencil buffer,
what should happen if the user later attaches a stencil
buffer of a different bit depth? Must the stencil reference
value or index write mask be respecified?
For the index write mask: we decide to treat this value as
"all 1's" as the current specification allows, but further
define the number of 1's to be 32 (the minimum width of an
integer in GL), and a likely maximum stencil bitdpeth for
the forseeable future. This should retain backward
compatbility and still handle the case where the bitdepth of
the stencil buffer can change dynamically.
For the stencil reference value, we decide to treat this
state similar to way various clamped colors are treated in
the ARB floating point pixel extensions. Specifically, the
state values are clamped against the current logical buffer
bitdepths as they are used for rendering and queried, but
are not clamped on specification. This means that these
state values do not need to be respecified just because the
logical buffer bit depth changes, and retains backward
compatibility to the behavior prior to this extension.
We will update the appropriate sections of the specification
to describe this behavior.
(76) Currently framebuffer objects are shared, should we make them
not shared across contexts?
RESOLUTION: yes, framebuffers are shared like display lists
and textures are shared.
Initially it was suggested that some complicated
multi-context semantics might be avoided if if the namespace
for framebuffer objects were not shared across contexts.
Specifically, some members of the group felt that by not
sharing framebuffer objects, we could avoid the situation
where:
a) one context can change the draw buffer of a
framebuffer object in use by another context.
b) one context can change the attachments of a
framebuffer object which may be in use by another
context.
However, after some discussion, we realized that even if we
didn't share framebuffer objects, there were still
interactions similar to those listed above because the
underlying images could still be shared. Consequently, one
context could still affect the completeness and attachments
of the framebuffers in another context by modifying or
deleting the framebuffer-attachable images shared by both
contexts.
So in the end, we decided to retain the share-ability of
framebuffer objects rather than introduce an asymmetry with
other GL objects like textures.
ADDITIONAL COMMENTS:
See the "Dependencies on ARB_framebuffer_object and OpenGL 3.0"
section above for the interaction behaviour between EXT and
non-EXT FBO interfaces.
(77) If the application deletes an object and that object contains
an image which is attached to a framebuffer object, exactly
when and how is the image detached from the framebuffer?
RESOLUTION: resolved, option (1): images are detached from
the currently bound framebuffer on delete, but images remain
attached to any non-bound framebuffers.
This is issue is somewhat related to the multi-context
object-sharing discussion currently going on in the ARB.
This extension presupposes that framebuffer attachments
represent a reference to the attached image (or more
correctly - a reference to the object containing the
attached image). Since having a reference to an object
affects when the object (and/or its name) is deleted, object
deletion semantics are tied into the notion when the state
describing these references is modified. In other words,
the semantics of when objects are deleted are affected by
the details concerning when a change to the framebuffer
attachment state takes place.
Prior to the EXT_framebuffer_object and GLSL extensions, the
only way in which an object not currently bound to this GL
context could be modified, was when the object was modified
by another GL context.
Both the EXT_framebuffer_object and GLSL extensions allow an
object (texture, renderbuffer, shader) to be attached to a
"container" object (framebuffer, program). With the
introduction of "attachment", an object could be bound to
the context at more than one binding point. For example, a
texture can be bound to TEXTURE_2D_BINDING, and it can also
be indirectly bound through the FRAMEBUFFER_BINDING if it is
attached to the framebuffer object bound to the
FRAMEBUFFER_BINDING.
Furthermore, a texture can be attached (by reference) to a
framebuffer object that is not bound to any context, while
at the same time the texture *is* bound to context's
TEXTURE_2D_BINDING. Because the texture state is a part of
the framebuffer object's state, it is now possible for
modification of a texture through TEXTURE_2D_BINDING to
cause modification of a framebuffer object, even though the
framebuffer object is not bound to any context at the time
it is modified.
One conceptual model for dealing with this situation is to
treat attachment similar to bind, but instead of binding to
a context, you are "binding" to another object. For the
purposes of managing object references, object lifetimes,
state propogation semantics, etc., these attachments can be
considered to be "just like" a bind operation. [A "bind"
and an "attach" are not exactly equivalent, however; see
issue (82) for a further discussion on Bind vs. Attach.]
If we agree on the above conceptual model, then we may wish
to look to the multi-context situation for guidance on how
to treat state changes to non-currently-bound framebuffer
objects.
Unfortunately, the multi-context semantics are poorly
defined by OpenGL. If we decide to use them as a guide, we
should at least define what they are and this is why the
larger ARB is looking at this issue now.
For EXT_framebuffer_object, there are three choices for
behavior. In each case, we defer to the larger ARB the
details about when an object name is available for reuse.
For the purposes of this discussion, we are looking only at
state changes governing the attachments. The three choices
are listed below:
For the sake of concrete simplicity, this discussion
speaks to the images of a texture object; but it applies
equally to the image of a renderbuffer object.
If you delete a texture object while one of the texture's
images is attached to a framebuffer object (or multiple
framebuffer objects), then:
(1) The image is automatically detached from the currently
bound framebuffer object only.
If the image is also attached to any other framebuffer
objects, then the image is NOT automatically detached
from those.
The application is responsible for manually detaching
images from the other framebuffer objects, by
rebinding each framebuffer in turn and performing an
explicit detach operation.
Until the application manually detaches the image from
the other framebuffers, those framebuffers continue to
use the image for rendering. The other framebuffer
objects have a reference to the image until the image
has been detached from them. In this way, attachment
behaves as if the image was "bound to the framebuffer
object".
(2) The image is automatically detached from the currently
bound framebuffer object. Also during DeleteTexture,
the image is automatically detached from any other
framebuffer object to which it is attached; however,
the image is not guaranteed to be detached from the
other framebuffer objects until the next time those
framebuffer objects are bound via BindFramebufferEXT.
Similar to option (1), in order to "really" delete the
object, the application is responsible for rebinding
all the framebuffer objects to which the deleted image
was attached. However, unlike option (1), the
application need not actually perform an explicit
detach operation. The application can merely bind the
framebuffer.
Until the application actually rebinds the framebuffer
the images are not actually detached and deleted. The
other framebuffer objects continue to hold a reference
(like a binding) to the image until the next time the
framebuffer objects are bound.
(3) The image is automatically detached from all
framebuffers objects during DeleteTextures, including
the currently bound framebuffer as well as any other
framebuffers to which the image is attached.
The application need not explicitly bind to, and
detach the image from, any framebuffer that is not
bound at the time DeleteTextures was called.
Because the framebuffer object has a reference to the
texture object, and the texture object's state is
considered part of the framebuffer object's state,
this resolution implies that DeleteTextures may
modifiy the state of a framebuffer object that is not
the currently bound object.
With reference to the object-sharing discussion that is
going on in the ARB right now, for (a)-style
implementations, options (2) and (3) are indistinguishable.
However, for (b)-style implementations, implementing (3)
would require textures to store a list of all attached
framebuffers while (2) would not.
Options (2) and (3) essentially treat the currently-bound
and non-currently-bound framebuffers the same--i.e.,
deleting the image (ultimately) detaches it from all
framebuffer. This may be desirable as a convenience to the
application.
On the other hand, Option (1) treats the currently bound
framebuffer special, in that deletions are performed
automatically much like textures are unbound automatically
from the current context's binding points, but they are not
unbound automatically from other contexts' binding points.
Also, Option (1) leaves the application in control of when
the images are detached, which also may be desirable.
We choose option (1) because it is the simplest, and it also
does not unduly burden implementations regardless of their
choice of (a) versus (b) object-sharing model.
If an implementation has the (a)-style object sharing model,
then the fact that images remain attached to non-bound
objects has no affect on when the object name may be
re-used. If the implementation has a (b)-style
object-sharing model, then the outstanding attachments will
delay re-use of the object name until the image has been
detached. Regardless of whether the ARB chooses (a) or (b)
behavior, or even if the ARB chooses to leave this behavior
undefined, we can "piggy-back" on the name-reuse semantics
they decide.
Also, option (1) means that if the application deletes a
texture while one of the texture's images is attached to a
framebuffer object that is not bound, then the application
may continue to render into the image after the framebuffer
is bound again, regardless of the (a) vs. (b) choice.
Finally, note that if a context deletes an object containing
an image attached to the currently bound framebuffer, then
we first detach the image from the bound framebuffer. This
means that the state change to the framebuffer (the detach
operation) is guaranteed to be picked up by any other
context the next time the framebuffer is bound in one of the
other contexts.
(78) Should we collapse the notions of "framebuffer-attachable image
completeness" and "framebuffer attachment completeness" into a
single type of completeness (probably retaining the name
"framebuffer attachment completeness"
RESOLUTION: resolved, yes, eliminate "framebuffer-attachable
image completeness" and add a "non-zero-area" requirement to
the "framebuffer attachement completeness" test.
Originally this extension had several layers of which
affected framebuffer completness. They were:
- framebuffer-attachable image completeness
* image has non-zero width/height/depth
* image has color, depth, or stencil format
* image is not from a proxy texture
- framebuffer attachment completeness
* attached image is textures/renderbuffer
* attached image is from existing object
* attached image has format appropriate
for attachment point (depth buffer
has depth format, etc)
- framebuffer completeness
* all attachment points are "attachment complete"
* all images are "framebuffer-attachable image complete"
* all color buffers have same format
* draw buffer is attached
* read buffer is attached
* framebuffer format combination is supported
However, upon further reflection of the
"framebuffer-attachable image completeness" tests, we
realized that
a) the requirement that the renderble image is not a
"proxy" texture was already covered by the fact that
it's illegal to attach a proxy texture to a
framebuffer, and
b) the requirement that the format be color, depth, or
stencil is essentially already covered by the
"framebuffer attachment completeness" test
requirement that the format is appropriate for the
attachment point.
This left only the "non-zero-area" test, so we decided to
fold this requirement into the "framebuffer attachement
completeness" test and eliminate the concept of
"framebuffer-attachable image completeness". This decision
required the elimination of one of the
FRAMEBUFFER_INCOMPLETE_* enums as they correspond to the
conditions in the "framebuffer completeness" test of section
4.4.4
(79) Should the internal format chosen by GL for a texture (or
renderbuffer) be invariant with respect to the state of the
current framebuffer and its attached images?
RESOLUTION: yes, the choice of internal format must be
invariant with respect to framebuffer state changes.
This means that the GL must choose texture internal format
based only on the arguments to TexImage and ignore the
current framebuffer state in this selection process.
Similarly, the GL must choose renderbuffer internal format
based only on the arguments to RenderbufferStorage and
ignore the current framebuffer state in this selection
process.
This issue is a variant of issue (62). The OpenGL 2.0
specification (p.152, paragraph 4) states that:
"A GL implementation may vary its allocation of
internal component resolution or compressed internal
format based on any TexImage3D, TexImage2D (see below),
or TexImage1D (see below) parameter (except target),
but the allocation and chosen compressed image format
must not be a function of any other state and cannot be
changed once they are established."
Consider that prior to this extension, some implementations
may have considered the the bitdepths of the logical buffers
of the framebuffer or the bitdepth of the display when
choosing an internal format for textures. Since, in
practice, these bitdepths typically were immutable for the
lifetime of a GL context, the invariance requirements were
met.
With the introduction of EXT_framebuffer_object, however,
the logical buffer bitdepths can change over the lifetime of
the context. So this issue examines whether or not
framebuffer state is allowed to affect texture internal
format selection.
After some discussion, we felt it was too problematic to
introduce this type of invariance. So this extension makes
no modifications to the invariance language, and adds
similar invariance language applicable to renderbuffer
objects. As long as the app provides the same arguments to
TexImage{1D|2D|3D} or RenderbufferStorage, then the GL must
always choose the same internal format.
Note, however, that the GL is not required to provide the
same internal format resolution for renderbuffers as it does
for textures.
(80) Should attachment routines be display-list'able?
RESOLUTION: no, in fact none of the routines introduced in
this extension are included in display lists.
Initially, we were just considering whether or not the
framebuffer attachement routines should be included in
display lists. The rationale for not including them was
that since query routines can not be in display lists, and
well-behaved apps should call the query routine
CheckFramebufferStatusEXT() after calling making changes to
framebuffer attachments, it was not possible to write a
well-behaved app that uses display lists to build up and use
a framebuffer. So, one possible solution was to simply
disallow from display lists the routines that change change
the result of CheckFramebufferStatusEXT().
However, we realized on further consideration that other
routines which can affect the results of
CheckFramebufferStatusEXT are already allowed in display
lists. Namely, the routines which affect textures (TexImage
and friends). So, disallowing the attachment routines is a
partial solution at best.
We also looked for various precedents and found some mixed
results:
- VBO bind operations are not display-list'able, but
this is primarily because the VBO bindings are
considered client-state
- texture bindings are display-list'able
In the end, though we decided to not include the routines
introduced by this extension in display lists for reasons of
simplicity more than anything else.
It's possible we may need to add support for display lists
back in during promotion of this extension if we determine
that it is needed later, but for now, we leave this out.
(81) How should PushAttrib and PopAttrib work with this extension?
RESOLUTION: mostly deferred for now, may revisit later
This extension introduces no new push/pop attrib bits to
cover the state introduced by this extension (for instance
there is no FRAMEBUFFER_BIT). So the only real question to
answer is what effect should Push/Pop attrib have on any
existing state as it relates to this extension.
In particular, how should Push/PopAttrib of the
COLOR_BUFFER_BIT which covers the DRAW_BUFFER and
READ_BUFFER state interact with this extension? Does the
COLOR_BUFFER_BIT affect the per-object DRAW_BUFFER and
READ_BUFFER state?
Currently, the answer is yes. PushAttrib(COLOR_BUFFER_BIT)
saves the DRAW_BUFFER value of the currently bound
framebuffer object. If the app later calls PopAttrib() this
saved value will be restored even if the framebuffer bound
at the time PopAttrib is called is different from the
framebuffer bound at the time PushAttrib was called.
In other words, one are considering whether or not it is
strange that PushAttrib(COLOR_BUFFER_BIT) affects a piece of
per-object state. Note that this is somewhat similar to the
way that a PushAttrib(TEXTURE_BIT) can save off
per-texture-object state and a later call to PopAttrib can
restore that per-object state even if the texture bound at
PopAttrib time has since been changed/ deleted/modified in
some way.
There are some differences with the texture analogy though.
Namely, the TEXTURE_BIT does include the texture bindings so
at least the texture object binding is restored in
conjunction with the per-texture-object state. Also, some
may consider the fact that the TEXTURE_BIT affects
per-texture-object state more intuitive than the fact that
the COLOR_BUFFER_BIT affects per-framebuffer-object state.
Also, there is a larger discussion going on in the ARB right
now about whether PushAttrib/PopAttrib save references to
existing bound objects or only the state values which name
an existing bound object.
For now, we have deferred further discussion of the
PushAttrib/PopAttrib semantics in this extension until the
larger issues are cleared up.
(82) What is the relationship between a "binding" and an
"attachment"?
RESOLUTION: resolved, the concept of attachment is described
below, though final implications will be affected by larger
ARB discussions about object sharing and multiple context
semantics.
"Attaching" is 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 principle,
we treat "A" as if it is <implicitly> bound to "C".
The larger ARB is currently attempting to more clearly
define the mutliple context semantics as they relate to
object sharing and binding. The final implications for
EXT_framebuffer_object may not be clear until those
discussions are resolved. This extension may need an
update once those issues are addressed.
(83) We use a non-zero framebuffer binding to enable the use of this
extension. Should we instead consider using an explicit
enable?
RESOLVED: no, retain the "non-zero-binding means enable"
semantics.
Currently we enable the use of an application-created
framebuffer by binding a non-zero framebuffer object to
FRAMEBUFFER_EXT binding point. If the framebuffer binding
is zero, then the extension is disabled (i.e., we use the
window-system-provided framebuffer).
It might be cleaner to be able to say things like, "when
FRAMEBUFFER_OBJECT is enabled", rather than "when the
framebuffer binding is not zero", and add an explicit
enable. Doing so would also allow changing framebuffer
object attachments while FBO is disabled, which might result
in the driver doing less validation while the application is
setting up framebuffer objects. It would also provide a
cleaner way to explain that the permitted DRAW_BUFFER and
READ_BUFFER values change when the extension is
enabled/disabled.
There are a few object model precedents to choose from:
Textures and ARB Vertex and Framgment Program extensions use
the explicit enable state. However, Vertex Buffer Objects,
Pixel Buffer Objects, and GLSL Vertex and Fragment shaders
use a non-zero-binding to enable the use of those features.
If we used an explicit enable, then we could allow creation
of an object named zero. Precedent dictates that an object
named zero is never shared in the context share group. All
other framebuffer objects are shared across the share group.
It might be cleaner to disallow creation of an object named
zero anyway.
Since binding to zero disables the extension, one way to
think about this is that there is an object named zero which
is managed through MakeCurrent, MakeContextCurrent, and the
window manager. All other objects are managed through
FramebufferTexture, FramebufferRenderbuffer, and the
operations that define/modify texture and renderbuffer
images. When looked at in this light, lack of an explicit
enable is not as strange.
(84) Do we need to add any language to describe the y-orientation of
framebuffer-attachable images? Specifically, what coordinate
system is used by images attached to the framebuffer?
Resolution: unresolved
GL defines the rendering origin at the lower-left corner.
Yet, because of the differences between orientation storage
of textures and images, pbuffer rendering is often
implemented using a "y-inverted" coordinate system. Is this
y-inversion exposed in the API?
Is the origin in the lower-left? Upper-left? Do we need to
say anything about this at all, or is it already covered by
existing GL language?
Currently there is place-holder text in section 4.4.2.3
The intent of this specification is simply to mirror the
y-orientation issues of the pbuffer style render to texture
API's. What's unclear is whether this requires any new
language in this specification or not.
(85) Explain what happens when the FBO has a different width/height
from the window?
An FBO takes on the width/height of its attachments. This
width/height can be different than the width/height of the
window (of framebuffer "zero").
In such cases, after calling BindFramebuffer, it is the
application's responsibility to set the glViewport and the
glScissor (if necessary) to match that of the new
framebuffer binding.
Some background: The default viewport for a context is
defined by the dimensions of the window to which the context
is first made current. When the window is resized, or when
the context is bound to a different window, the viewport
does not change automatically. It has always been the
application's responsibility to set the viewport after one
of these events. FBO is no different; after BindFramebuffer
it is the application's responsibility to set the viewport
if the new framebuffer binding has a different width/height
than the old binding..
(86) Are any one- or two- component formats color-renderable?
Presently none of the one- or two- component texture formats
defined in unextended OpenGL is color-renderable. The R
and RG float formats defined by the NV_float_buffer
extension are color-renderable.
Although an early draft of the FBO specification permitted
rendering into alpha, luminance, and intensity formats, this
this capability was pulled when it was realized that it was
under-specified exactly how rendering into these formats
would work. (specifically, how R/G/B/A map to I/L/A)
To resolve this we seem to have two options:
A) Add new R and RG formats like NV_float_buffer did.
B) For the existing one- and two- component formats, define
the mapping from RGBA components to ILA components.
The superbuffers group has informally decided that option A
is preferable.
(87) What happens if a single image is attached more than once to a
framebuffer object?
RESOLVED: The value written to the pixel is undefined.
There used to be a rule in section 4.4.4.2 that resulted in
FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT if a single
image was attached more than once to a framebuffer object.
FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
* A single image is not attached more than once to the
framebuffer object.
{ FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT }
This rule was removed in version #117 of the
EXT_framebuffer_object specification after discussion at the
September 2005 ARB meeting. The rule essentially required an
O(n*lg(n)) search. Some implementations would not need to do that
search if the completeness rules did not require it. Instead,
language was added to section 4.10 which says the values
written to the framebuffer are undefined when this rule is
violated.
Revision History
#123, October 6, 2016: Jon Leech
- Remove STENCIL_REF from list of state moved to become framebuffer
dependent (Bug 8422).
#122, May 3, 2016: Kevin Rogvin, James Jones
- Specify behaviour of mixing EXT and ARB_framebuffer_object /
OpenGL 3.0 framebuffer objects so that the aliases of the
functions are correctly observed (Bug 1485)
#121, September 23, 2013: Jon Leech
- Specify that undefined behavior results when mixing EXT and
ARB_framebuffer_object / OpenGL 3.0 API framebuffer objects
(Bug 10738).
#120, April 22, 2008: Jeremy Sandmel & Jon Leech
- Update errors section so detaching renderbuffers and textures
using object name zero is not an error.
#119, February 13, 2007: Jon Leech
- Corrected typos in 'GenerateMipmap'.
#118, April 5, 2006: jjuliano
- Improve language related to which formats are
color-renderable, and describe format conversions when reading
from and writing to the framebuffer. Lays groundwork for
making additional formats color-renderable.
- Add section 4.4.6.
- Selecting same attachment multiple times via DRAW_BUFFERs
writes undefined value to the buffer.
- Clarify effect of framebuffer completeness on values of state
table 9.nnn.
- Describe interaction with NV_float_buffer and
NV_texture_shader.
#117, September 26, 2005: jjuliano
- Remove FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT.
- Add language to section 4.10 explaining that duplicate
attachments result in undefined behavior
- Add issue (87) to discuss the change.
- List EXT_packed_depth_stencil as affecting this extension.
#116, September 16, 2005: jjuliano
- Add example (8) demonstrating FBO + ARB_draw_buffers.
- Add issue (85) discussing window and FBO of different sizes.
- Add issue (86) about one- and two- component texture formats.
- State that OpenGL 1.1 is required.
#115, July 25, 2005: jjuliano
- Improve wording around ReadPixels of color data while
READ_BUFFER is NONE. (INVALID_OPERATION). Clarify that it is
legal to read depth/stencil while READ_BUFFER is NONE.
- In section 4.4.4.2 (Framebuffer Completeness), clarify that
READ_BUFFER can be NONE, and if NONE then framebuffer
completeness does not require a color attachment.
#114, June 16, 2005: jjuliano
- Eliminate the name STENCIL_INDEX_EXT. The name STENCIL_INDEX
is already defined in the core specification.
- Add some missing errors to the errors section.
- Add _ARB suffix to TEXTURE_RECTANGLE, and describe interactions
with ARB_texture_rectangle.
- In errors section, say that it is an error if cube map texture
passed to GenerateMipmapEXT is not cube complete.
#113, May 27, 2005: jsandmel, jjuliano, chris niederauer, alex eddy, barthold lichtenbelt
- improved langage and added some tables (10.nnn and 11.nnn) in
another attempt to clarify the DrawBuffer(s)/ReadBuffer error
semantics
- added additional errors to the summary at the end
- fixed typo in FramebufferTexture3D where <zoffset> was
compared against MAX_3D_TEXTURE_SIZE and should have been
compared against (MAX_3D_TEXTURE_SIZE - 1).
- note that issue (21) is a duplicate of issue (77) and
mark issue (21)'s resolution with a reference to issue (77)
- the resolution of issue (75) indicated that STENCIL_REF is now
dependent on the current framebuffer state, but STENCIL_REF
was inadvertantly left off of table 9.nnn
- fixed the bullet item in section 4.4.1 that stated that when bound to
an application-created framebufer, the value of SAMPLES is 1.
it should have said 0.
- added missing queries of renderbuffer bit depths that were
inadvertantly left out of the spec.
#112, April 28, 2005: jsandmel, jjuliano, chris niederauer
- updated contributors list
- Improve language pertaining to "render to texture source" loop.
- Fixed typo where CheckFramebufferStatusEXT was accidentally
listed twice in additions to chapter 5's list of
non-display-listed commands
- fixed typo in prototype conventions
- as per workgroup meeting decision on April 4, 2005,
DrawBuffer(s) and ReadBuffer no longer generate an error when
specifying an attachment point for which there is no image
attached. The rationale is that the user can always attach
(or detach) after DrawBuffer(s)/ReadBuffer is called anyway.
We retain the test in CheckFramebufferStatusEXT that makes
sure the buffers are attached prior to rendering, however.
- as per workgroup email list discussions April 20, 2005, added
BindFramebuffer/BindRenderbuffer to the list of
display-listable functions. They were inadvertantly left off
the list. Adding them back to be consistent with resolution
of issue (80).
- added missing language to FramebufferTexture discussion to
correct section where we compared width/height/level values to
MAX_TEXTURE_SIZE instead of MAX_CUBE_MAP_TEXTURE_SIZE for cube
maps attached to framebuffer.
- as per workgroup meeting decision on April 26, 2005,
CheckFramebufferStatusEXT will generate an error if called
within a Begin/End pair, since it is (intentionally) not
listed in the exclusion list for functions that can be called
within Begin/End in section 2.6.3
- as per workgroup meeting decision on April 26, 2005, since
section 2.6.3 states that routines that return a value should
return 0 if the routine generates an error,
CheckFramebufferStatusEXT should return zero and not
FRAMEBUFFER_STATUS_ERROR_EXT. Since we don't need
FRAMEBUFFER_STATUS_ERROR_EXT anymore, we are removing this
enum from the spec.
- added missing error language to spec body and fixed incorrect
language in "Errors" section to clarify that specifying enums
to DrawBuffer(s) and ReadBuffer that are NEVER legal is an
INVALID_ENUM, while specifying values that only illegal
because of the current framebuffer binding are an
INVALID_OPERATION.
- Fix minor typos in DrawBuffer(s) and ReadBuffer definitions.
#111, February 28, 2005: jjuliano, jsandmel
- Add example 7 illustrating "depth-only" framebuffer object.
#110, February 28, 2005: jsandmel, jjuliano, brian paul
- no functional changes
- integrated Brian Paul's fixes for typos and noted
that invalid operation is generated if the <textarget>
and type of texture don't match in FramebufferTexture
- default internalformat for renderbuffer is RGBA not "1" since
"1" is not a legal internalformat for renderbuffers
- note that the unsinged base internal formats of RGB, RGBA,
DEPTH_COMPONENT, and STENCIL_INDEX are legal internal formats
for renderbuffers. They were intended to be legal all along
but the language indicated otherwise.
#109, January 31, 2005: jsandmel, jjuliano
- added language to issue (48) to indidcate that
CheckFramebufferStatus will return an undefined result for a
framebuffer in the intial state since a framebuffer in the
initial state violates multiple completeness rules
#108, January 31, 2005: jjuliano
- fix typos pointed out by various people (thanks)
#107, January 17, 2005: jjuliano, jsandmel
- fix resolution of issue (28) to say "zoffset", not "image"
- more cleanup of issue resolutions
#106, January 17, 2005: jjuliano
- per working group decision, clean up issue resolutions
- minor whitespace and punctuation cleanup
#105, January 17, 2005: jjuliano
- add XXX documenting "undefined-ness" of rendering
vs. texturing
- minor language clarification and typo fix
#104, January 14, 2005: jjuliano, jsandmel
- white space clean up (plus a few capitalizations)
- no functional changes in this revision
#103, January 14, 2005: jjuliano, jsandmel, barthold lichtenbelt, jon leech
- add missing "NONE" case to DrawBuffer language
- permit ReadBuffer(NONE) for application-created framebuffers
- spec body: actually state that DrawPixels, ReadPixels,
CopyPixels, and derivatives of CopyPixels all generate
INVALID_FRAMEBUFFER_OPERATION_EXT if called while framebuffer
is not complete
- clarify error semantics for DrawBuffer(s) when there is no
image attached to the framebuffer attachment point named by
DrawBuffer(s)
- improve error language regarding the <level> parameter of
FramebufferTexture
- State that table 4.nnn is part of the per-framebuffer-object
state vector
- Delete dangling references to table 3.nnn
- In section 4.4.4.2, adjust wording to understand that
DeleteTextures deletes an object, not image
- Convert some left-over window-system-* to
window-system-provided
- Adjust some whitespace and punctuation
- renumbered tables to remove the hole now that the old table of
CheckFramebufferStatus enums has been deleted.
- incorporate remainder of barthold's edits removing more
"framebuffer-attachble" references from the issues list
- moved comment describing the purpose of the
CheckFramebufferStatus enums in the framebuffer completeness
test closer to their initial use in the spec.
- Eliminate two XXX comments that addressed by this revision
#102, January 13, 2005: jjuliano, jsandmel, barthold lichtenbelt, jon leech
- replacement of "renderable image" with "framebuffer-attachable
image"
- removed lots of (now redundant) instances of
"framebuffer-attachable"
- streamlined the grammar in several places to account for
"framebuffer-attachable" change
- incorporated outstanding edits from barthold's review of #73
and #98
- made FramebufferTexture and FramebufferRenderbuffer use "uint"
for texture and renderbuffer names for consistency with
Gen/Is/Bind/Delete. For some reason, in revision #77 we
had incorrectly changed these from uint to ints.
- renamed FRAMEBUFFER_INCOMPLETE_MULTIPLE_ATTACHMENT to
FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT
- fixed DeleteTextures and DeleteRenderbuffers language to
reflect resolution of issue (77), by adding forward reference
to the section that describes attachment (that already had
that right language).
- fixed the different language in FramebufferRenderbuffer and
FramebufferTexture that described the state when binding a
zero object (dropped the reference to object type of NONE
since that *is* the default and it already said the state was
set to default values)
- reworked section 4.4.2 overview to simplify intro to
attaching images to framebuffers
- reworded intro to section 4.4.2.1 Renderbuffer Objects
- fixed several instances of "render buffer" to "renderbuffer"
- replaced language in framebuffer attachment routines that
bounded the upper value of <level> to use the parallel
language from page 185 of the OpenGL 2.0 spec.
- simplified first clause of framebuffer compelteness test to
just require at least one image attached to framebuffer
- reordered CheckFramebufferStatusEXT section and moved
description of FRAMEBUFFER_UNSUPPORTED_EXT to be part of
framebuffer completeness section description
- deleted table 3.nnn which lsted the return values of
CheckFramebufferStatusEXT since this info is already included
in the framebuffer completeness test itself and was really
just a duplicate copy in table form.
- added several errors which were missing from the error summary
at the end of the spec
#101, January 12, 2005: jjuliano, jsandmel
- Clarify language related to BindRenderbuffer(<target>, 0)
- Small grammatical change related to object vs. object's image.
#100, January 11, 2005: jsandmel, jjuliano
- added new enums and clauses to framebuffer completeness test
to catch mutliple and missing attachements
- reshuffled existing enums to account for new enums
- clarified issue (84) it indicate that the intent is to mimic
the pbuffer orientation style
#99, January 11, 2005: jsandmel, jjuliano
- use more expelict language mapping window coordinates to
texture image texels at the end of section 4.4.2.3
- fixed typos
- coalesced interactions with AGL/GLX/WGL with interactions with
WGL/GLX_make_current_read extensions
- addressed and removed some more remaining XXX comments
- added note to issue (58) saying that {Copy}TexSubImage
uses negative offsets to address border texels
- added issue (84) - do we need any language describing
orientation of renderable images? (I.e., are they y-inverted?)
#98, January 7, 2005: jsandmel
- remove more outstanding XXX comments
- updated section 4.4 to better define applicatino-created and
window-system-provided framebuffers in the overview of
framebuffer objects
- further clarifications to issue (49) concerning MRT support
- removed stale XXX comment from issue (75) about stencil mask
language
#97, January 7, 2005: jjuliano
- Resolve some XXX comments, by adding missing spec language and
clarifying existing spec language.
#96, January 6, 2005: jjuliano, ian romanick
- renumbered sections to reflect earlier removal of the section
on renderable image completeness.
- fixed prototype of CheckFramebufferStatusEXT in spec (bool->enum)
#95, January 6, 2005: jsandmel, jjuliano
- added missing change notes from #94
- fixed more typos
- updated issue (48) - it had been resolved already but need
some updated some language from the resolution to reflect our
final decision
- marked issue (55) as resolved (it had been resolved a while
ago but was left as unresolved)
- resolved issue (82) - bind vs. attach. final spec
implications may get updated when we resolved the larger ARB
discussions over multicontext behavior and object sharing
#94, January 4, 2005: jjuliano
- language clarification and word smithing.
- note that rendering to the border of a texture uses
an origin within the border texels
- updated comments in sample code for clarity
- updated issue (16) to clarify how CopyTexImage possibly
affects framebuffer completeness, and simplified remaining
language
- updated issue (77) to better capture the effects of
deleting attached renderable images
- updated issue (79) to better capture the invariance of
renderable image internal format selection
- added additional clarifications to issue (83) to describe how
an explicit enable/disable API would work
#93, December 23, 2004: jsandmel
- improved stencil ref value clamping language yet again to
indicate that queries are clamped
- moved old XXX comment about an explicit enable into a new
resolved issue (83)
- removed a condition of framebuffer attachment completness
concerning the legality of the LEVEL param which I
overzealously added in revision #92
- resolved issue (77) - images are detached from current
framebuffer only, user must do manual detachment for
non current framebuffers
- clarified issue (79) to note that GL need not choose the same
format for both renderbuffers and textures as the text seemed
to imply before.
- clarified issue (16) to note that state changes to non-bound
framebuffers are somewhat similar to state changes made by
another context to shared objects (possibly) bound by this
context.
- clarified resolution of issues (15) and (16) which talk about
how {Copy}TexImage into textures affect the framebuffers to
which textures are attached.
#92, December 23, 2004: jsandmel
- updated "Dependencies" section to add descriptions for
interactions with other extensions
- fixed a stale reference to "accum" in overview
- improved language in overview that seemed to imply that
this extension required a data copy to do render to texture
- removed stale XXX comment about framebuffer sharing since
issue (76) is resolved
- added proposed language for "attach" definition in glossary
- removed stale glossary entry for "renderable image completeness"
now that issue (78) is resolved
- Updated chapter 2 to use proposed language changes describing
interactions with the framebuffer in the context of this
extension.
- clarified that GenerateMipmap only requires cubemap textures
to be cubemap complete
- removed unnecessary reference to proxy texture in GenerateMipmap
- clarified language about stencil ref value clamping
- removed various other stale XXX comments
- added note that RENDERBUFFER_BINDING_EXT can be queried
- included alternate beahviors in language influenced by issue
(77)
- defined the error that occurs on FramebufferTexture when
a level is specified that is too big
- added requirement to framebuffer attachment completeness
that FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT must be
less than q for symmetry with the requirement that the
z-offset is smaller than the depth of the texture
- added section numbers to state tables
- indicated there are no attribute bits for the state tables
- added proposed language for issue (82)
- added proposed language for issue (77)
#91, December 22, 2004: jsandmel
- added updated stencil language to reflect resolution of
issue (75) - stencil ref value and writemask clamping
- added language to section 4.4.2.1 indicating that internal
format selection for renderbuffers follows the same invariance
rules as textures
- updated framebuffer completeness language to reflect resolution
of sissue (78)
- added test to framebuffer attachment completeness indicating
that the z-offset identifying an image within a 3D texture must
be less than the texture's depth
- added routines to list of non-display-list'able routines
as per resolution of issue (80)
- deleted note about OpenGL ES in issue (76)
- cleaned up the proposed language for issue (77) based on
feedback from Jeff Juliano
#90, December 22, 2004: jsandmel
- removed plural from FRAMEBUFFER_INCOMPLETE_ATTACHMENT[S]
- added FRAMEBUFFER_STATUS_ERROR_EXT to enumerants list
- resolved issue (78) - collapsing "renderable image
completeness" test and removed FRAMEBUFFER_INCOMPLETE_IMAGES
enum as per meeting Dec. 21, 2004
- fixed up some typos
- wrote up and resolved issue (76) - framebuffers are shared
like textures as per meeting Dec. 21, 2004
- wrote up issue (77) - detachment on deletion
- wrote up and resolved issue (79) - textures are invariant
with respect to framebuffer state
- wrote up and resolved issue (80) - no routines in this
extension are display-list'able
- wrote up and deferred issue (81) - push/pop attrib
- added issue (82) - bind vs. attach defintions
#89, December 16, 2004: jjuliano, jsandmel, ian romanick
- added glx protocol for this extension
- added issue (75) - stencil ref value and write mask state
- added issue (76) - sharing framebuffer objects
- added issue (77) - deletes affect on detaching images
- added issue (78) - collapsing "completeness" tests
#88, December 06, 2004: jjuliano, jsandmel
- revised examples again for clarity, added example (6) to show
one way to handle CheckFramebufferStatusEXT
#87, December 03, 2004: jjuliano, jsandmel
- incorporated language edit feedback from john rosasco
- changed a few instances of "rendering to texture" to "render
to texture"
- added XXX notes about sections that still need cleanup
- clarified definition of renderbuffer and its image in overview
- clarified comparison of MakeCurrent and BindFramebuffer in
overview
- fixed misc typos
- renamed TEXTURE_ZOFFSET to TEXTURE_3D_ZOFFSET for consistency
with TEXTURE_CUBE_MAP_FACE
- added note to update section 2.1 to talk about configuring
framebuffer (need forward reference to chapeter 4).
- changed several instances "the GL is using ... framebuffer" to
"the GL is bound to ... framebuffer"
- changed several instances of "When [A], if [B], [C]" into "If
[A] and [B], then [C]"
#86, December 02, 2004: jon leech
- assigned "real" enum values
- fixed some minor typos
#85, December 01, 2004: jjuliano, jsandmel
- Improve error checking in examples
- whitespace cleanup
#84, December 01, 2004: jjuliano
- DrawBuffer(s) while bound to user-created framebuffer object
generates an error if the named color attachment does not have
have anything attached to it when DrawBuffer is invoked.
- Likewise for ReadBuffer.
#83, November 30, 2004: jjuliano
- improve wording of issue (28) - zoffset vs image of a
3-dimensional texture
- update examples to use the new attach target enums, and
to check framebuffer status
#82, November 30, 2004: jsandmel
- renumbered tables to start with 1.nnn instead of 2.nnn
- resolved issue (74) - return value of CheckFramebufferStatus()
- re-opened and re-resolved issue (28) - zoffset vs image of a
3d texture
- fixed reference of CopyTexImage to CopyTexSubImage in intro
- added 16 enums for COLOR_ATTACHMENTn_EXT as per meeting
november 29, 2004
- clarified language about number of attachment points in
description of BindFramebufferEXT().
#81, November 30, 2004: jsandmel
- re-added *-renderable clause to "renderable image completeness"
test.
- clarified language in intro that describes selecting an
image from a texture
- fixed a few more typos
#80, November 30, 2004: jjuliano
- Improve definition of CheckFramebufferStatusEXT.
FRAMEBUFFER_STATUS_ERROR_EXT is returned if <target> is
invalid. Framebuffer zero always produces
FRAMEBUFFER_COMPLETE_EXT.
- Rename 3D_IMAGE to ZOFFSET. More consistent with
CopyTex(Sub)Image.
- In definition of GetFramebufferAttachmentParameterivEXT,
explain that zero is returned when face or zoffset is queried,
but texture is not cube map or 3-dimensional, resp. This
matches the informal description in issue (51).
- Eliminate table 1.nnn, and modify references to instead
reference table 6.nnn. I have not renumbered all the tables
yet, so that the diffs are more obvious. Renumbering can
happen in the next change.
- Eliminate *-renderable clause from Renderable Image
Completeness. This is already covered under Framebuffer
Attachment Completeness.
- For each clause in Framebuffer Completeness, add references to
specific error generated when that clause is violated.
#79, November 23, 2004: jsandmel, jjuliano
- more typos fixed
- added placeholder enumeration of all tables so that every
table was not named XXX.XXX. They are now named M.nnn where M
is incremented sequentially for each table.
- stated that order of return of CheckFramebufferStatus enums is
"implementatino-dependent" instead of "undefined"
- added state table for framebuffer object state (as opposed to
table of framebuffer attachment point state), added
DRAW_BUFFERi and READ_BUFFER state to this table.
#78, November 22, 2004: jsandmel
- re-opened and re-resolved issue (4) - renamed
"renderable-images" to "framebuffer-attachable images"
- resolved issue (70) - defer support of framebuffer binding
push/pop semantics
#77, November 22, 2004: jsandmel, jjuliano
- fixed up typos and address other issues found by Barthold
- changed errors of GetFramebufferAttachmentParameterivEXT
to be INVALID_ENUM instead of INVALID_VALUE where appropriate
- added missing INVALID_ENUM GetRenderbufferParameterivEXT error
case to list of errors
- dropped framebuffer status state from state table (The reason
is: technically this is not state queriable with a standard
Get call and doesn't really need to be stored, an
implementation could calculate this result on the fly in
principle.)
- added issue (74) - what does it mean to call
CheckFramebufferStatusEXT on framebuffer zero (default
framebuffer) and what if CheckFramebufferStatusEXT generates
an error?
- cleaned up a bunch more "window-system-provided" references
- changed a bunch of "bit plane" references --> "bitplane"
- more updates to glossary section (not complete yet)
- Added boolean return values to IsRenderbuffer and
IsFramebuffer prototypes
- Changed object id's in FramebufferTexture* and
FramebufferRenderbuffer from uint to int to be consistent with
texture routines.
- changed typo in Get*Parameter routines: "param" --> "params"
- added missing COLOR_ATTACHMENTn_EXT enums to new tokens list
- clarified difference and similarities between automatic and
manual mipmap generation in section 3.8.8
- added lots of missing EXT's
- clarified use of <textarget> in FramebufferTexture when
<texture> is zero and <renderbuffer> target in
FramebufferRenderbuffer when <renderbuffer> is zero.
(<textarget> and <renderbuffertarget> are ignored in this case>
- added a sentence defining that order of return for enums in
CheckFramebufferStatusEXT is undefined if multiple clauses of
framebuffer completeness test fail
#76, November 19, 2004: jsandmel
- as per group meeting Nov. 19, 2004, rename "render buffer" to
"renderbuffer". This is the only substantive change in this
revision. Unfortunately, this had a lot of white-space
collateral damage. Also, this reopens and closes issue (3).
#75, November 18, 2004: jsandmel
- added missing enums to New Tokens section
- clarified wgl/agl/glx language additions section to note that
the window-system draw/read drawables are ignored when bound
to an application-created framebuffer object
- resolved issue (69) - "application-create" framebuffers
- added more description of issue (70) - push/pop binding bits?
- resolved issue (71) - defining which draw/reading routines can
throw errors
- resolve issue (72) - require at least one color, depth, or
stencil attachment
- resolved issue (73) - allow READ_BUFFER to be none so
user can read from a non-color buffer in a framebuffer
with no color attachments
- added section on ReadBuffer whose absence had unfortunately
gone unnoticed until now.
- added missing "initial state" language for draw buffer to
section 4.2
- cleaned up several references to FRAMEBUFFER_EXT that should
have been either "the target FRAMEBUFFER_EXT" or
"FRAMEBUFFER_BINDING_EXT"
#74, November 18, 2004: jsandmel, jjuliano
- fixed up typos found by Ian Romanick
- changed several instances of "GL-allocated framebuffer" to
"application-created framebuffer" for consistency.
NOTE: However, we might want to pick a new term for these
everywhere. Added issue (69) for this.
- added a MAX_RENDERBUFFER_SIZE_EXT implementation constant
to catch errors to RenderbufferStorageEXT.
- added issue (70), (71), (72), (73) for issues found
by Jeff
#73, November 15, 2004: jsandmel
- split out CheckFramebufferStatus enums as per work group
meeting November 15, 2004
- added note to self to go back and clean up issue (48)
#72, November 15, 2004: jsandmel
- added "valid draw/read buffer" test to framebuffer
completeness test as per resolution of issue (55) as per
meeting on November 11, 2004.
- added new enums to CheckFramebufferStatus for each of the
implementation-independent failure cases as per resolution of
issue (55) as per meeting on November 11, 2004.
(these may be placeholder names for now)
- added additional partial resolutions to issue (55) as
per meeting on November 11, 2004
- added XXX note to update state tables with whatever the
final final resolution of the DRAW_BUFFER location is.
#71, November 9, 2004: jsandmel
- cleaned up contributors list
- resolved issue (61) on minimum requirements as per work group
meeting on November 6, 2004
- added partial resolution and additional description to
issue (55) as per meeting on November 8, 2004
#70, November 2, 2004: jsandmel, jjuliano
- clarified opening language of chapter 4 to name non-visible
buffers
- improved language about when the number of bits in a bitplane
can change
- removed "SUBPIXEL_BITS" from table of state that can change
on framebuffer state change as per working group
meeting November 1, 2004 and marked issue (62) as resolved
- marked issue (56) - draw buffer state location as framebuffer
object state as per working group meeting November 1, 2004
#69, November 1, 2004: jsandmel
- added placeholder "min requirements" text to issue (61)
- marked issue (68) as resolved since it was resolved during
week of Oct 18, 2004.
- incorporated feedback from Brian Paul on various typos,
prototype mismatches, missing "EXT"s, and missing
IsRenderbuffer language (to chapter 6)
- added missing IsFramebufferLanguage to chapter 6
#68, October 29, 2004: jjuliano, jsandmel
- additional clarifications to opening of chapter 4
- various other minor word substitutions
#67, October 28, 2004: jjuliano
- additional clarifications to issue (56)
#66, October 27, 2004: jsandmel
- added most (all?) of the necessary state tables to the end of
the spec (also removed old state table notation)
- made references to the state tables as 6.3XX until we know the
final table numbering
- fleshed out the language of the intro to chapter 4 describing
the color logical buffers and attachable color buffers
- at the beginning of chapter 4, modified core spec language to
note that the bitplane depths are no longer fixed
- moved XXX note about invariance to end of start of chapter 4
- slightly reworded description of FRAMEBUFFER_UNSUPPORTED_EXT
- moved table of "framebuffer dependent state variables"
from spec body into state tables at end of spec
- added most (all?) of the known errors to the "Errors"
section of the spec.
#65, October 25, 2004: jsandmel
- changes to resolve issue (67) - ValidateFramebuffer is now
called CheckFramebufferStatus().
- updated section 4.2.1 to include DrawBuffers (plural) language
from OpenGL 2.0 spec. Note: we either need to update whole
spec to be based on OpenGL 2.0 spec, or else revise the
DrawBuffer(s) language to refer to the ARB_draw_buffers
extension sepc language.
- added (possibly temp) reference to errors on ReadPixels when
using an incomplete framebuffer
- added note to section 4.4.1 that describes pixel ownership
test success when using application-created framebuffers
- added table of enum values returned from
CheckFramebufferStatus() as per resolution of issue (48)
- resolved issue (65) - name of error on incomplete framebuffer
operations
- clarified that issue (24) is really a duplicate of (64).
- resolved issue (48)
- added note to write up issue (61) language for review
#64, October 19, 2004: jsandmel, jjuliano
- more rewording and clarifications of issue (56)
#63, October 15, 2004: jjuliano
- more rewording and clarifications of issue (55) and (56)
#62, October 14, 2004: jsandmel
- more rewording and clarifications of issue (55) and (56)
#61, October 13, 2004: jjuliano
- Dramatically reword issues (55) and (56).
- Add issue (68) addressing which levels are generated by
GenerateMipmapEXT
#60, October 11, 2004: jsandmel
- revised write up of issue (56) to capture recent work group
discussions about draw buffer state location
- resolved issue (48) as per work group meeting Oct. 11, 2004
#59, October 11, 2004: jjuliano
- added note about possibly wanting to have explicit enable for
framebuffer objects instead of using zero in section 4.2.1
- cleaned up list of differences between framebuffer object and
default framebuffer
- separated out attach/detach cases in list of diffs between
default framebuffer and framebuffer objects
- added reminder note about invariance clause modifications
for section 4.4.5
- added reminder note about modifications for wgl spec
- cleaned up language in issue (26) about reading from
incomplete framebuffer
- clarified resolution of issue (44) - texture from destination
- replaced various instances of framebuffer "invalid" with
framebuffer "incomplete"
- other misc. typos, white space clean up
#58, October 8, 2004: jsandmel, jjuliano
- reopened and resolved issue (26) - incomplete framebuffer
read is an error?
- reopened, updated, and resolved issue (44) - "texture from
destination" is undefined
- marked issue (50) as resolved, since it basically was
- updated and resolved issue (64) - incomplete framebuffer
rendering is an error?
- tentatively resolved issue (65) - name of error when
trying to use an incomplete error
- resolved issue (66) - clarified what state can
cause framebuffer incompleteness
- created issue (67) - name of ValidateFramebuffer
- implemented preliminary draw buffer language in section 4.2.1
- added more language in section 4.4.1 to describe differences
between window-system and application-created framebuffers
- updated "texture-from-destination" language in section 4.4.3
to reflect new resolution of issue (44).
- removed clause describing "texture from destination"
constraints from framebuffer completeness test in section
4.4.4.1 to reflect resolution of issue (44).
- added list of operations which can change framebuffer
completeness to section 4.4.4.2
- Added language to section 4.4.4.3 indicating that rendering to
or reading from an incomplete framebuffer is an error, as per
resolution of issue (64) and (26)
- Added more description of implementation dependent state which
can change in section 4.4.5 and refer to framebuffer
completeness section in 4.4.4.2 to identify when this state
can change
- added MAX_COLOR_ATTACHMENTS to list of state variables that
might change if framebuffer state changes
- added error conditions to queries when framebuffer zero or
renderbuffer zero is bound (since there is no framebuffer
zero or renderbuffer zero).
- added placeholder for Additions to the AGL/GLX/WGL
Specifications
- fixed up misc. typos and whitespace
#57, October 1, 2004: jjuliano
- added additional discussion in issue (66)
- fixed up misc. typos and whitespace
#56, September 29, 2004: jsandmel
- added additional option (d) to issue (66) as per our work
group discussions on Sept 30, 2004.
#55, September 29, 2004: jsandmel
- added meta-issue (66) which deals with framebuffer
completeness dependencies on the context state.
- added section 4.4.5 about state variables which may change if
framebuffer state changes.
- dropped some redundant exposition in issue (55)
- resolved issue (60) and wrote up the description of the issue
- removed ACCUM_FORMAT from list of new enums per resolution of
issue (40)
#54, September 27, 2004: jsandmel
- added issue (64) - error to render with incomplete framebuffer?
- added issue (65) - what should the error be?
- added note to ask if we need to reopen (26) about reading
from invalid framebuffer in light of resolution of (64).
#53, September 17, 2004: jsandmel
- updated "attach" definition in glossary
- fixed up some minor typos, whitespace issues
- in issue (15)/(16) indicate tex state changes can affect
framebuffer completeness, not just cause it to fail (they
might cause it to succeed).
- add clarification about the type of intrinsic buffers that
were removed in issue (36)
- updated language describing use of ACCUM format for textures
in issue (40)
- reworded reference to "billboarding" in issue (42)
- clarified the draw buffer(s) issue (55) to indicate
possible problems even after DrawBuffer(s) is called.
- pacified some of the language surrounding issue (63) and the
rationale for using ValidateFramebuffer or a GetInteger style
query.
#52, September 17, 2004: jjuliano
- edits based on review of a subset of the issues section
- edits to the diffs from version #51
- added note to overview comparing render-to-texture to
CopyTexImage
- added "attach" term to glossary section
- replaced ARB's with EXT's in issue (1)
- distinguished between bind and attach in isuse (5)
- various replacements of "texture" with "texture image"
- various replacements of "framebufer (in)valid" language with
framebuffer (in)completeness language
- added additional rationale to issue (18) about framebuffer
renderable image attachment
- clarified issue (27) that the resolution is no error is
generated
- added note to issue (40) that we might want to use ACCUM
format for textures
- added description of complications with having draw and read
framebuffer targets in issue (42)
- added additional language describing issue (63) concerning the
reasons for using ValidateFramebuffer versus the reasons for
using an explicit query API for framebuffer completeness.
#51, September 16, 2004: jsandmel
- resolved issue (26) - reading from incomplete framebuffer
- clarified issue (55) - draw buffer set to non-existent buffer
- added issue (63) - should we make ValidateFramebuffer a query?
- marked issue (46) as resolved, since there's not much left to
do except resolve the minimum requirements issue (61).
#50, September 16, 2004: jjuliano
- edits based on version #49 diffs, as well as...
- replace uses of "fail ValidateFramebuffer" with references to
"framebuffer completeness"
- reformat whitespace of some very long and very indented issues
- remove "MERGE from some other proposed API" comments
#49, September 16, 2004: jsandmel
- added DeleteTexture and DeleteRenderbuffers spec language to
describe detaching from framebuffers first
- added place holders in various places to correspond
with lots of resolved issues
- added stencil S format table
- renamed section 4.4.3
- clarified framebuffer attachment and renderable image
requirements for completeness
- added requirement to completeness to have all
color attachments with the same format
- added missing write ups for various issues (8), (9), (12)
- in issue (40), clarified that accum language from 1.5 spec
already covers the error behavior we need to defer accum support
- in issue (41), clarified multisample language from 1.5 could
cover the behavior we need to defer multisample support if we
set SAMPLE_BUFFERS to 0 for non-default framebuffers
#48, September 15, 2004: jjuliano
- edits based on review of chapter 4.
#47, September 15, 2004: jjuliano
- edits based on review of all sections except for chapter 4,
Issues.
- clarified, reordered overview
- added missing enums for framebuffer attachment point state
queries to list of new enums
- indicated that GenerateMipmap will only generate
levels base through q instead of base through p
#46, September 15, 2004: jjuliano
- move issues section to end of document.
(issues section accounts for >50% of the document!)
#45, September 13, 2004: jsandmel, jjuliano
- typos and white space updates
- clarified language about the framebuffer object bound to <target>
in section 4.4.4.2
- clarified isssue (62) on which state can change and when
#44, September 13, 2004: jsandmel
- resolved issue (40) accum buffers - deferred per group
decision
- resolved issue (41) multisample buffers - deferred per group
decision
- resolved issue (57) maximum attachable color buffers query per
group decision
- opened issue (62) which queries can change state after
BindFramebuffer
#43, September 13, 2004: jsandmel, jjuliano
- typos, cleanup
- fixed up use of COLOR/AUX/DATAN to use lower n as GL spec.
- clarified definitions of color/depth renderable
- indicate renderable images don't have to be attached to be
"renderable image complete"
- replaced requirement on texture images that they simply need
non-zero dimensions instead of saying they have been "defined"
already
#42, September 13, 2004: jsandmel
- updated Framebuffer validation language
- added "complete" terms to glossary in overview
#41, September 9, 2004: jjuliano
- re-add and rewrite section 4.4.4 on "Framebuffer
Validation"
#40, September 9, 2004: jsandmel
- fixed extra "GL" typos noted by Brian Paul
- resolved issue (54) - color attachment names
- resolved issue (58) - textures with borders
- resolved issue (59) - stencil formats
- added issue (61) - minimum requirements
#39, September 9, 2004: jsandmel, jjuliano
- misc. typos and white space fixed
#38, September 8, 2004: jsandmel, jjuliano
- clarifed section 4.4.3 to indicate that if mipmapping
disabled, the framebuffer texture attachment rules are
slightly different.
- fleshed out multisample buffer support options for
issue (41) after more discussions
#37, September 8, 2004: jsandmel
- renamed attachment enums again to add FRAMEBUFFER_ on the
front to further qualify their namespace.
- updated table of attachment point state to include default
values
- added language to "Texturing From an Attached Renderable
Image" (section 4.4.3)
#36, September 8, 2004: jjuliano
- update chapter 3 language on mipmap generation
- modify example 5 to not use depth buffer when
custom-generating mipmap
- add issue 60 on whether or not disabled depth attachment
factors into framebuffer validity determination
#35, September 7, 2004: jsandmel
- updated chapter 6 language on querying renderbuffer and
framebuffer attachment state.
- made references to "id 0" into "name zero" for easier
searching and consistency with core GL spec
- renamed the enums for framebuffer attachment state to add
"ATTACHMENT" to each to qualify the name space of the enums.
These might not be the final names.
#34, September 7, 2004: jsandmel, jjuliano
- further clarified framebuffer attachment language
- specify that attachment routines set "rest" of
attachment state to default values
#33, September 7, 2004: jsandmel
- added examples to issue (54) about framebuffer attachment names
#32, September 7, 2004: jsandmel
- further clarified framebuffer attachment language
#31, September 3, 2004: jsandmel
- added issue (58) about texture borders
- added issue (59) about stencil internal formats
- updated new tokens section to reflect recent issue resolutions
- added attachment state table to section 4.4.2
- added langauge describing renderbuffer and texture attachment
routines
#30, September 3, 2004: jjuliano
- more typos and white space cleanup
- issue (46): make it clear that validation failure occurs
because of a mismatch in dimensions, rather than size
- clarified language on draw buffer error semantics in issue
(55)
- included more language describing issue (57) about querying
for max number of attachable drawbuffers.
#29, September 2, 2004: jsandmel, jjuliano
- typos fixed and whitespace clean up
- factored issue (39) on ARB_draw_buffers into separate
issues (53), (54), (55), (56), (57)
- fleshed out issue (40) - on ACCUM buffers, tentatively
we will support this if there is time
- made a few ValidationFailures in isseu (46) more
explicit
- added issue (53) - indirection for ARB_draw_buffers?
- added issue (54) - name of color attachment points?
- added issue (55) - error behavior for DRAW_BUFFER
- added issue (56) - is DRAW_BUFFER context state or framebuffer
state?
#28, September 2, 2004: jsandmel
- Improve language describing framebuffer and renderbuffer
objects
#27, August 26, 2004: jsandmel, jjuliano
- re-resolved issue (11) - we use 3 framebuffer attachment
routines for textures, 1 for renderbuffers, also cleaned up
the rationale language for this choice
- resolved issue (30) - renderbuffer state routines take a target
- resolved issue (42) - we use a single framebuffer target enum
- resolved issue (43) - incomplete attached textures will
not cause ValidateFramebuffer failures
- resolved issue (45) - framebuffers with no color buffer attached
will be allowed
- deferred and expanded issue (48) - what info should
ValidateFramebuffer return.
- resolved issue (51) - use individual queries for attachment
state
- resolve issue (52) - auto and manual mipmap generation
can peacefully coexist
- deleted obsolete mipmap generation language from spec text
as this needs to be reworked anyway
#26, August 26, 2004: jsandmel
- corrected some depth_offset --> image terms, since that
is the current resolution of issue (28), unless we reopen it.
- clean up issue (11) language
- moved query of attachments api sub issue from (34) to
its own issue (51)
- removed obsolete note on issue (44)
- fleshed out another alternative attachment query API in issue
(51)
- created issue (52) on when auto/manual mip generation applies
- began more spec language edits to mip generation and framebuffer
object definition (this may be throwaway language depending
on the resolution of some outstanding issues)
#25, August 24, 2004: jjuliano
- Fill in chapter 4.
- Replace some references to "logical buffer" with
"renderbuffer".
- Modification to issue (44).
- Incorporate feedback from Eric Werness: improvements to
examples.
- Incorporate feedback from Jason Allen: issue (42) option D
(GL_FRAMEBUFFER_EXT), and removal of FramebufferBuf.
#24, August 23, 2004: jjuliano
- First stab at text for additions to chapters 2, 3, and 5.
- Fill in examples 1-5.
- Add description of GetFramebufferBufferParametervEXT to
chapter 6.
- Add EXT suffix in some places it was missing.
#23, August 20, 2004: jjuliano
- fix minor typos
- added additional comments regarding reopened issue (11)
- changed some references from z-slice to depth offset
#22, August 19, 2004: jsandmel
- reopened and expanded the options for issue (11) about one vs
many FramebufferTexture attachment routines
- clarified issue (16) does not imply that texture/renderbuffer
state updates are delayed on attached renderable images
- clarified issue (21) to not specifically imply that a call
to BindFramebuffer is required to delete a renderable image
attached to a framebuffer.
- resolved issue (28) "slices" are now referred to as "images"
- resolved issue (29) - GenerateMipmap is included in this
extension
- added and resolved issue (49) - MRT of different formats are
not supported
- added issue (50) - meta issue about whether async generation
of GL errors should be avoided in this api.
#21, August 19, 2004: jsandmel
- incorporated feedback from Barthold (typos fixed)
- incorporated feedback from Barthold (ARB_compromise_buffers->EXT_framebuffer_object)
- incorporated feedback from Barthold (slice->image)
- incorporated feedback from Barthold (other ARB->EXT changes)
#20, August 19, 2004: jjuliano
- fill in issue (13) and (36) - intrinsic buffers
#19, August 18, 2004: jjuliano
- fixed minor typos in issue (15)
- further clarified design rationale in issue (16)
#18, August 18, 2004: jjuliano, jsandmel
- cleaned up language for issues (15) and (16)
#17, August 18, 2004: jsandmel
- cleaned up stale references to ARB_compromise_buffers.
- resolved issues (1) - extension name
- resolved issues (15) - {Copy}TexImage behavior on current framebuffer
- resolved issues (16) - {Copy}TexImage behavior on non-current framebuffer
- (re)resolved issues (21) - Delete object behavior on attached objects
- resolved issues (22) - 1 or 2 detach objects routines
- resolved issues (25) - query on invalid framebuffers
- cleaned up issue (34) language on attachment query API
#16, August 18, 2004: jsandmel
- renamed EXT_framebuffer_object as per group decision
#15, August 8, 2004: jsandmel
- fixed minor typos found by jeff
- expanded discussion on issue (20) to distinguish
width/height/format of texture is mutable unlike texture
target as suggested by jeff
#14, August 5, 2004: jsandmel
- In several issues, make sure ask the same questions about
renderbuffers when we are talking about textures. We want to
resolve these issues symmetrically in almost all cases.
- resolved issue (19) about unused texture/renderbuffer names
- resolved issue (20) about attaching default state objects to
framebuffers
- resolved issue (21) about deleting attached texture/renderbuffer
objects
- fixed typo indicating when issue (33) was resolved
- resolved issue (34) about querying framebuffer objects
for attachments
- resolved issue (44) about using a texture object as a source
texture and destination renderable image
- resolved issue (47) about delineating exactly which state
modifying routines can cause framebuffer revalidation
- added issue (48) about the returned information from
ValidateFramebuffer().
#13, August 3, 2004: jsandmel
- added related issue in issue (44) - we need to consider
texture objects bound to different targets on the same unit
not just currently bound texture, when calculating
source/destionation circuits.
- in issue (44), option (b), indicate a possibly variant is
to allow but not require ValidateFramebuffer to fail
- cleaned up the "must fail" and "can fail" cases in
issue (46).
- added issue (47) - do we need to list exactly which
state modification routines can cause ValidateFramebuffer
to change its answer?
#12, August 3, 2004: jsandmel
- added issue about when validation failures "can" occur vs. "must"
occur.
#11, August 2, 2004: jsandmel
- removed non-contact emails from contributor list
- "methodology" -> "model" in issue (7)
- resolved issues (31,32,33), there is no renderbuffer name zero,
and binding/attaching to it simply unbinds/detaches the previously
bound/attached object.
- added issue (44) about using the same texture object as both
a source and destination
- added issue (45) about scenarios where having no renderable
image attached to the color buffer attachment point might be
acceptable
#10, July 30, 2004: jjuliano
- flesh out details of issue (29) about GenerateMipmap
- add issue (43) about mipmap cube complete textures and
framebuffer consistency check.
#9, July 30, 2004: jsandmel
- renumbered issues to account for remaval and addition of issues
- dropped issue [used to be (14)] as it was a duplicate of issue
[now (38)] about support for multiple render targets.
- added issue (32) about whether and how to support a
renderbuffer with the name zero (is it an object?)
#8, July 30, 2004: jjuliano
- tightened up language in overview regarding use of renderable
images
- clarified in overview that window and framebuffer can
have different formats
- fixed various typos, grammar, spelling errors
- indicated we should drop issue (14) about MRT, same as issue (37)
- indicate -1 is one option for return value on nonsense queries
of non-validated framebuffer state
#7, July 29, 2004: jsandmel
- add some more terms to the glossary list
- white space and various grammar clean ups (minor)
- note that we need resolution on the switch from
"render target" to "renderable image"
- cleaned up language for issue (31) and (32)
#6, July 29, 2004: jsandmel
- reworked, clarified, streamlined overview section to read better
- cleaned up some white space problems
#5, July 29, 2004: jsandmel
- fixed bad numbering in issues list
#4, July 29, 2004: jsandmel
- cleaned up issues after incorporating feedback
#3, July 28, 2004: jsandmel
- began merging render target and compromise buffers issues lists
- added contributors from EXT_render_target list
- added some extension dependencies
- borrowed overview from EXT_render_target, reworded to
make more appropriate for differences with this spec
- added placeholders for sample code
- resolved a few issues here
- removed intrinsic buffers per group decision july 26,2004
- retained framebuffer objects per group decision july 26,2004
- made FramebufferTexture into 3 functions per group decision july 26, 2004
#2, July 22, 2004: jsandmel
- removed all old EXT-compromise_buffer language, but
some of this will get reformed and added back in
- removed example temporarily, again this will get reformed and
added back in.
- LogicalBuffer renamed to "Renderbuffer"
- began fleshing out issues list
#1, July 22, 2004: jsandmel
- very first revision
- derived from EXT_compromise_buffers but really a mishmash of
all the proposals under discussion