[cogl-offscreen] Cleans up the cogl offscreen API and adds documentation

There were several functions I believe no one is currently using that were
only implemented in the GL backend (cogl_offscreen_blit_region and
cogl_offscreen_blit) that have simply been removed so we have a chance to
think about design later with a real use case.

There was one nonsense function (cogl_offscreen_new_multisample) that
sounded exciting but in all cases it just returned COGL_INVALID_HANDLE
(though at least for GL it checked for multisampling support first!?)
it has also been removed.

The MASK draw buffer type has been removed. If we want to expose color
masking later then I think it at least would be nicer to have the mask be a
property that can be set on any draw buffer.

The cogl_draw_buffer and cogl_{push,pop}_draw_buffer function prototypes
have been moved up into cogl.h since they are for managing global Cogl state
and not for modifying or creating the actual offscreen buffers.

This also documents the API so for example desiphering the semantics of
cogl_offscreen_new_to_texture() should be a bit easier now.
This commit is contained in:
Robert Bragg 2009-04-30 22:19:43 +01:00
parent cb344560dc
commit 869a2b4167
8 changed files with 69 additions and 273 deletions

View File

@ -35,43 +35,47 @@ G_BEGIN_DECLS
/** /**
* SECTION:cogl-offscreen * SECTION:cogl-offscreen
* @short_description: Fuctions for creating and manipulating offscreen * @short_description: Fuctions for creating and manipulating offscreen
* frame buffer objects * frame buffer objects
* *
* COGL allows creating and operating on FBOs (Framebuffer Objects). * Cogl allows creating and operating on offscreen render targets.
*/ */
/* Offscreen api */ /* Offscreen api */
/** /**
* cogl_offscreen_new_to_texture: * cogl_offscreen_new_to_texture:
* @texhandle: * @handle: A CoglHandle for a Cogl texture
* *
* Returns: * This creates an offscreen buffer object using the given texture as the
* primary color buffer. It doesn't just initialize the contents of the
* offscreen buffer with the texture; they are tightly bound so that
* drawing to the offscreen buffer effectivly updates the contents of the
* given texture. You don't need to destroy the offscreen buffer before
* you can use the texture again.
*
* Note: This does not work with sliced Cogl textures.
*
* Returns: a CoglHandle for the new offscreen buffer or COGL_INVALID_HANDLE
* if it wasn't possible to create the buffer.
*/ */
CoglHandle cogl_offscreen_new_to_texture (CoglHandle texhandle); CoglHandle cogl_offscreen_new_to_texture (CoglHandle texhandle);
/**
* cogl_offscreen_new_multisample:
*
*
* Returns:
*/
CoglHandle cogl_offscreen_new_multisample (void);
/** /**
* cogl_offscreen_ref: * cogl_offscreen_ref:
* @handle: * @handle: A CoglHandle for an offscreen buffer
* *
* Returns: * Increments the reference count on the offscreen buffer.
*
* Returns: For convenience it returns the given CoglHandle
*/ */
CoglHandle cogl_offscreen_ref (CoglHandle handle); CoglHandle cogl_offscreen_ref (CoglHandle handle);
/** /**
* cogl_is_offscreen: * cogl_is_offscreen:
* @handle: A CoglHandle * @handle: A CoglHandle for an offscreen buffer
* *
* Gets whether the given handle references an existing offscreen * Gets whether the given handle references an existing offscreen buffer
* buffer object. * object.
* *
* Returns: %TRUE if the handle references an offscreen buffer, * Returns: %TRUE if the handle references an offscreen buffer,
* %FALSE otherwise * %FALSE otherwise
@ -80,68 +84,13 @@ gboolean cogl_is_offscreen (CoglHandle handle);
/** /**
* cogl_offscreen_unref: * cogl_offscreen_unref:
* @handle: * @handle: A CoglHandle for an offscreen buffer
* *
* Decreases the reference count for the offscreen buffer and frees it when
* the count reaches 0.
*/ */
void cogl_offscreen_unref (CoglHandle handle); void cogl_offscreen_unref (CoglHandle handle);
/**
* cogl_offscreen_blit:
* @src_buffer:
* @dst_buffer:
*
*/
void cogl_offscreen_blit (CoglHandle src_buffer,
CoglHandle dst_buffer);
/**
* cogl_offscreen_blit_region:
* @src_buffer:
* @dst_buffer:
* @src_x:
* @src_y:
* @src_w:
* @src_h:
* @dst_x:
* @dst_y:
* @dst_w:
* @dst_h:
*
*/
void cogl_offscreen_blit_region (CoglHandle src_buffer,
CoglHandle dst_buffer,
gint src_x,
gint src_y,
gint src_w,
gint src_h,
gint dst_x,
gint dst_y,
gint dst_w,
gint dst_h);
/**
* cogl_draw_buffer:
* @target:
* @offscreen:
*
*/
void cogl_draw_buffer (CoglBufferTarget target,
CoglHandle offscreen);
/**
* cogl_push_draw_buffer:
*
* Save cogl_draw_buffer() state.
*/
void cogl_push_draw_buffer (void);
/**
* cogl_pop_draw_buffer:
*
* Restore cogl_draw_buffer() state.
*/
void cogl_pop_draw_buffer (void);
G_END_DECLS G_END_DECLS
#endif /* __COGL_OFFSCREEN_H__ */ #endif /* __COGL_OFFSCREEN_H__ */

