cogl-framebuffer: Add _cogl_blit_framebuffer
This adds the _cogl_blit_framebuffer internal function which is a wrapper around glBlitFramebuffer. The API is changed from the GL version of the function to reflect the limitations provided by the GL_ANGLE_framebuffer_blit extension (eg, no scaling or mirroring).
This commit is contained in:
parent
392cfb493a
commit
9d242b62a9
@ -288,5 +288,58 @@ void
|
|||||||
_cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
|
_cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
|
||||||
CoglFramebuffer *read_buffer);
|
CoglFramebuffer *read_buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _cogl_blit_framebuffer:
|
||||||
|
* @src_x: Source x position
|
||||||
|
* @src_y: Source y position
|
||||||
|
* @dst_x: Destination x position
|
||||||
|
* @dst_y: Destination y position
|
||||||
|
* @width: Width of region to copy
|
||||||
|
* @height: Height of region to copy
|
||||||
|
*
|
||||||
|
* This blits a region of the color buffer of the current draw buffer
|
||||||
|
* to the current read buffer. The draw and read buffers can be set up
|
||||||
|
* using _cogl_push_framebuffers(). This function should only be
|
||||||
|
* called if the COGL_FEATURE_OFFSCREEN_BLIT feature is
|
||||||
|
* advertised. The two buffers must both be offscreen and have the
|
||||||
|
* same format.
|
||||||
|
*
|
||||||
|
* Note that this function differs a lot from the glBlitFramebuffer
|
||||||
|
* function provided by the GL_EXT_framebuffer_blit extension. Notably
|
||||||
|
* it doesn't support having different sizes for the source and
|
||||||
|
* destination rectangle. This isn't supported by the corresponding
|
||||||
|
* GL_ANGLE_framebuffer_blit extension on GLES2.0 and it doesn't seem
|
||||||
|
* like a particularly useful feature. If the application wanted to
|
||||||
|
* scale the results it may make more sense to draw a primitive
|
||||||
|
* instead.
|
||||||
|
*
|
||||||
|
* We can only really support blitting between two offscreen buffers
|
||||||
|
* for this function on GLES2.0. This is because we effectively render
|
||||||
|
* upside down to offscreen buffers to maintain Cogl's representation
|
||||||
|
* of the texture coordinate system where 0,0 is the top left of the
|
||||||
|
* texture. If we were to blit from an offscreen to an onscreen buffer
|
||||||
|
* then we would need to mirror the blit along the x-axis but the GLES
|
||||||
|
* extension does not support this.
|
||||||
|
*
|
||||||
|
* The GL function is documented to be affected by the scissor. This
|
||||||
|
* function therefore ensure that an empty clip stack is flushed
|
||||||
|
* before performing the blit which means the scissor is effectively
|
||||||
|
* ignored.
|
||||||
|
*
|
||||||
|
* The function also doesn't support specifying the buffers to copy
|
||||||
|
* and instead only the color buffer is copied. When copying the depth
|
||||||
|
* or stencil buffers the extension on GLES2.0 only supports copying
|
||||||
|
* the full buffer which would be awkward to document with this
|
||||||
|
* API. If we wanted to support that feature it may be better to have
|
||||||
|
* a separate function to copy the entire buffer for a given mask.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_cogl_blit_framebuffer (unsigned int src_x,
|
||||||
|
unsigned int src_y,
|
||||||
|
unsigned int dst_x,
|
||||||
|
unsigned int dst_y,
|
||||||
|
unsigned int width,
|
||||||
|
unsigned int height);
|
||||||
|
|
||||||
#endif /* __COGL_FRAMEBUFFER_PRIVATE_H */
|
#endif /* __COGL_FRAMEBUFFER_PRIVATE_H */
|
||||||
|
|
||||||
|
@ -54,6 +54,8 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define glBlitFramebuffer ctx->drv.pf_glBlitFramebuffer
|
||||||
|
|
||||||
#ifndef GL_FRAMEBUFFER
|
#ifndef GL_FRAMEBUFFER
|
||||||
#define GL_FRAMEBUFFER 0x8D40
|
#define GL_FRAMEBUFFER 0x8D40
|
||||||
#endif
|
#endif
|
||||||
@ -1429,3 +1431,47 @@ _cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_blit_framebuffer (unsigned int src_x,
|
||||||
|
unsigned int src_y,
|
||||||
|
unsigned int dst_x,
|
||||||
|
unsigned int dst_y,
|
||||||
|
unsigned int width,
|
||||||
|
unsigned int height)
|
||||||
|
{
|
||||||
|
CoglFramebuffer *draw_buffer;
|
||||||
|
CoglFramebuffer *read_buffer;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
draw_buffer = _cogl_get_draw_buffer ();
|
||||||
|
read_buffer = _cogl_get_read_buffer ();
|
||||||
|
|
||||||
|
g_return_if_fail (cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT));
|
||||||
|
/* We can only support blitting between offscreen buffers because
|
||||||
|
otherwise we would need to mirror the image and GLES2.0 doesn't
|
||||||
|
support this */
|
||||||
|
g_return_if_fail (cogl_is_offscreen (draw_buffer));
|
||||||
|
g_return_if_fail (cogl_is_offscreen (read_buffer));
|
||||||
|
/* The buffers must be the same format */
|
||||||
|
g_return_if_fail (draw_buffer->format == read_buffer->format);
|
||||||
|
|
||||||
|
/* Make sure the current framebuffers are bound. We explicitly avoid
|
||||||
|
flushing the clip state so we can bind our own empty state */
|
||||||
|
_cogl_framebuffer_flush_state (_cogl_get_draw_buffer (),
|
||||||
|
_cogl_get_read_buffer (),
|
||||||
|
COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE);
|
||||||
|
|
||||||
|
/* Flush any empty clip stack because glBlitFramebuffer is affected
|
||||||
|
by the scissor and we want to hide this feature for the Cogl API
|
||||||
|
because it's not obvious to an app how the clip state will affect
|
||||||
|
the scissor */
|
||||||
|
_cogl_clip_stack_flush (NULL);
|
||||||
|
|
||||||
|
glBlitFramebuffer (src_x, src_y,
|
||||||
|
src_x + width, src_y + height,
|
||||||
|
dst_x, dst_y,
|
||||||
|
dst_x + width, dst_y + height,
|
||||||
|
GL_COLOR_BUFFER_BIT,
|
||||||
|
GL_NEAREST);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user