Add an internal _cogl_offscreen_new_to_texture_full function
This function is the same as cogl_offscreen_new_to_texture but it takes a level parameter and a set of flags so that FBOs can be used to render to higher mipmap levels and to disable the depth and stencil buffers. cogl_offscreen_new_to_texture now just calls the new function with the level set to zero. This function could be useful in a few places in Cogl where we want to use FBOs as an implementation detail such as when copying between textures. http://bugzilla.clutter-project.org/show_bug.cgi?id=2414
This commit is contained in:
parent
d52bd995a6
commit
b4016f64fa
@ -66,6 +66,12 @@ typedef struct _CoglOffscreen
|
|||||||
CoglHandle texture;
|
CoglHandle texture;
|
||||||
} CoglOffscreen;
|
} CoglOffscreen;
|
||||||
|
|
||||||
|
/* Flags to pass to _cogl_offscreen_new_to_texture_full */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL = 1
|
||||||
|
} CoglOffscreenFlags;
|
||||||
|
|
||||||
#define COGL_OFFSCREEN(X) ((CoglOffscreen *)(X))
|
#define COGL_OFFSCREEN(X) ((CoglOffscreen *)(X))
|
||||||
|
|
||||||
typedef struct _CoglOnscreen
|
typedef struct _CoglOnscreen
|
||||||
@ -143,5 +149,23 @@ _cogl_create_framebuffer_stack (void);
|
|||||||
void
|
void
|
||||||
_cogl_free_framebuffer_stack (GSList *stack);
|
_cogl_free_framebuffer_stack (GSList *stack);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _cogl_offscreen_new_to_texture_full:
|
||||||
|
* @texhandle: A handle to the texture to target
|
||||||
|
* @create_flags: Flags specifying how to create the FBO
|
||||||
|
* @level: The mipmap level within the texture to target
|
||||||
|
*
|
||||||
|
* Creates a new offscreen buffer which will target the given
|
||||||
|
* texture. By default the buffer will have a depth and stencil
|
||||||
|
* buffer. This can be disabled by passing
|
||||||
|
* %COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL in @create_flags.
|
||||||
|
*
|
||||||
|
* Return value: the new CoglOffscreen object.
|
||||||
|
*/
|
||||||
|
CoglHandle
|
||||||
|
_cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
|
||||||
|
CoglOffscreenFlags create_flags,
|
||||||
|
unsigned int level);
|
||||||
|
|
||||||
#endif /* __COGL_FRAMEBUFFER_PRIVATE_H */
|
#endif /* __COGL_FRAMEBUFFER_PRIVATE_H */
|
||||||
|
|
||||||
|
@ -324,10 +324,18 @@ _cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
|
|||||||
framebuffer->dirty_bitmasks = FALSE;
|
framebuffer->dirty_bitmasks = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CoglHandle texture;
|
||||||
|
unsigned int level;
|
||||||
|
unsigned int level_width;
|
||||||
|
unsigned int level_height;
|
||||||
|
} CoglFramebufferTryFBOData;
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
try_creating_fbo (CoglOffscreen *offscreen,
|
try_creating_fbo (CoglOffscreen *offscreen,
|
||||||
TryFBOFlags flags,
|
TryFBOFlags flags,
|
||||||
CoglHandle texture)
|
CoglFramebufferTryFBOData *data)
|
||||||
{
|
{
|
||||||
GLuint gl_depth_stencil_handle;
|
GLuint gl_depth_stencil_handle;
|
||||||
GLuint gl_depth_handle;
|
GLuint gl_depth_handle;
|
||||||
@ -339,7 +347,8 @@ try_creating_fbo (CoglOffscreen *offscreen,
|
|||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
|
|
||||||
if (!cogl_texture_get_gl_texture (texture, &tex_gl_handle, &tex_gl_target))
|
if (!cogl_texture_get_gl_texture (data->texture,
|
||||||
|
&tex_gl_handle, &tex_gl_target))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (tex_gl_target != GL_TEXTURE_2D
|
if (tex_gl_target != GL_TEXTURE_2D
|
||||||
@ -362,7 +371,7 @@ try_creating_fbo (CoglOffscreen *offscreen,
|
|||||||
offscreen->fbo_handle = fbo_gl_handle;
|
offscreen->fbo_handle = fbo_gl_handle;
|
||||||
|
|
||||||
GE (glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
GE (glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||||
tex_gl_target, tex_gl_handle, 0));
|
tex_gl_target, tex_gl_handle, data->level));
|
||||||
|
|
||||||
if (flags & _TRY_DEPTH_STENCIL)
|
if (flags & _TRY_DEPTH_STENCIL)
|
||||||
{
|
{
|
||||||
@ -370,8 +379,8 @@ try_creating_fbo (CoglOffscreen *offscreen,
|
|||||||
GE (glGenRenderbuffers (1, &gl_depth_stencil_handle));
|
GE (glGenRenderbuffers (1, &gl_depth_stencil_handle));
|
||||||
GE (glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_stencil_handle));
|
GE (glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_stencil_handle));
|
||||||
GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_STENCIL,
|
GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_STENCIL,
|
||||||
cogl_texture_get_width (texture),
|
data->level_width,
|
||||||
cogl_texture_get_height (texture)));
|
data->level_height));
|
||||||
GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
|
GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
|
||||||
GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
|
GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||||
GL_STENCIL_ATTACHMENT,
|
GL_STENCIL_ATTACHMENT,
|
||||||
@ -391,8 +400,8 @@ try_creating_fbo (CoglOffscreen *offscreen,
|
|||||||
/* For now we just ask for GL_DEPTH_COMPONENT16 since this is all that's
|
/* For now we just ask for GL_DEPTH_COMPONENT16 since this is all that's
|
||||||
* available under GLES */
|
* available under GLES */
|
||||||
GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
|
GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
|
||||||
cogl_texture_get_width (texture),
|
data->level_width,
|
||||||
cogl_texture_get_height (texture)));
|
data->level_height));
|
||||||
GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
|
GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
|
||||||
GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
|
GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||||
GL_DEPTH_ATTACHMENT,
|
GL_DEPTH_ATTACHMENT,
|
||||||
@ -407,8 +416,8 @@ try_creating_fbo (CoglOffscreen *offscreen,
|
|||||||
GE (glGenRenderbuffers (1, &gl_stencil_handle));
|
GE (glGenRenderbuffers (1, &gl_stencil_handle));
|
||||||
GE (glBindRenderbuffer (GL_RENDERBUFFER, gl_stencil_handle));
|
GE (glBindRenderbuffer (GL_RENDERBUFFER, gl_stencil_handle));
|
||||||
GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX8,
|
GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX8,
|
||||||
cogl_texture_get_width (texture),
|
data->level_width,
|
||||||
cogl_texture_get_height (texture)));
|
data->level_height));
|
||||||
GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
|
GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
|
||||||
GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
|
GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
|
||||||
GL_STENCIL_ATTACHMENT,
|
GL_STENCIL_ATTACHMENT,
|
||||||
@ -443,11 +452,16 @@ try_creating_fbo (CoglOffscreen *offscreen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
_cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
|
||||||
|
CoglOffscreenFlags create_flags,
|
||||||
|
unsigned int level)
|
||||||
{
|
{
|
||||||
CoglOffscreen *offscreen;
|
CoglOffscreen *offscreen;
|
||||||
static TryFBOFlags flags;
|
static TryFBOFlags flags;
|
||||||
static gboolean have_working_flags = FALSE;
|
static gboolean have_working_flags = FALSE;
|
||||||
|
unsigned int i;
|
||||||
|
CoglFramebufferTryFBOData data;
|
||||||
|
gboolean fbo_created;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
@ -462,6 +476,27 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
|||||||
if (cogl_texture_is_sliced (texhandle))
|
if (cogl_texture_is_sliced (texhandle))
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
|
data.texture = texhandle;
|
||||||
|
data.level = level;
|
||||||
|
|
||||||
|
/* Calculate the size of the texture at this mipmap level to ensure
|
||||||
|
that it's a valid level */
|
||||||
|
data.level_width = cogl_texture_get_width (texhandle);
|
||||||
|
data.level_height = cogl_texture_get_height (texhandle);
|
||||||
|
|
||||||
|
for (i = 0; i < level; i++)
|
||||||
|
{
|
||||||
|
/* If neither dimension can be further divided then the level is
|
||||||
|
invalid */
|
||||||
|
if (data.level_width == 1 && data.level_height == 1)
|
||||||
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
|
if (data.level_width > 1)
|
||||||
|
data.level_width >>= 1;
|
||||||
|
if (data.level_height > 1)
|
||||||
|
data.level_height >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: The framebuffer_object spec isn't clear in defining whether attaching
|
/* XXX: The framebuffer_object spec isn't clear in defining whether attaching
|
||||||
* a texture as a renderbuffer with mipmap filtering enabled while the
|
* a texture as a renderbuffer with mipmap filtering enabled while the
|
||||||
* mipmaps have not been uploaded should result in an incomplete framebuffer
|
* mipmaps have not been uploaded should result in an incomplete framebuffer
|
||||||
@ -477,25 +512,36 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
|||||||
offscreen = g_new0 (CoglOffscreen, 1);
|
offscreen = g_new0 (CoglOffscreen, 1);
|
||||||
offscreen->texture = cogl_handle_ref (texhandle);
|
offscreen->texture = cogl_handle_ref (texhandle);
|
||||||
|
|
||||||
if ((have_working_flags &&
|
if ((create_flags & COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL))
|
||||||
try_creating_fbo (offscreen, flags, texhandle)) ||
|
fbo_created = try_creating_fbo (offscreen, 0, &data);
|
||||||
#ifdef HAVE_COGL_GL
|
else
|
||||||
try_creating_fbo (offscreen, flags = _TRY_DEPTH_STENCIL, texhandle) ||
|
|
||||||
#endif
|
|
||||||
try_creating_fbo (offscreen, flags = _TRY_DEPTH | _TRY_STENCIL,
|
|
||||||
texhandle) ||
|
|
||||||
try_creating_fbo (offscreen, flags = _TRY_STENCIL, texhandle) ||
|
|
||||||
try_creating_fbo (offscreen, flags = _TRY_DEPTH, texhandle) ||
|
|
||||||
try_creating_fbo (offscreen, flags = 0, texhandle))
|
|
||||||
{
|
{
|
||||||
/* Record that the last set of flags succeeded so that we can
|
if ((have_working_flags &&
|
||||||
try that set first next time */
|
try_creating_fbo (offscreen, flags, &data)) ||
|
||||||
have_working_flags = TRUE;
|
#ifdef HAVE_COGL_GL
|
||||||
|
try_creating_fbo (offscreen, flags = _TRY_DEPTH_STENCIL, &data) ||
|
||||||
|
#endif
|
||||||
|
try_creating_fbo (offscreen, flags = _TRY_DEPTH | _TRY_STENCIL,
|
||||||
|
&data) ||
|
||||||
|
try_creating_fbo (offscreen, flags = _TRY_STENCIL, &data) ||
|
||||||
|
try_creating_fbo (offscreen, flags = _TRY_DEPTH, &data) ||
|
||||||
|
try_creating_fbo (offscreen, flags = 0, &data))
|
||||||
|
{
|
||||||
|
/* Record that the last set of flags succeeded so that we can
|
||||||
|
try that set first next time */
|
||||||
|
have_working_flags = TRUE;
|
||||||
|
fbo_created = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fbo_created = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fbo_created)
|
||||||
|
{
|
||||||
_cogl_framebuffer_init (COGL_FRAMEBUFFER (offscreen),
|
_cogl_framebuffer_init (COGL_FRAMEBUFFER (offscreen),
|
||||||
COGL_FRAMEBUFFER_TYPE_OFFSCREEN,
|
COGL_FRAMEBUFFER_TYPE_OFFSCREEN,
|
||||||
cogl_texture_get_width (texhandle),
|
data.level_width,
|
||||||
cogl_texture_get_height (texhandle));
|
data.level_height);
|
||||||
|
|
||||||
return _cogl_offscreen_object_new (offscreen);
|
return _cogl_offscreen_object_new (offscreen);
|
||||||
}
|
}
|
||||||
@ -508,6 +554,12 @@ cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoglHandle
|
||||||
|
cogl_offscreen_new_to_texture (CoglHandle texhandle)
|
||||||
|
{
|
||||||
|
return _cogl_offscreen_new_to_texture_full (texhandle, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_offscreen_free (CoglOffscreen *offscreen)
|
_cogl_offscreen_free (CoglOffscreen *offscreen)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user