framebuffer: defer calculating level size until allocation

The plan is to defer more of the work for creating a texture until
allocation time, but that means we won't be able to always assume
we can query the size of a texture when creating an offscreen
framebuffer from a texture (consider for example using
_texture_new_from_file() where the size isn't known until the file has
been loaded). This defers needing to know the size of the texture
underlying an offscreen framebuffer until calling
cogl_framebuffer_allocate().

Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 9688e7dc1eeae3144729dfd4a4bf409620346bf4)
This commit is contained in:
Robert Bragg 2013-06-27 04:24:34 +01:00
parent 08ba5c64b9
commit 96ed01cc18
4 changed files with 53 additions and 34 deletions

View File

@ -205,8 +205,6 @@ struct _CoglOffscreen
CoglTexture *texture; CoglTexture *texture;
int texture_level; int texture_level;
int texture_level_width;
int texture_level_height;
CoglTexture *depth_texture; CoglTexture *depth_texture;

View File

@ -643,34 +643,27 @@ _cogl_offscreen_new_with_texture_full (CoglTexture *texture,
CoglContext *ctx = texture->context; CoglContext *ctx = texture->context;
CoglOffscreen *offscreen; CoglOffscreen *offscreen;
CoglFramebuffer *fb; CoglFramebuffer *fb;
int level_width;
int level_height;
CoglOffscreen *ret; CoglOffscreen *ret;
_COGL_RETURN_VAL_IF_FAIL (cogl_is_texture (texture), NULL); _COGL_RETURN_VAL_IF_FAIL (cogl_is_texture (texture), NULL);
_COGL_RETURN_VAL_IF_FAIL (level < _cogl_texture_get_n_levels (texture),
NULL);
_cogl_texture_get_level_size (texture,
level,
&level_width,
&level_height,
NULL);
offscreen = g_new0 (CoglOffscreen, 1); offscreen = g_new0 (CoglOffscreen, 1);
offscreen->texture = cogl_object_ref (texture); offscreen->texture = cogl_object_ref (texture);
offscreen->texture_level = level; offscreen->texture_level = level;
offscreen->texture_level_width = level_width;
offscreen->texture_level_height = level_height;
offscreen->create_flags = create_flags; offscreen->create_flags = create_flags;
fb = COGL_FRAMEBUFFER (offscreen); fb = COGL_FRAMEBUFFER (offscreen);
/* NB: we can't assume we can query the texture's width yet, since
* it might not have been allocated yet and for example if the
* texture is being loaded from a file then the file might not
* have been read yet. */
_cogl_framebuffer_init (fb, _cogl_framebuffer_init (fb,
ctx, ctx,
COGL_FRAMEBUFFER_TYPE_OFFSCREEN, COGL_FRAMEBUFFER_TYPE_OFFSCREEN,
level_width, -1, /* unknown width, until allocation */
level_height); -1); /* unknown height until allocation */
ret = _cogl_offscreen_object_new (offscreen); ret = _cogl_offscreen_object_new (offscreen);
@ -780,6 +773,13 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
return FALSE; return FALSE;
} }
/* Now that the texture has been allocated we can determine a
* size for the framebuffer... */
framebuffer->width = cogl_texture_get_width (offscreen->texture);
framebuffer->height = cogl_texture_get_height (offscreen->texture);
framebuffer->viewport_width = framebuffer->width;
framebuffer->viewport_height = framebuffer->height;
/* Forward the texture format as the internal format of the /* Forward the texture format as the internal format of the
* framebuffer */ * framebuffer */
framebuffer->internal_format = framebuffer->internal_format =

View File

