Name EXT_framebuffer_object Name Strings GL_EXT_framebuffer_object Contributors Kurt Akeley Jason Allen Bob Beretta Pat Brown Matt Craighead 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 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, ATI Research (jsandmel 'at' ati.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: January 31, 2005 Revision: #109 Number 310 Dependencies 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_vertex_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, and FramebufferRenderbufferEXT: 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_INDEX_EXT 0x8D45 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 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_DUPLICATE_ATTACHMENT_EXT 0x8CD8 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 FRAMEBUFFER_STATUS_ERROR_EXT 0x8CDE 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 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." 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. 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. When the GL is bound to the window-system-provided framebuffer, then is a symbolic constant specifying zero, one, two, or four buffers for writing. For the window-system-provided framebuffer, must be one of NONE, FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, FRONT, BACK, LEFT, RIGHT, FRONT_AND_BACK, and AUX0 through AUXn, where n + 1 is the number of available auxiliary buffers specified in the implementation dependent state variable, AUX_BUFFERS. 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. When the GL is bound to an application-created framebuffer object, then is a symbolic constant specifying a single color buffer for writing. In this case, must be either NONE or one of COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT, where n+1 is the number of available attachable color buffers, specified in the implementation-dependent state variable, MAX_COLOR_ATTACHMENTS_EXT. 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. The constants and the buffers they indicate are summarized in Table 4.3. 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, then the error INVALID_OPERATION results. If the GL is bound to an application-created framebuffer object, DrawBuffers is supplied with a COLOR_ATTACHMENTi_EXT constant, and FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is NONE for the attachment COLOR_ATTACHMENTi_EXT, then the error INVALID_OPERATION 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. 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. If the GL is bound to the default window-system-provided framebuffer, then the constants must be one of NONE, FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, or AUX0 through AUXm, where m+1 is the number of available auxiliary buffers. Otherwise, INVALID_OPERATION is generated. If one of the constants names a color buffer that is not available, then INVALID_OPERATION is generated. If the GL is bound to an application-created framebuffer object, then each of the constants must be either NONE or one of COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT, where n+1 is the number of available attachable color buffers, specified in the implementation-dependent state variable, MAX_COLOR_ATTACHMENTS_EXT. Specifying COLOR_ATTACHMENTi_EXT enables drawing to the image attached to the framebuffer at COLOR_ATTACHMENTi. Each COLOR_ATTACHMENTi_EXT adheres to COLOR_ATTACHMENTi_EXT = COLOR_ATTACHMENT0_EXT + i. If FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is NONE for the color attachment i, then INVALID_OPERATION is generated. 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. Except for NONE, a buffer may not appear more then once in the array pointed to by bufs. Specifying a buffer more then once will result in the error INVALID_OPERATION. If fixed-function fragment shading is being performed, DrawBuffers specifies a set of draw buffers into which the fragment color is written. If a fragment shader writes to "gl_FragColor", DrawBuffers specifies a set of draw buffers into which the single fragment color defined by "gl_FragColor" is written. If a fragment shader writes to gl FragData, DrawBuffers specifies a set of draw buffers into which each of the multiple fragment colors defined by "gl_FragData" are separately written. If a fragment shader writes to neither gl FragColor nor "gl_FragData", the values of the fragment colors following shader execution are undefined, and may differ for each fragment color. 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. 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 an application-created framebuffer object, DrawBuffers is supplied with a COLOR_ATTACHMENTi_EXT constant, and FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is NONE for the attachment COLOR_ATTACHMENTi_EXT, then the error INVALID_OPERATION results. For the window-system-provided framebuffer and for application-created framebuffers, if is greater than the value of MAX_DRAW_BUFFERS, the error INVALID_VALUE 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 an 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, 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. The possible 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. When the GL is using the default window-system-provided framebuffer, must be one of FRONT LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT, FRONT, BACK, LEFT, RIGHT, and AUX0 through AUXn. 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 either NONE or COLOR_ATTACHMENT0_EXT through COLOR_ATTACHMENTn_EXT, where n+1 is the number of available attachable color buffers, specified in the implementation-dependent state variable, MAX_COLOR_ATTACHMENTS_EXT. If the requested buffer is missing, i.e. FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is NONE, then the error INVALID_OPERATION is generated. Analogous to how DRAW_BUFFERs are handled, specifying COLOR_ATTACHMENTi_EXT enables reading from the image attached to the framebuffer at COLOR_ATTACHMENTi_EXT. For application-created framebuffer objects, the initial setting for ReadBuffer is COLOR_ATTACHMENT0_EXT. If READ_BUFFER is NONE, then the values obtained by ReadPixels are undefined. Otherwise, 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. 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. 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 ReadPixels will generate the error INVALID_FRAMEBUFFER_OPERATION_EXT." 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 a application-created framebuffer object, then the operations described in chapters 2, 3, and 4 (such as Begin, DrawPixels, and DrawArrays) 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 is 1, and SAMPLE_BUFFERS is 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 one of the internal formats from table 3.16 or table 2.nnn which has a base internal format of RGB, RGBA, DEPTH_COMPONENT, or STENCIL_INDEX. 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. 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_VALUE 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. specifies the mipmap level of the texture image to be attached to the framebuffer. If is TEXTURE_RECTANGLE, 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. 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. 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, 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. The entire texture image, including border texels, if any, can be addressed with window-coordinates in the following range: 0 <= window_x < (texture_width + (2 * border)), and 0 <= window_y < (texture_height + (2 * border)) // XXX see issues (58) and (84) // XXX is the origin the lower left or upper left? // XXX is the preceding paragraph even necessary? 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. // XXX The right way to specify this seems to be a modification to chapter 3, to state that texture lookups (tau) produce undefined results while in this "feedback loop" state. 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 target of texture object is enabled* on 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, (where q is defined in the Mipmapping discussion of section 3.8.8), for the texture object . * For the purpose of this discussion, a texture is considered "enabled" if it would be enabled according to the texture target precedence rules of section 3.8.15, or if the texture would be sampled by the currently bound fragment program, or by the active fragment shader or vertex shader. Note that by setting TEXTURE_BASE_LEVEL and TEXTURE_MAX_LEVEL to exclude any levels containing image(s) attached to the currently bound framebuffer, an application can still render into the excluded mipmap levels of the texture. This can be useful when performing customized mipmap level generation, for instance. 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. * An internal format is "color-renderable" if it is one of the formats from table 3.16 whose base internal format is RGB or RGBA. No other formats, including compressed internal formats, are color-renderable. * An internal format is "depth-renderable" if it is one of the formats from table 3.16 whose base internal format is DEPTH_COMPONENT. No other formats are depth-renderable. * An internal format is "stencil-renderable" if it is one of the STENCIL_INDEX formats from table 2.nnn. 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 } * A single image is not attached more than once to the framebuffer object. { FRAMEBUFFER_INCOMPLETE_DUPLICATE_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 } * 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, then FRAMEBUFFER_STATUS_ERROR_EXT is returned and INVALID_ENUM is generated. 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. XXX The GL core spec assumes there is always a GL_FRONT buffer. Need to modify appropriate pieces of spec to relax this assumption. 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 the internal format of an image attached to the currently bound framebuffer object. If 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 internal format of the images attached to the currently bound framebuffer object. On the other hand, if the currently bound framebuffer object is not framebuffer complete, then the values of the state variables listed in table 9.nnn are undefined." 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, DeleteFramebuffersEXT, CheckFramebufferStatusEXT, GenRenderbuffersEXT, DeleteRenderbuffersEXT, RenderbufferStorageEXT, FramebufferTexture1DEXT, FramebufferTexture2DEXT, FramebufferTexture3DEXT, FramebufferRenderbufferEXT, CheckFramebufferStatusEXT, 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 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 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 or DrawBuffers 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_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 GetRenderbufferParameterivEXT is called while the value of RENDERBUFFER_BINDING_EXT is zero. 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, The error INVALID_VALUE is generated if RenderbufferStorageEXT is called with a or that is greater than MAX_RENDERBUFFER_SIZE_EXT. The error INVALID_VALUE is generated if FramebufferTexture{1D|2D|3D}EXT is called with a that is less than zero. The error INVALID_VALUE is generated if FramebufferTexture2DEXT is called with a that is not zero and is TEXTURE_RECTANGLE. 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. The error INVALID_VALUE is generated if FramebufferTexture3DEXT is called with a greater than the log base 2 of the MAX_3D_TEXTURE_SIZE. The error INVALID_VALUE is generated if FramebufferTexture3DEXT is called with a that is larger than MAX_3D_TEXTURE_SIZE. The error OUT_OF_MEMORY is generated if the GL is unable to create a data store of the required size when calling RenderbufferStorageEXT. 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 1 internal format 4.4.2.1 - of renderbuffer Move the following existing state from "Implementation Dependent Values", tables 6.31-6.36 to into a new table called "Framebuffer Dependent Values", table 9.nnn. Get Value --------- AUX_BUFFERS MAX_DRAW_BUFFERS RGBA_MODE INDEX_MODE DOUBLEBUFFER STEREO SAMPLE_BUFFERS SAMPLES RED_BITS GREEN_BITS BLUE_BITS ALPHA_BITS DEPTH_BITS STENCIL_BITS ACCUM_RED_BITS ACCUM_GREEN_BITS ACCUM_BLUE_BITS ACCUM_ALPHA_BITS To the same table called "Framebuffer Dependent Values", table 9.nnn add the following new framebuffer dependent state. Get Value Type Get Command Minimum Value Description Section Attribute --------- ---- ----------- ------------- ------------------- ------- --------- MAX_COLOR_ATTACHMENTS_EXT Z+ GetIntegerv 1 Maximum number of 4.4.2.2 - attachment points for color buffers when using framebuffer objects New Implementation Dependent State Get Value Type Get Command Minimum Value Description Section Attribute --------- ---- ----------- ------------- ------------------- ------- --------- MAX_RENDERBUFFER_SIZE_EXT Z+ GetIntegerv 1 Maximum width and 4.4.2.1 - height of renderbuffers supported by the implementation Additions to the AGL/GLX/WGL Specifications and dependencies on WGL_ARB_make_current_read, GLX_SGI_make_current_read, and GLX 1.3 The color, depth, stencil, aux, and accum logical buffers defined by the 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 removed. 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 removed. 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_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); 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_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); GenerateMipmapEXT(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_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); CHECK_FRAMEBUFFER_STATUS(); // 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); CHECK_FRAMEBUFFER_STATUS(); } 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(); Issues (1) We obviously won't call this "ARB_compromise_buffers", so what name should we use? RESOLUTION: resolved, EXT_framebuffer_object Possibilities considered include: EXT_framebuffer EXT_framebuffer_object EXT_renderable_buffers EXT_renderbuffer EXT_superbuffers (hah!) EXT_renderable_image EXT_render_image The lead candidates were EXT_renderable_image and EXT_framebuffer_object Since this extension introduced both new concepts into OpenGL, this was a bit of a toss up. EXT_framebuffer_object was chosen based on a weak precedent given by EXT_texture_object and ARB_vertex_buffer_object (2) Many developers complain about the OpenGL/glX/WGL/agl pbuffer API, which they use both to do "render to texture" and to do general offscreen (non-windowed) accelerated rendering. This extension is intended to subsume, some and perhaps all of, the functionality currently handled by pbuffers. Should this extension (initially?) support only render-to-texture or should it try to provide an OpenGL API to fully replace the pbuffer API? RESOLUTION: This extension should fully replace the pbuffer API. The implication of this decision is that this API should provide a way to support rendering to offscreen buffers that are not textures. (3) As a consequence of issue (2), this extension adds the concept of share-able, non-texturable renderable entitites that can be used as color buffers, depth buffers, stencil buffers, etc. The OpenGL spec refers to these entities as "logical buffers". What should this spec call them? RESOLUTION: "renderbuffer", (one word) We could just call them "logical buffers", but is there a better name? The group considered: logical buffer - possible, kind of general render buffer - clear, (one word or two?) renderable - clear, but may conflict with glx "drawable" drawable - confusing: glx "drawable" == gl "framebuffer" render surface - possible render target - possible image buffer - may get confused with Tex"Image" image - may get confused with Tex"Image" surface buffer - too verbose? surface - too general others??? The group felt "render buffer " (or possibly "renderbuffer") provides for the clearest expression of the purpose for these buffers. We finally decided on "renderbuffer" because we didn't want to use "render" as an adjective to describe a generic buffer, but rather decided to coin a new compound word to describe this concept. (4) How should the specification refer to the group of various types of objects that can be attached to the framebuffer attachment points? RESOLUTION: The specification will use the phrase "framebuffer-attachable images" to mean the 2D array of pixels (image) of a "renderbuffer", a "texture", or any other items that could be attached to a framebuffer. Options considered include: "render target" "renderable image" "framebuffer-attachable Initially, we chose the phrase "render target" for this but felt it didn't accurately capture the concept of a 2D array of pixels that was simultaneously useable as the storage of a texture object and the destination of rendering. We then tried to borrow the "image" language of OpenGL which describes texture's pixel arrays as "images" and we chose the term "renderable image". However, in the end, we felt that the salient characteristic of these images was that we could attach them to a framebuffer and settled on the term "framebuffer-attachable image". (5) How should the specification refer to the places in a framebuffer that can hold a framebuffer-attachable image? RESOLUTION: This state is called an "attachment point" of the framebuffer. "attachment points" will be be used to describe the framebuffer state that holds a connection to a given framebuffer-attachable image (a renderbuffer image or a texture image). The framebuffer attachment points include the framebuffer's color buffers, stencil buffer, depth buffer, and aux buffer. The word "attach" is being used to refer to connecting one object to another. "bind" refers to connecting an object to the context state. A texture image can be attached to a framebuffer object, but a framebuffer object is bound into the context state vector. (6) This extension adds the concept of collections of "logical buffers", to replace the window-system provided collection (drawable, or window) of logical buffers. What should we call these? RESOLUTION: "framebuffer" For the "collection of logical buffers" object, the group considered the names: "framebuffer", "renderTarget", "drawable". We chose "framebuffer" since this is consistent with how the OpenGL specification already uses the word framebuffer. (7) This extension introduces two new object types into the OpenGL: renderbuffer objects and framebuffer objects. For handling these objects, there are two main object manipulation methodology precedents to choose from: 1) "texture/program/vbo" object model: app-supplied int handles, Gen/is/Bind/Delete functions 2) "GLSL" object model: driver-supplied GLhandle handles, Create/Delete/Attach, etc Which methodology should this extension use for each new object? RESOLUTION: Use Option (1), "texture" object methodology, for both "renderbuffer" objects and framebuffer objects. This is consistent with the June, 2004 ARB meeting vote to use the "texture" object methodlogy as the default object methodology. (8) Do we need separate framebuffer objects? RESOLUTION: yes. The framebuffer object is an object to encapsulate the state of the framebuffer and the collection of framebuffer-attachable images attached to the logical buffer attachment points. A question was raised early on about whether we should have separate, shareable framebuffer objects or we should fold a single framebuffer "object" state vector into the context. We decided to leave framebuffer objects in the API, with the understanding that we could easily remove them from the API and the spec later if a convincing case was argued for removing it. There are several reasons why framebuffer objects were introduced: FB1. It can be "expensive" (for some definition of expensive) to validate the framebuffer and all its attached objects. There is a desire to be able to easily recognize that a particular state. combination has been seen and validated previously. FB2. There is some subset of GL context state which only makes sense in its relationship to the current framebuffer and attached images (red bits, green bits, blue bits, etc, presence or absences of aux buffers or depth buffers, current value of draw buffer(s), read buffer, etc. etc). It would be nice if this state "tracked" changes to the current framebuffer configuration by being part of the framebuffer object state. FB3. For a while, we considered adding "intrinsic" or "implicit" buffer storage to the framebuffer. This would be used for buffers that were either hidden from the user, like the multisample buffer, or perhaps needed to be explicitly formatted by the driver. If we did have this kind of "intrinsic" storage, then framebuffers would be a lot like textures and would have the same kinds of pressures to minimize vram, sharing storage across objects and contexts as textures did. In fact, they would be similar to cube map texture objects which had 6 attached face images, or mipmaped textures which had a set of mipmap level images. In the end we decided not to use intrinsic buffers, - see issue (13) - but we might decide to add them back in the future. For instance, one option for supporting multisampling is to use an implicit multisample buffer. FB4. We realized that most of the "hard" issues introduced by this extension were completely orthogonal to the presence or absence of framebuffer objects. All of the same issues apply regardless of whether there is a single non-default framebuffer as part of the context or multiple framebuffer objects. These issues about attaching, (binding) objects, reformatting attached (or bound) images via TexImage/RenderbufferStorage, pixel format combinations, framebuffer completeness, and the relationship between a non-"default" framebuffer and the legacy window sytem framebuffer and pixel format all come in to play either way. So there is actually little implementation or conceptual cost incurred by the introduction of these framebuffer objects. There were also a few reasons why we considered *not* adding framebuffer objects: NoFB1. In the absence of "intrinsic" buffers, framebuffer objects only really consist of the attachment state. It is convenient to encapsulate this state into an object, but one could ask if it's any more convenient than say a "blend state" object or a "texture unit attachment state" object, which to date, we have chosen not to add into OpenGL. NoFB2. As a "state-only" object, there's a question about how much state should be included - at least the attachment state should be included, but what about draw buffers state, what about the viewport state, what about other state? Since drawing the line is hard, we questioned whether we needed these objects. NoFB3. Some amount of the functionality of the framebuffer objects could be implemented by the application with the appropriate use of display lists. In weighing (FB1), expense of validating framebuffer state, versus (NoFB1), not wanting to introduce "state only" objects, we realized that framebuffer validation is more expensive than the blend state (for which there is no object in GL) and less expensive than a fragment program (for which there is an object in GL). While it's not exactly clear precisely where on the spectrum of "expense" the framebuffer validation lies, we decided that it may be expensive enough to justify creating a new object type. So we retained framebuffer objects in the API now, with the understanding that if we change our minds it's easier to rip them out later than it is to add them back in later. (9) Should the routine which allocates a renderbuffer accept an image to initialize the buffer, analogous to how TexImage works? RESOLUTION: no, it should allocate uninitialized storage We could have allowed a renderbuffer "image" specification routine, but this would essentially serve the same purpose as a combined "allocate renderbuffer followed by DrawPixels" routine so we decided it was extraneous. The primary purpose of these buffers is to store rendered output anyway, so there was not sufficient demand to support an optimized path for data initialization. See related issue (10). (10) What should we call the routine that allocates storage for the renderbuffer? This routine would be the moral equivalent of glTexImage. RESOLUTION: RenderbufferStorage() Options included: RenderbufferStorage() RenderbufferImage() others??? This is really a function of how we resolve issue (9). RenderbufferImage would be appropriate if the allocation routine could take an image to initialize the renderbuffer. RenderbufferStorage would be more appropriate if the allocation routine does not take an image. Since the group decided supporting an "initialization" image for a "renderbuffer" was too much overlapping functionality with DrawPixels, RenderbufferStorage was chosen. (11) The routine(s) which attach a texture to a framebuffer attachment point need to describe which image in the texture they are using, i.e., which cube map face, mipmap level, or 3D texture z-slice/depthoffset/image. Should we have one routine that handles all of these with some arguments ignored for specific texture types/targets? Or should we have a parallel set of routines for 1D/2D/3D, like TexImage does? RESOLUTION: Option (b) 3 routines for texture, 1 for renderbuffer Originally, we chose option (b) for reasons of similarity to glTexImage1D/2D/3D. For TexImage2D and FramebufferTexture2D, the texture target was used to select a face on a cube map texture object. Since glTexImage1D/3D used TEXTURE_1D/TEXTURE_3D texture targets, we did the same for FramebufferTexture1D/3D. We also included the texture target in case it was needed for future expandability. However, some felt uncomfortable with this resolution since it adds 3 framebuffer attachment calls for textures, so we reopened the issue. Originally we just considered options (a) and (b). We then reconsidered a few additional flavors: (c), (d),