View File

@ -228,7 +228,6 @@ GType cogl_feature_flags_get_type (void) G_GNUC_CONST;
/** /**
* CoglBufferTarget: * CoglBufferTarget:
* @COGL_WINDOW_BUFFER: FIXME * @COGL_WINDOW_BUFFER: FIXME
* @COGL_MASK_BUFFER: FIXME
* @COGL_OFFSCREEN_BUFFER: FIXME * @COGL_OFFSCREEN_BUFFER: FIXME
* *
* Target flags for FBOs. * Target flags for FBOs.
@ -238,8 +237,7 @@ GType cogl_feature_flags_get_type (void) G_GNUC_CONST;
typedef enum typedef enum
{ {
COGL_WINDOW_BUFFER = (1 << 1), COGL_WINDOW_BUFFER = (1 << 1),
COGL_MASK_BUFFER = (1 << 2), COGL_OFFSCREEN_BUFFER = (1 << 2)
COGL_OFFSCREEN_BUFFER = (1 << 3)
} CoglBufferTarget; } CoglBufferTarget;
#define COGL_TYPE_BUFFER_TARGET (cogl_buffer_target_get_type ()) #define COGL_TYPE_BUFFER_TARGET (cogl_buffer_target_get_type ())

View File

@ -578,6 +578,35 @@ void cogl_clip_stack_save (void);
*/ */
void cogl_clip_stack_restore (void); void cogl_clip_stack_restore (void);
/**
* cogl_set_draw_buffer:
* @target: A #CoglBufferTarget that specifies what kind of draw buffer you
* are setting as the render target.
* @offscreen: If you are setting a draw buffer of type COGL_OFFSCREEN_BUFFER
* then this is a CoglHandle for the offscreen buffer.
*
* This redirects all subsequent drawing to the specified draw buffer. This
* can either be an offscreen buffer created with
* cogl_offscreen_new_to_texture () or you can revert to your original
* on screen window buffer.
*/
void cogl_set_draw_buffer (CoglBufferTarget target,
CoglHandle offscreen);
/**
* cogl_push_draw_buffer:
*
* Save cogl_set_draw_buffer() state.
*/
void cogl_push_draw_buffer (void);
/**
* cogl_pop_draw_buffer:
*
* Restore cogl_set_draw_buffer() state.
*/
void cogl_pop_draw_buffer (void);
/** /**
* cogl_flush_gl_state: * cogl_flush_gl_state:
* @flags: flags controlling what is flushed; currently unused, pass in 0 * @flags: flags controlling what is flushed; currently unused, pass in 0

View File

@ -179,7 +179,6 @@ cogl_buffer_target_get_type (void)
{ {
static const GFlagsValue values[] = { static const GFlagsValue values[] = {
{ COGL_WINDOW_BUFFER, "COGL_WINDOW_BUFFER", "window-buffer" }, { COGL_WINDOW_BUFFER, "COGL_WINDOW_BUFFER", "window-buffer" },
{ COGL_MASK_BUFFER, "COGL_MASK_BUFFER", "mask-buffer" },
{ COGL_OFFSCREEN_BUFFER, "COGL_OFFSCREEN_BUFFER", "offscreen-buffer" }, { COGL_OFFSCREEN_BUFFER, "COGL_OFFSCREEN_BUFFER", "offscreen-buffer" },
{ 0, NULL, NULL } { 0, NULL, NULL }
}; };

View File

@ -173,9 +173,7 @@ cogl_offscreen_new_to_texture
cogl_offscreen_ref cogl_offscreen_ref
cogl_offscreen_unref cogl_offscreen_unref
cogl_is_offscreen cogl_is_offscreen
cogl_offscreen_blit cogl_set_draw_buffer
cogl_offscreen_blit_region
cogl_draw_buffer
<SUBSECTION Private> <SUBSECTION Private>
cogl_offscreen_new_multisample cogl_offscreen_new_multisample
</SECTION> </SECTION>

View File

@ -148,15 +148,6 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
return _cogl_offscreen_handle_new (fbo); return _cogl_offscreen_handle_new (fbo);
} }
CoglHandle
cogl_offscreen_new_multisample ()
{
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN_MULTISAMPLE))
return COGL_INVALID_HANDLE;
return COGL_INVALID_HANDLE;
}
static void static void
_cogl_offscreen_free (CoglFbo *fbo) _cogl_offscreen_free (CoglFbo *fbo)
{ {
@ -171,75 +162,7 @@ _cogl_offscreen_free (CoglFbo *fbo)
} }
void void
cogl_offscreen_blit_region (CoglHandle src_buffer, cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
CoglHandle dst_buffer,
int src_x,
int src_y,
int src_w,
int src_h,
int dst_x,
int dst_y,
int dst_w,
int dst_h)
{
CoglFbo *src_fbo;
CoglFbo *dst_fbo;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT))
return;
/* Make sure these are valid fbo handles */
if (!cogl_is_offscreen (src_buffer))
return;
if (!cogl_is_offscreen (dst_buffer))
return;
src_fbo = _cogl_offscreen_pointer_from_handle (src_buffer);
dst_fbo = _cogl_offscreen_pointer_from_handle (dst_buffer);
/* Copy (and scale) a region from one to another framebuffer */
GE( glBindFramebufferEXT (GL_READ_FRAMEBUFFER_EXT, src_fbo->gl_handle) );
GE( glBindFramebufferEXT (GL_DRAW_FRAMEBUFFER_EXT, dst_fbo->gl_handle) );
GE( glBlitFramebufferEXT (src_x, src_y, src_x + src_w, src_y + src_h,
dst_x, dst_y, dst_x + dst_w, dst_y + dst_h,
GL_COLOR_BUFFER_BIT, GL_LINEAR) );
}
void
cogl_offscreen_blit (CoglHandle src_buffer,
CoglHandle dst_buffer)
{
CoglFbo *src_fbo;
CoglFbo *dst_fbo;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT))
return;
/* Make sure these are valid fbo handles */
if (!cogl_is_offscreen (src_buffer))
return;
if (!cogl_is_offscreen (dst_buffer))
return;
src_fbo = _cogl_offscreen_pointer_from_handle (src_buffer);
dst_fbo = _cogl_offscreen_pointer_from_handle (dst_buffer);
/* Copy (and scale) whole image from one to another framebuffer */
GE( glBindFramebufferEXT (GL_READ_FRAMEBUFFER_EXT, src_fbo->gl_handle) );
GE( glBindFramebufferEXT (GL_DRAW_FRAMEBUFFER_EXT, dst_fbo->gl_handle) );
GE( glBlitFramebufferEXT (0, 0, src_fbo->width, src_fbo->height,
0, 0, dst_fbo->width, dst_fbo->height,
GL_COLOR_BUFFER_BIT, GL_LINEAR) );
}
void
cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
{ {
CoglFbo *fbo = NULL; CoglFbo *fbo = NULL;
CoglDrawBufferState *draw_buffer; CoglDrawBufferState *draw_buffer;
@ -301,10 +224,8 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
GE( glEnable (GL_SCISSOR_TEST) ); GE( glEnable (GL_SCISSOR_TEST) );
GE( glClear (GL_COLOR_BUFFER_BIT) ); GE( glClear (GL_COLOR_BUFFER_BIT) );
GE( glPopAttrib () ); GE( glPopAttrib () );
} }
else if ((target & COGL_WINDOW_BUFFER) || else if (target & COGL_WINDOW_BUFFER)
(target & COGL_MASK_BUFFER))
{ {
/* Check current draw buffer target */ /* Check current draw buffer target */
if (draw_buffer->target == COGL_OFFSCREEN_BUFFER) if (draw_buffer->target == COGL_OFFSCREEN_BUFFER)
@ -322,23 +243,6 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
/* Bind window framebuffer object */ /* Bind window framebuffer object */
GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) ); GE( glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0) );
if (target == COGL_WINDOW_BUFFER)
{
/* Draw to RGB channels */
GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE) );
}
else if (target == COGL_MASK_BUFFER)
{
/* Draw only to ALPHA channel */
GE( glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE) );
}
else
{
/* Draw to all channels */
GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) );
}
} }
/* Store new target */ /* Store new target */
@ -389,14 +293,14 @@ cogl_pop_draw_buffer(void)
to_pop = ctx->draw_buffer_stack->data; to_pop = ctx->draw_buffer_stack->data;
to_restore = ctx->draw_buffer_stack->next->data; to_restore = ctx->draw_buffer_stack->next->data;
/* the logic in cogl_draw_buffer() only works if /* the logic in cogl_set_draw_buffer() only works if
* to_pop is still on top of the stack, because * to_pop is still on top of the stack, because
* cogl_draw_buffer() needs to know the previous * cogl_set_draw_buffer() needs to know the previous
* state. * state.
*/ */
cogl_draw_buffer (to_restore->target, to_restore->offscreen); cogl_set_draw_buffer (to_restore->target, to_restore->offscreen);
/* cogl_draw_buffer() should have set top of stack /* cogl_set_draw_buffer() should have set top of stack
* to to_restore * to to_restore
*/ */
g_assert (to_restore->target == to_pop->target); g_assert (to_restore->target == to_pop->target);
@ -409,3 +313,4 @@ cogl_pop_draw_buffer(void)
g_slice_free (CoglDrawBufferState, to_pop); g_slice_free (CoglDrawBufferState, to_pop);
} }