@ -1693,6 +1693,8 @@ _cogl_gles2_offscreen_allocate (CoglOffscreen *offscreen,
const CoglWinsysVtable *winsys; const CoglWinsysVtable *winsys;
CoglError *internal_error = NULL; CoglError *internal_error = NULL;
CoglGLES2Offscreen *gles2_offscreen; CoglGLES2Offscreen *gles2_offscreen;
int level_width;
int level_height;
if (!framebuffer->allocated && if (!framebuffer->allocated &&
!cogl_framebuffer_allocate (framebuffer, error)) !cogl_framebuffer_allocate (framebuffer, error))
@ -1722,11 +1724,18 @@ _cogl_gles2_offscreen_allocate (CoglOffscreen *offscreen,
} }
gles2_offscreen = g_slice_new0 (CoglGLES2Offscreen); gles2_offscreen = g_slice_new0 (CoglGLES2Offscreen);
_cogl_texture_get_level_size (offscreen->texture,
offscreen->texture_level,
&level_width,
&level_height,
NULL);
if (!_cogl_framebuffer_try_creating_gl_fbo (gles2_context->context, if (!_cogl_framebuffer_try_creating_gl_fbo (gles2_context->context,
offscreen->texture, offscreen->texture,
offscreen->texture_level, offscreen->texture_level,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height, level_height,
offscreen->depth_texture, offscreen->depth_texture,
&COGL_FRAMEBUFFER (offscreen)->config, &COGL_FRAMEBUFFER (offscreen)->config,
offscreen->allocation_flags, offscreen->allocation_flags,

View File

@ -734,14 +734,26 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
CoglContext *ctx = fb->context; CoglContext *ctx = fb->context;
CoglOffscreenAllocateFlags flags; CoglOffscreenAllocateFlags flags;
CoglGLFramebuffer *gl_framebuffer = &offscreen->gl_framebuffer; CoglGLFramebuffer *gl_framebuffer = &offscreen->gl_framebuffer;
int level_width;
int level_height;
_COGL_RETURN_VAL_IF_FAIL (offscreen->texture_level <
_cogl_texture_get_n_levels (offscreen->texture),
NULL);
_cogl_texture_get_level_size (offscreen->texture,
offscreen->texture_level,
&level_width,
&level_height,
NULL);
if (fb->config.depth_texture_enabled && if (fb->config.depth_texture_enabled &&
offscreen->depth_texture == NULL) offscreen->depth_texture == NULL)
{ {
offscreen->depth_texture = offscreen->depth_texture =
create_depth_texture (ctx, create_depth_texture (ctx,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height); level_height);
if (!cogl_texture_allocate (offscreen->depth_texture, error)) if (!cogl_texture_allocate (offscreen->depth_texture, error))
{ {
@ -770,8 +782,8 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
try_creating_fbo (ctx, try_creating_fbo (ctx,
offscreen->texture, offscreen->texture,
offscreen->texture_level, offscreen->texture_level,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height, level_height,
offscreen->depth_texture, offscreen->depth_texture,
&fb->config, &fb->config,
flags = 0, flags = 0,
@ -781,8 +793,8 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
try_creating_fbo (ctx, try_creating_fbo (ctx,
offscreen->texture, offscreen->texture,
offscreen->texture_level, offscreen->texture_level,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height, level_height,
offscreen->depth_texture, offscreen->depth_texture,
&fb->config, &fb->config,
flags = ctx->last_offscreen_allocate_flags, flags = ctx->last_offscreen_allocate_flags,
@ -800,8 +812,8 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
try_creating_fbo (ctx, try_creating_fbo (ctx,
offscreen->texture, offscreen->texture,
offscreen->texture_level, offscreen->texture_level,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height, level_height,
offscreen->depth_texture, offscreen->depth_texture,
&fb->config, &fb->config,
flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL, flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL,
@ -810,8 +822,8 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
try_creating_fbo (ctx, try_creating_fbo (ctx,
offscreen->texture, offscreen->texture,
offscreen->texture_level, offscreen->texture_level,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height, level_height,
offscreen->depth_texture, offscreen->depth_texture,
&fb->config, &fb->config,
flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH | flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH |
@ -821,8 +833,8 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
try_creating_fbo (ctx, try_creating_fbo (ctx,
offscreen->texture, offscreen->texture,
offscreen->texture_level, offscreen->texture_level,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height, level_height,
offscreen->depth_texture, offscreen->depth_texture,
&fb->config, &fb->config,
flags = COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL, flags = COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL,
@ -831,8 +843,8 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
try_creating_fbo (ctx, try_creating_fbo (ctx,
offscreen->texture, offscreen->texture,
offscreen->texture_level, offscreen->texture_level,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height, level_height,
offscreen->depth_texture, offscreen->depth_texture,
&fb->config, &fb->config,
flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH, flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH,
@ -841,8 +853,8 @@ _cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
try_creating_fbo (ctx, try_creating_fbo (ctx,
offscreen->texture, offscreen->texture,
offscreen->texture_level, offscreen->texture_level,
offscreen->texture_level_width, level_width,
offscreen->texture_level_height, level_height,
offscreen->depth_texture, offscreen->depth_texture,
&fb->config, &fb->config,
flags = 0, flags = 0,