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 v