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: April 22, 2008 Revision: #120 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_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 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 parameter of BindFramebufferEXT, CheckFramebufferStatusEXT, FramebufferTexture{1D|2D|3D}EXT, FramebufferRenderbufferEXT, and GetFramebufferAttachmentParameterivEXT: FRAMEBUFFER_EXT 0x8D40 Accepted by the parameter of BindRenderbufferEXT, RenderbufferStorageEXT, and GetRenderbufferParameterivEXT, and returned by GetFramebufferAttachmentParameterivEXT: RENDERBUFFER_EXT 0x8D41 Accepted by the parameter of RenderbufferStorageEXT: STENCIL_INDEX1_EXT 0x8D46 STENCIL_INDEX4_EXT 0x8D47 STENCIL_INDEX8_EXT 0x8D48 STENCIL_INDEX16_EXT 0x8D49 Accepted by the 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 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 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 . * The texture is attached to one of the attachment points, , of framebuffer object . * TEXTURE_MIN_FILTER is NEAREST or LINEAR, and the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT for attachment point 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 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 is one of TEXTURE_1D, TEXTURE_2D, TEXTURE_CUBE_MAP, or TEXTURE_3D. Mipmap generation affects the texture image attached to . For cube map textures, INVALID_OPERATION is generated if the texture bound to 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: " is an integer reference value that is used in the unsigned stencil comparison. Stencil comparison operations and queries of use the value of 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 ); defines a buffer or set of buffers for writing. must be one of the values from tables 4.4 or 10.nnn. Otherwise, INVALID_ENUM is generated. In addition, acceptable values for 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 must be one the values listed in table 4.4, which summarizes the constants and the buffers they indicate. In this case, 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, must be one of the values listed in table 10.nnn, which summarizes the constants and the buffers they indicate. In this case, 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. specifies the number of buffers in . is a pointer to an array of symbolic constants specifying the buffer to which each fragment color is written. Each enumerant listed in 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 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 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 is greater than MAX_DRAW_BUFFERS. Except for NONE, a buffer may not appear more then once in the array pointed to by . 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 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. must be one of the values from tables 4.4 or 10.nnn. Otherwise, INVALID_ENUM is generated. Further, the acceptable values for 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, 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, 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 set to FRAMEBUFFER_EXT and 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 . If the bind is successful no change is made to the state of the bound framebuffer object and any previous binding to 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); contains 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 of FRAMEBUFFER_EXT and of zero. Unused names in are silently ignored, as is the value zero. The command void GenFramebuffersEXT(sizei n, uint *ids); returns previously unused framebuffer object names in . 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 set to RENDERBUFFER_EXT and set to the unused name. If 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 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 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 is zero, then any previous binding to is broken and the 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 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 RENDERBUFFER_EXT and 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 are silently ignored, as is the value zero. The command void GenRenderbuffersEXT( sizei n, uint *renderbuffers ); returns previously unused renderbuffer object names in . 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. must be RENDERBUFFER_EXT. must be color-renderable, depth-renderable, or stencil-renderable (as defined in section 4.4.4). and are the dimensions in pixels of the renderbuffer. If either or 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); must be FRAMEBUFFER_EXT. INVALID_OPERATION is generated if the current value of FRAMEBUFFER_BINDING_EXT is zero when FramebufferRenderbufferEXT is called. should be set to one of the attachment points of the framebuffer listed in table 1.nnn. must be RENDERBUFFER_EXT and should be set to the name of the renderbuffer object to be attached to the framebuffer. must be either zero or the name of an existing renderbuffer object of type , otherwise INVALID_OPERATION is generated. If is zero, then the value of is ignored. If is not zero and if FramebufferRenderbufferEXT is successful, then the renderbuffer named will be used as the logical buffer identified by of the framebuffer currently bound to . 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 . All other state values of the attachment point specified by 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 logical buffer of the framebuffer object bound to framebuffer 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 name zero will detach the image, if any, identified by , in the framebuffer currently bound to . All state values of the attachment point specified by in the object bound to 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 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, 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. must be one of the attachment points of the framebuffer listed in table 1.nnn. In all three routines, if is zero, then , , and are ignored. If is not zero, then must either name an existing texture object with an target of , or must name an existing cube map texture and 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. specifies the mipmap level of the texture image to be attached to the framebuffer. If is TEXTURE_RECTANGLE_ARB, then must be zero. If is TEXTURE_3D, then must be greater than or equal to zero and less than or equal to log base 2 of MAX_3D_TEXTURE_SIZE. If 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 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 , must be greater than or equal to zero and no larger than log base 2 of MAX_TEXTURE_SIZE. Otherwise, INVALID_VALUE is generated. specifies the z-offset of a 2-dimensional image within a 3-dimensional texture. INVALID_VALUE is generated if is larger than MAX_3D_TEXTURE_SIZE-1. For FramebufferTexture1DEXT, if is not zero, then must be TEXTURE_1D. For FramebufferTexture2DEXT, if is not zero, then 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 is not zero, then must be TEXTURE_3D. If 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 of the framebuffer currently bound to . 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 . Additionally, the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL for the named attachment point is set to . If is a cubemap texture then, the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE the named attachment point is set to . If is a 3D texture, then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET for the named attachment point is set to . All other state values of the attachment point specified by 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 logical buffer of the framebuffer object bound to framebuffer 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 name zero will detach the image identified by , if any, in the framebuffer currently bound to . All state values of the attachment point specified by 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 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 is attached to the currently bound framebuffer at attachment point , and - the texture object is currently bound to a texture unit , and - the current fixed-function texture state or programmable vertex and/or fragment processing state makes it possible(*) to sample from the texture object bound to texture unit while either of the following conditions are true: - the value of TEXTURE MIN FILTER for texture object is NEAREST or LINEAR, and the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT for attachment point is equal to the value of TEXTURE_BASE_LEVEL for the texture object , or - the value of TEXTURE_MIN_FILTER for texture object 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 is within the the range specified by the current values of TEXTURE_BASE_LEVEL to q, inclusive, for the texture object . (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 bound to texture unit " if any of the following are true: - programmable vertex and fragment processing is disabled and the target of texture object 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 bound to , or - if the active fragment or vertex shader contains any instructions that might sample from the texture object bound to 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 is not NONE, then it is said that a framebuffer-attachable image, named , is attached to the framebuffer at the attachment point. is identified by the state in as described in section 4.4.2. The framebuffer attachment point is said to be "framebuffer attachment complete" if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT for is NONE (i.e., no image is attached), or if all of the following conditions are true: * 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 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 is one of COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT, then must have a color-renderable internal format. * If is DEPTH_ATTACHMENT_EXT, then must have a depth-renderable internal format. * If is STENCIL_ATTACHMENT_EXT, then 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 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 can be queried by calling enum CheckFramebufferStatusEXT(enum target); If 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 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); must be FRAMEBUFFER_EXT. must be one of the attachment points of the framebuffer listed in table 1.nnn. 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 is zero, then INVALID_OPERATION is generated. Upon successful return from GetFramebufferAttachmentParameterivEXT, if 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 is FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, 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 is FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT, then will contain the name of the texture object which contains the attached image. If is FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT, then will contain the mipmap level of the texture object which contains the attached image. If is FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT and the texture object named FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT is a cube map texture, then will contain the cube map face of the cubemap texture object which contains the attached image. Otherwise will contain the value zero. If is FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT and the texture object named FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT is a 3-dimensional texture, then will contain the zoffset of the 2D image of the 3D texture object which contains the attached image. Otherwise will contain the value zero. Otherwise, INVALID_ENUM is generated. void GetRenderbufferParameterivEXT(enum target, enum pname, int* params); must be RENDERBUFFER_EXT. must be one of the symbolic values in table 8.nnn. If the renderbuffer currently bound to is zero, then INVALID_OPERATION is generated. Upon successful return from GetRenderbufferParameterivEXT, if is RENDERBUFFER_WIDTH_EXT, RENDERBUFFER_HEIGHT_EXT, or RENDERBUFFER_INTERNAL_FORMAT_EXT, then will contain the width in pixels, height in pixels, or internal format, respectively, of the image of the renderbuffer currently bound to . Upon successful return from GetRenderbufferParameterivEXT, if 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 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 . 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 is the name of an framebuffer object. If is zero, or if 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 is the name of a renderbuffer object. If is zero, or if 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 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 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 constant that is not listed in table 4.4 or 10.nnn. The error INVALID_ENUM is generated if DrawBuffers is called with a 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 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 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 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 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 or that is greater than MAX_RENDERBUFFER_SIZE_EXT. The error INVALID_ENUM is generated if RenderbufferStorageEXT is called with an 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 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 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 that is less than zero and is not zero. The error INVALID_VALUE is generated if FramebufferTexture2DEXT is called with a that is not zero and is TEXTURE_RECTANGLE_ARB and is not zero. The error INVALID_VALUE is generated if FramebufferTexture{1D|2D}EXT is called with a that is greater than the log base 2 of MAX_TEXTURE_SIZE and is respectively a non-zero 1D or 2D texture object name. The error INVALID_VALUE is generated if FramebufferTexture2DEXT is called with a that is greater than the log base 2 of MAX_CUBE_MAP_TEXTURE_SIZE and is a non-zero cubemap texture object name. The error INVALID_VALUE is generated if FramebufferTexture3DEXT is called with a greater than the log base 2 of the MAX_3D_TEXTURE_SIZE and is not zero. The error INVALID_VALUE is generated if FramebufferTexture3DEXT is called with a that is larger than MAX_3D_TEXTURE_SIZE-1 and is not zero. The error INVALID_ENUM is generated if CheckFramebufferStatusEXT is called and 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 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 STENCIL_REF 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 and 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_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(); // Re-enable rendering to the window glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindTexture(GL_TEXTURE_2D, 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); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindTexture(GL_TEXTURE_2D, color_tex); } (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 } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // automatically generate mipmaps for (int i=0; i } (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); // 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); } glTexParameteri(TEXTURE_2D, TEXTURE_BASE_LEVEL, 0); glTexParameteri(TEXTURE_2D, TEXTURE_MAX_LEVEL, max); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } (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(); // Re-enable rendering to the window glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindTexture(GL_TEXTURE_2D, 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] // 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); 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 is ignored for non-3D textures and 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 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 parameter to FramebufferTexture3DEXT actually be called? RESOLUTION: resolved, "zoffset" This parameter could have been called or . or 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 = a framebuffer target = {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 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 = a framebuffer target = {attachment_point} = 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, ¶m). Another option is to add a target-aware query routine, i.e., GetFramebufferiv(FRAMEBUFFER, COMPLETE, ¶m); 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. (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 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 #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 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 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 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 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(, 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 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 in FramebufferTexture when is zero and target in FramebufferRenderbuffer when is zero. ( and 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 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