View File

@ -130,15 +130,6 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
return _cogl_offscreen_handle_new (fbo); return _cogl_offscreen_handle_new (fbo);
} }
CoglHandle
cogl_offscreen_new_multisample ()
{
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN_MULTISAMPLE))
return COGL_INVALID_HANDLE;
return COGL_INVALID_HANDLE;
}
static void static void
_cogl_offscreen_free (CoglFbo *fbo) _cogl_offscreen_free (CoglFbo *fbo)
{ {
@ -153,31 +144,7 @@ _cogl_offscreen_free (CoglFbo *fbo)
} }
void void
cogl_offscreen_blit_region (CoglHandle src_buffer, cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
CoglHandle dst_buffer,
int src_x,
int src_y,
int src_w,
int src_h,
int dst_x,
int dst_y,
int dst_w,
int dst_h)
{
/* Not supported on GLES */
return;
}
void
cogl_offscreen_blit (CoglHandle src_buffer,
CoglHandle dst_buffer)
{
/* Not supported on GLES */
return;
}
void
cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
{ {
CoglFbo *fbo = NULL; CoglFbo *fbo = NULL;
CoglDrawBufferState *draw_buffer; CoglDrawBufferState *draw_buffer;
@ -249,8 +216,7 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
scissor_box[2], scissor_box[3]); scissor_box[2], scissor_box[3]);
} }
else if ((target & COGL_WINDOW_BUFFER) || else if (target & COGL_WINDOW_BUFFER)
(target & COGL_MASK_BUFFER))
{ {
/* Check current draw buffer target */ /* Check current draw buffer target */
if (draw_buffer->target == COGL_OFFSCREEN_BUFFER) if (draw_buffer->target == COGL_OFFSCREEN_BUFFER)
@ -269,23 +235,6 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
/* Bind window framebuffer object */ /* Bind window framebuffer object */
GE( glBindFramebuffer (GL_FRAMEBUFFER, 0) ); GE( glBindFramebuffer (GL_FRAMEBUFFER, 0) );
if (target == COGL_WINDOW_BUFFER)
{
/* Draw to RGB channels */
GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) );
}
else if (target == COGL_MASK_BUFFER)
{
/* Draw only to ALPHA channel */
GE( glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE) );
}
else
{
/* Draw to all channels */
GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) );
}
} }
/* Store new target */ /* Store new target */
@ -336,14 +285,14 @@ cogl_pop_draw_buffer(void)
to_pop = ctx->draw_buffer_stack->data; to_pop = ctx->draw_buffer_stack->data;
to_restore = ctx->draw_buffer_stack->next->data; to_restore = ctx->draw_buffer_stack->next->data;
/* the logic in cogl_draw_buffer() only works if /* the logic in cogl_set_draw_buffer() only works if
* to_pop is still on top of the stack, because * to_pop is still on top of the stack, because
* cogl_draw_buffer() needs to know the previous * cogl_set_draw_buffer() needs to know the previous
* state. * state.
*/ */
cogl_draw_buffer (to_restore->target, to_restore->offscreen); cogl_set_draw_buffer (to_restore->target, to_restore->offscreen);
/* cogl_draw_buffer() should have set top of stack /* cogl_set_draw_buffer() should have set top of stack
* to to_restore * to to_restore
*/ */
g_assert (to_restore->target == to_pop->target); g_assert (to_restore->target == to_pop->target);
@ -373,12 +322,6 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
return COGL_INVALID_HANDLE; return COGL_INVALID_HANDLE;
} }
CoglHandle
cogl_offscreen_new_multisample ()
{
return COGL_INVALID_HANDLE;
}
CoglHandle CoglHandle
cogl_offscreen_ref (CoglHandle handle) cogl_offscreen_ref (CoglHandle handle)
{ {
@ -391,27 +334,7 @@ cogl_offscreen_unref (CoglHandle handle)
} }
void void
cogl_offscreen_blit_region (CoglHandle src_buffer, cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
CoglHandle dst_buffer,
int src_x,
int src_y,
int src_w,
int src_h,
int dst_x,
int dst_y,
int dst_w,
int dst_h)
{
}
void
cogl_offscreen_blit (CoglHandle src_buffer,
CoglHandle dst_buffer)
{
}
void
cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
{ {
} }

View File

@ -483,9 +483,6 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
_cogl_current_matrix_push (); _cogl_current_matrix_push ();
_cogl_current_matrix_identity (); _cogl_current_matrix_identity ();
/* Draw to all channels */
cogl_draw_buffer (COGL_WINDOW_BUFFER | COGL_MASK_BUFFER, 0);
/* Direct copy operation */ /* Direct copy operation */
if (ctx->texture_download_material == COGL_INVALID_HANDLE) if (ctx->texture_download_material == COGL_INVALID_HANDLE)
@ -582,8 +579,6 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW); _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
_cogl_current_matrix_pop (); _cogl_current_matrix_pop ();
cogl_draw_buffer (COGL_WINDOW_BUFFER, 0);
return TRUE; return TRUE;
} }