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