| | '''OpenGL extension ARB.framebuffer_object |
| | |
| | This module customises the behaviour of the |
| | OpenGL.raw.GL.ARB.framebuffer_object to provide a more |
| | Python-friendly API |
| | |
| | Overview (from the spec) |
| | |
| | ARB_framebuffer_object is an extension intended to address the following |
| | goals: |
| | |
| | - Reflect FBO-related functionality found in the OpenGL 3.0 specification. |
| | |
| | - Integrate multiple disjoint extensions into a single ARB extension. |
| | These extensions are: |
| | |
| | EXT_framebuffer_object |
| | EXT_framebuffer_blit |
| | EXT_framebuffer_multisample |
| | EXT_packed_depth_stencil |
| | |
| | - Where appropriate, relax some of the constraints expressed by previous |
| | FBO-related extensions. In particular the requirement of matching |
| | attachment dimensions and component sizes has been relaxed, to allow |
| | implementations the freedom to support more flexible usages where |
| | possible. |
| | |
| | |
| | ARB_framebuffer_object defines an 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 layer (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 BindFramebufferARB 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. |
| | |
| | ARB_framebuffer_object, on the other hand, is both simpler to use |
| | and more efficient than ARB_render_texture. The |
| | ARB_framebuffer_object API is contained wholly within the GL API and |
| | has no (non-portable) window-system components. Under |
| | ARB_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. |
| | |
| | This extension differs from EXT_framebuffer_object by splitting the |
| | framebuffer object binding point into separate DRAW and READ |
| | bindings (incorporating functionality introduced by |
| | EXT_framebuffer_blit). This allows copying directly from one |
| | framebuffer to another. In addition, a new high performance blit |
| | function is added to facilitate these blits and perform some data |
| | conversion where allowed. |
| | |
| | This extension also enables usage of multisampling in conjunction with |
| | renderbuffers (incorporating functionality from |
| | EXT_packed_depth_stencil), as follows: |
| | |
| | The new operation RenderbufferStorageMultisample() allocates |
| | storage for a renderbuffer object that can be used as a multisample |
| | buffer. A multisample render buffer image differs from a |
| | single-sample render buffer image in that a multisample image has a |
| | number of SAMPLES that is greater than zero. No method is provided |
| | for creating multisample texture images. |
| | |
| | All of the framebuffer-attachable images attached to a framebuffer |
| | object must have the same number of SAMPLES or else the framebuffer |
| | object is not "framebuffer complete". If a framebuffer object with |
| | multisample attachments is "framebuffer complete", then the |
| | framebuffer object behaves as if SAMPLE_BUFFERS is one. |
| | |
| | In traditional multisample rendering, where |
| | DRAW_FRAMEBUFFER_BINDING is zero and SAMPLE_BUFFERS is one, the |
| | GL spec states that "the color sample values are resolved to a |
| | single, displayable color each time a pixel is updated." There are, |
| | however, several modern hardware implementations that do not |
| | actually resolve for each sample update, but instead postpones the |
| | resolve operation to a later time and resolve a batch of sample |
| | updates at a time. This is OK as long as the implementation behaves |
| | "as if" it had resolved a sample-at-a-time. Unfortunately, however, |
| | honoring the "as if" rule can sometimes degrade performance. |
| | |
| | In contrast, when DRAW_FRAMEBUFFER_BINDING is an |
| | application-created framebuffer object, MULTISAMPLE is enabled, and |
| | SAMPLE_BUFFERS is one, there is no implicit per-sample-update |
| | resolve. Instead, the application explicitly controls when the |
| | resolve operation is performed. The resolve operation is affected |
| | by calling BlitFramebuffer where the source is a multisample |
| | application-created framebuffer object and the destination is a |
| | single-sample framebuffer object (either application-created or |
| | window-system provided). |
| | |
| | This design for multisample resolve more closely matches current |
| | hardware, but still permits implementations which choose to resolve |
| | a single sample at a time. If hardware that implements the |
| | multisample resolution "one sample at a time" exposes |
| | ARB_framebuffer_object, it could perform the implicit resolve |
| | to a driver-managed hidden surface, then read from that surface when |
| | the application calls BlitFramebuffer. |
| | |
| | Another motivation for granting the application explicit control |
| | over the multisample resolve operation has to do with the |
| | flexibility afforded by ARB_framebuffer_object. Previously, a |
| | drawable (window or pbuffer) had exclusive access to all of its |
| | buffers. There was no mechanism for sharing a buffer across |
| | multiple drawables. Under ARB_framebuffer_object, however, a |
| | mechanism exists for sharing a framebuffer-attachable image across |
| | several framebuffer objects, as well as sharing an image between a |
| | framebuffer object and a texture. If we had retained the "implicit" |
| | resolve from traditional multisampled rendering, and allowed the |
| | creation of "multisample" format renderbuffers, then this type of |
| | sharing would have lead to two problematic situations: |
| | |
| | * Two contexts, which shared renderbuffers, might perform |
| | competing resolve operations into the same single-sample buffer |
| | with ambiguous results. |
| | |
| | * It would have introduced the unfortunate ability to use the |
| | single-sample buffer as a texture while MULTISAMPLE is ENABLED. |
| | |
| | Using BlitFramebuffer as an explicit resolve to serialize access to |
| | the multisampled contents and eliminate the implicit per-sample |
| | resolve operation, we avoid both of these problems. |
| | |
| | This extension also enables usage of packed depth-stencil formats in |
| | renderbuffers (incorporating functionality from |
| | EXT_packed_depth_stencil), as follows: |
| | |
| | Many OpenGL implementations have chosen to interleave the depth and |
| | stencil buffers into one buffer, often with 24 bits of depth |
| | precision and 8 bits of stencil data. 32 bits is more than is |
| | needed for the depth buffer much of the time; a 24-bit depth buffer, |
| | on the other hand, requires that reads and writes of depth data be |
| | unaligned with respect to power-of-two boundaries. On the other |
| | hand, 8 bits of stencil data is more than sufficient for most |
| | applications, so it is only natural to pack the two buffers into a |
| | single buffer with both depth and stencil data. OpenGL never |
| | provides direct access to the buffers, so the OpenGL implementation |
| | can provide an interface to applications where it appears the one |
| | merged buffer is composed of two logical buffers. |
| | |
| | One disadvantage of this scheme is that OpenGL lacks any means by |
| | which this packed data can be handled efficiently. For example, |
| | when an application reads from the 24-bit depth buffer, using the |
| | type GL_UNSIGNED_SHORT will lose 8 bits of data, while |
| | GL_UNSIGNED_INT has 8 too many. Both require expensive format |
| | conversion operations. A 24-bit format would be no more suitable, |
| | because it would also suffer from the unaligned memory accesses that |
| | made the standalone 24-bit depth buffer an unattractive proposition |
| | in the first place. |
| | |
| | Many applications, such as parallel rendering applications, may also |
| | wish to draw to or read back from both the depth and stencil buffers |
| | at the same time. Currently this requires two separate operations, |
| | reducing performance. Since the buffers are interleaved, drawing to |
| | or reading from both should be no more expensive than using just |
| | one; in some cases, it may even be cheaper. |
| | |
| | This extension provides a new data format, GL_DEPTH_STENCIL, |
| | that can be used with the glDrawPixels, glReadPixels, and |
| | glCopyPixels commands, as well as a packed data type, |
| | GL_UNSIGNED_INT_24_8, that is meant to be used with |
| | GL_DEPTH_STENCIL. No other data types are supported with |
| | GL_DEPTH_STENCIL. If ARB_depth_texture or SGIX_depth_texture is |
| | supported, GL_DEPTH_STENCIL/GL_UNSIGNED_INT_24_8 data can |
| | also be used for textures; this provides a more efficient way to |
| | supply data for a 24-bit depth texture. |
| | |
| | GL_DEPTH_STENCIL data, when passed through the pixel path, |
| | undergoes both depth and stencil operations. The depth data is |
| | scaled and biased by the current GL_DEPTH_SCALE and GL_DEPTH_BIAS, |
| | while the stencil data is shifted and offset by the current |
| | GL_INDEX_SHIFT and GL_INDEX_OFFSET. The stencil data is also put |
| | through the stencil-to-stencil pixel map. |
| | |
| | glDrawPixels of GL_DEPTH_STENCIL data operates similarly to that |
| | of GL_STENCIL_INDEX data, bypassing the OpenGL fragment pipeline |
| | entirely, unlike the treatment of GL_DEPTH_COMPONENT data. The |
| | stencil and depth masks are applied, as are the pixel ownership and |
| | scissor tests, but all other operations are skipped. |
| | |
| | glReadPixels of GL_DEPTH_STENCIL data reads back a rectangle |
| | from both the depth and stencil buffers. |
| | |
| | glCopyPixels of GL_DEPTH_STENCIL data copies a rectangle from |
| | both the depth and stencil buffers. Like glDrawPixels, it applies |
| | both the stencil and depth masks but skips the remainder of the |
| | OpenGL fragment pipeline. |
| | |
| | glTex[Sub]Image[1,2,3]D of GL_DEPTH_STENCIL data loads depth and |
| | stencil data into a depth_stencil texture. glGetTexImage of |
| | GL_DEPTH_STENCIL data can be used to retrieve depth and stencil |
| | data from a depth/stencil texture. |
| | |
| | In addition, a new base internal format, GL_DEPTH_STENCIL, can |
| | be used by both texture images and renderbuffer storage. When an |
| | image with a DEPTH_STENCIL internal format is attached to both |
| | the depth and stencil attachment points of a framebuffer object, |
| | then it becomes both the depth and stencil |
| | buffers of the framebuffer. This fits nicely with hardware that |
| | interleaves both depth and stencil data into a single buffer. When |
| | a texture with DEPTH_STENCIL data is bound for texturing, only |
| | the depth component is accessible through the texture fetcher. The |
| | stencil data can be written with TexImage or CopyTexImage, and can |
| | be read with GetTexImage. When a DEPTH_STENCIL image is |
| | attached to the stencil attachment of the bound framebuffer object, |
| | the stencil data can be accessed through any operation that reads |
| | from or writes to the framebuffer's stencil buffer. |
| | |
| | |
| | The official definition of this extension is available here: |
| | http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt |
| | ''' |
| | from OpenGL import platform, constant, arrays |
| | from OpenGL import extensions, wrapper |
| | import ctypes |
| | from OpenGL.raw.GL import _types, _glgets |
| | from OpenGL.raw.GL.ARB.framebuffer_object import * |
| | from OpenGL.raw.GL.ARB.framebuffer_object import _EXTENSION_NAME |
| |
|
| | def glInitFramebufferObjectARB(): |
| | '''Return boolean indicating whether this extension is available''' |
| | from OpenGL import extensions |
| | return extensions.hasGLExtension( _EXTENSION_NAME ) |
| |
|
| | |
| | glDeleteRenderbuffers=wrapper.wrapper(glDeleteRenderbuffers).setInputArraySize( |
| | 'renderbuffers', None |
| | ) |
| | glGenRenderbuffers=wrapper.wrapper(glGenRenderbuffers).setOutput( |
| | 'renderbuffers',size=lambda x:(x,),pnameArg='n',orPassIn=True |
| | ) |
| | glGetRenderbufferParameteriv=wrapper.wrapper(glGetRenderbufferParameteriv).setOutput( |
| | 'params',size=_glgets._glget_size_mapping,pnameArg='pname',orPassIn=True |
| | ) |
| | |
| | glDeleteFramebuffers=wrapper.wrapper(glDeleteFramebuffers).setInputArraySize( |
| | 'framebuffers', None |
| | ) |
| | glGenFramebuffers=wrapper.wrapper(glGenFramebuffers).setOutput( |
| | 'framebuffers',size=lambda x:(x,),pnameArg='n',orPassIn=True |
| | ) |
| | glGetFramebufferAttachmentParameteriv=wrapper.wrapper(glGetFramebufferAttachmentParameteriv).setOutput( |
| | 'params',size=_glgets._glget_size_mapping,pnameArg='pname',orPassIn=True |
| | ) |
| | |
| | from OpenGL.lazywrapper import lazy as _lazy |
| |
|
| | glGenFramebuffers = wrapper.wrapper(glGenFramebuffers).setOutput( |
| | 'framebuffers', |
| | lambda x: (x,), |
| | 'n', orPassIn=True) |
| | |
| | glGenRenderbuffers = wrapper.wrapper(glGenRenderbuffers).setOutput( |
| | 'renderbuffers', |
| | lambda x: (x,), |
| | 'n', orPassIn=True) |
| |
|
| |
|
| | @_lazy( glDeleteFramebuffers ) |
| | def glDeleteFramebuffers( baseOperation, n, framebuffers=None ): |
| | """glDeleteFramebuffers( framebuffers ) -> None |
| | """ |
| | if framebuffers is None: |
| | framebuffers = arrays.GLuintArray.asArray( n ) |
| | n = arrays.GLuintArray.arraySize( framebuffers ) |
| | return baseOperation( n, framebuffers ) |
| |
|
| | |
| | from OpenGL import images |
| | from OpenGL.raw.GL.VERSION.GL_1_1 import GL_UNSIGNED_INT |
| | images.TYPE_TO_ARRAYTYPE[ GL_UNSIGNED_INT_24_8 ] = GL_UNSIGNED_INT |
| | images.TIGHT_PACK_FORMATS[ GL_UNSIGNED_INT_24_8 ] = 4 |
| |
|
| | |
| | |
| | GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = constant.Constant( 'GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS', 0x8CD9 ) |
| | GL_FRAMEBUFFER_INCOMPLETE_FORMATS = constant.Constant( 'GL_FRAMEBUFFER_INCOMPLETE_FORMATS', 0x8CDA ) |
| | GL_FRAMEBUFFER_UNSUPPORTED = constant.Constant( 'GL_FRAMEBUFFER_UNSUPPORTED', 0x8CDD ) |
| | del images |
| | del GL_UNSIGNED_INT |
| |
|