Name NV_framebuffer_blit Name Strings GL_NV_framebuffer_blit Contributors Contributors to EXT_framebuffer_blit, ARB_framebuffer_object and ANGLE_framebuffer_blit Greg Roth, NVIDIA Xi Chen, NVIDIA Contact Mathias Heyer, NVIDIA Corporation (mheyer 'at' nvidia.com) Status Complete Version Last Modified Date: 03 Mar 2015 Author Revision: 06 Number OpenGL ES Extension #142 Dependencies OpenGL ES 2.0 is required. The extension is written against the OpenGL ES 2.0.25 specification. EXT_sRGB affects the definition of this extension. EXT_color_buffer_half_float affects the definition of this extension EXT_discard_framebuffer affects the definition of this extension NV_fbo_color_attachments affects the definition of this extension NV_framebuffer_multisample affects the definition of this extension NV_read_buffer affects the definition of this extension NV_draw_buffers affects the definition of this extension This extension interacts with OpenGL ES 3.0 and later versions. Overview This extension modifies OpenGL ES 2.0 by splitting the framebuffer object binding point into separate DRAW and READ bindings. 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. New Procedures and Functions void BlitFramebufferNV(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, bitfield mask, enum filter); New Tokens Accepted by the parameter of BindFramebuffer, CheckFramebufferStatus, FramebufferTexture2D, FramebufferRenderbuffer, and GetFramebufferAttachmentParameteriv: READ_FRAMEBUFFER_NV 0x8CA8 DRAW_FRAMEBUFFER_NV 0x8CA9 Accepted by the parameters of GetIntegerv and GetFloatv: DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6 // alias FRAMEBUFFER_BINDING READ_FRAMEBUFFER_BINDING_NV 0x8CAA Additions to Chapter 3 of the OpenGL ES 2.0.25 Specification (Rasterization) Change the last paragraph of section 3.7.2 to: "Calling CopyTexImage2D or CopyTexSubImage2D will result in an INVALID_FRAMEBUFFER_OPERATION error if the object bound to READ_FRAMEBUFFER_BINDING_NV is not framebuffer complete (see section 4.4.5)." Additions to Chapter 4 of the OpenGL ES 2.0.25 Specification (Per-Fragment Operations and the Frame Buffer) Change the first word of Chapter 4 from "The" to "A". Replace the last paragraph of the Introduction of Chapter 4: "The GL has two active framebuffers; the draw framebuffer is the destination for rendering operations, and the read framebuffer is the source for readback operations. The same framebuffer may be used for both drawing and reading. Section 4.4.1 describes the mechanism for controlling framebuffer usage. The default framebuffer is initially used as the draw and read framebuffer and the initial state of all provided bitplanes is undefined. The format and encoding of buffers in the draw and read framebuffers can be queried as described in section 6.1.7." Modify the first sentence of the last paragraph of section 4.1.1: "While an application-created framebuffer object is bound to DRAW_FRAMEBUFFER_NV, the pixel ownership test always passes." In section 4.3.1 (Reading Pixels), replace the following sentence: "The implementation-chosen format may vary depending on the format of the currently bound rendering surface." with: "The implementation chosen format may vary depending on the format of the selected READ_BUFFER_NV of the currently bound read framebuffer (READ_FRAMEBUFFER_BINDING_NV)." Add to section 4.3.1 (Reading Pixels) right before the subsection "Obtaining Pixels from the Framebuffer": "Calling ReadPixels generates INVALID_FRAMEBUFFER_OPERATION if the object bound to READ_FRAMEBUFFER_BINDING_NV is not "framebuffer complete" (section 4.4.5)." In section 4.3.1, after the definition of ReadBufferNV, replace "FRAMEBUFFER_BINDING" with "READ_FRAMEBUFFER_BINDING_NV", so that ReadBufferNV always refers to the current read framebuffer. Add section 4.3.3 Copying Pixels: "BlitFramebufferNV transfers a rectangle of pixel values from one region of the read framebuffer to another in the draw framebuffer. BlitFramebufferNV(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, bitfield mask, enum filter); is the bitwise OR of a number of values indicating which buffers are to be copied. The values are COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT, and STENCIL_BUFFER_BIT, which are described in section 4.2.3. The pixels corresponding to these buffers are copied from the source rectangle, bound by the locations (srcX0, srcY0) and (srcX1, srcY1), to the destination rectangle, bound by the locations (dstX0, dstY0) and (dstX1, dstY1). The lower bounds of the rectangle are inclusive, while the upper bounds are exclusive. When the color buffer is transferred, values are taken from the read buffer of the read framebuffer and written to each of the draw buffers of the draw framebuffer. The actual region taken from the read framebuffer is limited to the intersection of the source buffers being transferred, which may include the color buffer selected by the read buffer, the depth buffer, and/or the stencil buffer depending on . The actual region written to the draw framebuffer is limited to the intersection of the destination buffers being written, which may include multiple draw buffers, the depth buffer, and/or the stencil buffer depending on . Whether or not the source or destination regions are altered due to these limits, the scaling and offset applied to pixels being transferred is performed as though no such limits were present. If the source and destination rectangle dimensions do not match, the source image is stretched to fit the destination rectangle. must be LINEAR or NEAREST and specifies the method of interpolation to be applied if the image is stretched. LINEAR filtering is allowed only for the color buffer; if includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT, and filter is not NEAREST, no copy is performed and an INVALID_OPERATION error is generated. If the source and destination dimensions are identical, no filtering is applied. If either the source or destination rectangle specifies a negative dimension, the image is reversed in the corresponding direction. If both the source and destination rectangles specify a negative dimension for the same direction, no reversal is performed. If a linear filter is selected and the rules of LINEAR sampling (see section 3.7.7) would require sampling outside the bounds of a source buffer, it is as though CLAMP_TO_EDGE texture sampling were being performed. If a linear filter is selected and sampling would be required outside the bounds of the specified source region, but within the bounds of a source buffer, the implementation may choose to clamp while sampling or not. If the source and destination buffers are identical, and the source and destination rectangles overlap, the result of the blit operation is undefined. When values are taken from the read buffer, if the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment corresponding to the read buffer is sRGB (see section 6.1.13), the red, green, and blue components are converted from the non-linear sRGB color space as described in section 3.7.14. When values are written to the draw buffers, blit operations bypass the fragment pipeline. The only fragment operations which affect a blit are the pixel ownership test, the scissor test, and sRGB conversion (see section 3.7.14). Additionally color, depth, and stencil masks (see section 4.2.2) are ignored. If a buffer is specified in and does not exist in both the read and draw framebuffers, the corresponding bit is silently ignored. If the color formats of the read and draw framebuffers do not match, and includes COLOR_BUFFER_BIT, the pixel groups are converted to match the destination format as in CopyTexImage. However, colors are clamped only if all draw color buffers have fixedpoint components. Format conversion is not supported for all data types, and an INVALID_OPERATION error is generated under any of the following conditions: * The read buffer contains fixed-point or floating-point values and any draw buffer contains neither fixed-point nor floating-point values. Calling BlitFramebufferNV will result in an INVALID_FRAMEBUFFER_OPERATION_EXT error if the objects bound to DRAW_FRAMEBUFFER_BINDING_NV and READ_FRAMEBUFFER_BINDING_NV are not "framebuffer complete" (section 4.4.4.2)." Calling BlitFramebufferNV will result in an INVALID_OPERATION error if includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT and the source and destination depth and stencil buffer formats do not match. If SAMPLE_BUFFERS for the read framebuffer is greater than zero and SAMPLE_BUFFERS for the draw framebuffer is zero, the samples corresponding to each pixel location in the source are converted to a single sample before being written to the destination. If SAMPLE_BUFFERS for the read framebuffer is zero and SAMPLE_BUFFERS for the draw framebuffer is greater than zero, the value of the source sample is replicated in each of the destination samples. If SAMPLE_BUFFERS for both the read and draw framebuffers are greater than zero, and the values of SAMPLES for the read and draw framebuffers are identical, the samples are copied without modification from the read framebuffer to the draw framebuffer. Otherwise, no copy is performed and an INVALID_OPERATION error is generated. Note that the samples in the draw buffer are not guaranteed to be at the same sample location as the read buffer, so rendering using this newly created buffer can potentially have geometry cracks or incorrect antialiasing. This may occur if the sizes of the framebuffers do not match, if the formats differ, or if the source and destination rectangles are not defined with the same (X0,Y0) and (X1,Y1) bounds. If SAMPLE_BUFFERS for either the read framebuffer or draw framebuffer is greater than zero, no copy is performed and an INVALID_OPERATION error is generated if the dimensions of the source and destination rectangles provided to BlitFramebuffer are not identical, or if the formats of the read and draw framebuffers are not identical. Modify the beginning of section 4.4.1 (Binding and Managing Framebuffer Objects): The default framebuffer for rendering and readback operations is provided by the windowing system. In addition, named framebuffer objects can be created and operated upon. The namespace for framebuffer objects is the unsigned integers, with zero reserved by the GL for the default framebuffer. A framebuffer object is created by binding an unused name to DRAW_FRAMEBUFFER_NV or READ_FRAMEBUFFER_NV. The binding is effected by calling void BindFramebuffer( enum target, uint framebuffer ); with set to the desired framebuffer target and set to the unused name. The resulting framebuffer object is a new state vector. There are MAX_COLOR_ATTACHMENTS_NV color attachment points, plus one each for the depth and stencil attachment points. BindFramebuffer may also be used to bind an existing framebuffer object to DRAW_FRAMEBUFFER_NV and/or READ_FRAMEBUFFER_NV. If the bind is successful no change is made to the state of the bound framebuffer object and any previous binding to is broken. If a framebuffer object is bound to DRAW_FRAMEBUFFER_NV or READ_- FRAMEBUFFER_NV, it becomes the target for rendering or readback operations, respectively, until it is deleted or another framebuffer is bound to the corresponding bind point. Calling BindFramebuffer with set to FRAMEBUFFER binds to both read and draw targets. While a framebuffer object is bound, OpenGL ES 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. Queries of the values specified in table 6.21 (Implementation Dependent Pixel Depths) are derived from the framebuffer object bound to DRAW_FRAMEBUFFER_NV with the exception of IMPLEMENTATION_COLOR_READ_TYPE and IMPLEMENTATION_- COLOR_READ_FORMAT, which are derived from the framebuffer object bound to READ_FRAMEBUFFER_NV. The initial state of DRAW_FRAMEBUFFER_NV and READ_FRAMEBUFFER_NV refers to the default framebuffer. In order that access to the default framebuffer is not lost, it is treated as a framebuffer object with the name of zero. The default framebuffer is therefore rendered to and read from while zero is bound to the corresponding targets. 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.) Change the description of DeleteFramebuffers: contains names of framebuffer objects to be deleted. After a framebuffer object is deleted, it has no attachments, and its name is again unused. If a framebuffer that is currently bound to one or more of the targets DRAW_FRAMEBUFFER_NV or READ_FRAMEBUFFER_NV is deleted, it is as though BindFramebuffer had been executed with the corresponding and of zero. Unused names in framebuffers are silently ignored, as is the value zero. The names bound to the draw and read framebuffer bindings can be queried by calling GetIntegerv with the symbolic constants DRAW_FRAMEBUFFER_BINDING and READ_FRAMEBUFFER_BINDING, respectively. FRAMEBUFFER_BINDING is equivalent to DRAW_FRAMEBUFFER_BINDING In section 4.4.3, modify the first two sentences of the description of FramebufferRenderbuffer as follows: "The must be DRAW_FRAMEBUFFER_NV, READ_FRAMEBUFFER_NV, or FRAMEBUFFER. If is FRAMEBUFFER, it behaves as though DRAW_FRAMEBUFFER_NV was specified. INVALID_OPERATION is generated if the value of the corresponding binding is zero." In section 4.4.3, modify the first two sentences of the description of FramebufferTexture2D as follows: "The must be DRAW_FRAMEBUFFER_NV, READ_FRAMEBUFFER_NV, or FRAMEBUFFER_NV. If is FRAMEBUFFER, it behaves as though DRAW_FRAMEBUFFER_NV was specified. INVALID_OPERATION is generated if the value of the corresponding binding is zero." In section 4.4.5, modify the first two paragraphs describing CheckFramebufferStatus as follows: "If is not DRAW_FRAMEBUFFER_NV, READ_FRAMEBUFFER_NV or FRAMEBUFFER, INVALID_ENUM is generated. FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER_NV." The values of SAMPLE_BUFFERS and SAMPLES are derived from the attachments of the currently bound framebuffer object. If the current DRAW_FRAMEBUFFER_BINDING is not framebuffer complete, then both SAMPLE_BUFFERS and SAMPLES are undefined. Otherwise, SAMPLES is equal to the value of RENDERBUFFER_SAMPLES for the attached images (which all must have the same value for RENDERBUFFER_SAMPLES). Further, SAMPLE_BUFFERS is one if SAMPLES is non-zero. Otherwise, SAMPLE_BUFFERS is zero." Additions to Chapter 6 of the OpenGL ES 2.0.25 Specification (State and State Requests) In section 6.1.3, modify the first sentence of the description of GetFramebufferAttachmentParameteriv as follows: " must be DRAW_FRAMEBUFFER_NV, READ_FRAMEBUFFER_NV or FRAMEBUFFER. FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER_NV." Dependencies on OpenGL ES 3.0 and later If OpenGL ES 3.0 or later is supported, the described modifications to language for BlitFramebufferNV also apply to BlitFramebuffer. (Add to the end of the section describing BlitFramebuffer) "If SAMPLE_BUFFERS for both the read and draw framebuffers are greater than zero, and the values of SAMPLES for the read and draw framebuffers are identical, the samples are copied without modification from the read framebuffer to the draw framebuffer. Otherwise, no copy is performed and an INVALID_OPERATION error is generated. Note that the samples in the draw buffer are not guaranteed to be at the same sample location as the read buffer, so rendering using this newly created buffer can potentially have geometry cracks or incorrect antialiasing. This may occur if the sizes of the framebuffers do not match, if the formats differ, or if the source and destination rectangles are not defined with the same (X0,Y0) and (X1,Y1) bounds. If SAMPLE_BUFFERS for either the read framebuffer or draw framebuffer is greater than zero, no copy is performed and an INVALID_OPERATION error is generated if the dimensions of the source and destination rectangles provided to BlitFramebuffer are not identical, or if the formats of the read and draw framebuffers are not identical." (In the error list for BlitFramebuffer, modify the item "An INVALID_OPERATION error is generated if the draw framebuffer is multisampled.") * An INVALID_OPERATION error is generated if both the read and draw buffers are multisampled, and SAMPLE_BUFFERS for the read and draw buffers are not identical. (In the error list for BlitFramebuffer, modify the item "An INVALID_OPERATION error is generated if the read framebuffer is multisampled, and the source and destination rectangles are not defined with the same (X0, Y0) and (X1, Y1) bounds.") * An INVALID_OPERATION error is generated if either the read or draw buffer is multisampled, and the dimensions of the source and destination rectangles are not identical, or if the formats of the read and draw framebuffers are not identical. Dependencies on EXT_sRGB: If EXT_sRGB is not supported, remove any language referring to sRGB conversion during a BlitFramebufferNV operation. Dependencies on EXT_color_buffer_half_float: If EXT_color_buffer_half_float is not supported, remove any language referring to floating point conversion during a BlitFramebufferNV operation. Dependencies on EXT_discard_framebuffer: If EXT_discard_framebuffer is supported, in Section 4.5 replace the sentence: " must be FRAMEBUFFER." with " must be DRAW_FRAMEBUFFER_NV, READ_FRAMEBUFFER_NV, or FRAMEBUFFER. FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER_NV." and relax the error to match. Dependencies on NV_fbo_color_attachments: If NV_fbo_color_attachments is not supported, replace the sentence: "There are the values of MAX_COLOR_ATTACHMENTS_NV color attachment points, plus one set each for the depth and stencil attachment points." with "There is one color attachment point, plus one each for the depth and stencil attachment points." Dependencies on NV_framebuffer_multisample: If NV_framebuffer_multisample is not supported, ignore edits to the second paragraph describing CheckFramebufferStatus. Dependencies on NV_read_buffer: If NV_read_buffer is not supported, ignore any language referring to ReadBufferNV. In this case the default OpenGL ES 2.0 behavior will take place, where GL_COLOR_ATTACHMENT0 will implicitly always be the read color buffer for application-created framebuffers and BACK for the default framebuffer. Dependencies on NV_draw_buffers: The absence of the NV_draw_buffers extension implies that there can be ever only one destination color buffer. No replication of the one read buffer data into possibly multiple destination color buffers can happen. Errors The error INVALID_FRAMEBUFFER_OPERATION is generated if BlitFramebufferNV is called while the draw framebuffer is not framebuffer complete. The error INVALID_FRAMEBUFFER_OPERATION is generated if BlitFramebufferNV, ReadPixels, CopyTex{Sub}Image2D, is called while the read framebuffer is not framebuffer complete. The error INVALID_VALUE is generated by BlitFramebufferNV if has any bits set other than those named by COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT. The error INVALID_OPERATION is generated if BlitFramebufferNV is called and includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT and is not NEAREST. The error INVALID_OPERATION is generated if BlitFramebufferNV is called and includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT and the source and destination depth or stencil buffer formats do not match. The error INVALID_ENUM is generated by BlitFramebufferNV if is not LINEAR or NEAREST. The error INVALID_ENUM is generated if BindFramebuffer, CheckFramebufferStatus, FramebufferTexture2D, FramebufferRenderbuffer, or GetFramebufferAttachmentParameteriv is called and is not DRAW_FRAMEBUFFER_NV, READ_FRAMEBUFFER_NV or FRAMEBUFFER. New State (modify table 6.24, "Framebuffer State") Get Value Type Get Command Initial Value Description Section ---------------------------- ---- ----------- -------------- ------------------- ------------ DRAW_FRAMEBUFFER_BINDING_NV Z+ GetIntegerv 0 framebuffer object bound 4.4.1 to DRAW_FRAMEBUFFER_NV READ_FRAMEBUFFER_BINDING_NV Z+ GetIntegerv 0 framebuffer object 4.4.1 to READ_FRAMEBUFFER_NV Remove reference to FRAMEBUFFER_BINDING. Issues 1) How does the functionality described by this extension differ from that provided by EXT_framebuffer_blit? - allow depth/stencil blits to be stretched using nearest filtering - allow fixed point<-->floating point format conversion - sRGB conversion 2) How does the functionality described by this extension differ from that provided by ES 3.0? - allow relocating MSAA resolve blits - allow MSAA buffers as destination of blits - allow overlapping blits with undefined results 3) How does this extension interact with NV_coverage_sample? UNRESOLVED: - should we allow blitting coverage information (GL_COVERAGE_BUFFER_BIT)? - should we allow VCAA resolve blits? - how to differentiate blitting the coverage buffer itself and doing a resolve blit? a) if read FBO has coverage buffer attachment, but draw FBO has not, a VCAA resolve blit is being attempted b) if GL_COVERAGE_BUFFER_BIT is part of , the coverage buffer should be copied as-is. - some surface blits would make it necessary to rotate the coverage information itself. Better not allow copies of the coverage buffer at all, restricting the VCAA functionality to resolve blits only? Revision History #06 03 Mar 2015 Xi Chen Add interaction with OpenGL ES 3.0 and later. #05 02 Feb 2015 James Helferty Add interaction with DiscardFramebuffer. #04 31 Jan 2013 Greg Roth Rewrote section 4.4.1 to better jibe with ES2.0 #03 09 Jan 2013 Greg Roth Language clarifications and more formatting corrections. #02 19 Apr 2012 Mathias Heyer Clarifications and formatting corrections #01 18 Apr 2012 Mathias Heyer Initial draft.