st/mesa: add support for layered framebuffers and consolidate code

This is a subset of geometry shaders. It's all about setting first_layer and
last_layer correctly.

Also some code between st_render_texture and update_framebuffer_state is
consolidated. It doesn't use rtt_level and derives the level from dimensions
instead as the code in st_atom_framebuffer.c did.
This commit is contained in:
Marek Olšák 2013-11-21 15:31:32 +01:00
parent 0b3b901cff
commit d8d67d2e1f
6 changed files with 99 additions and 93 deletions

View file

@ -43,56 +43,6 @@
#include "util/u_format.h"
/**
* When doing GL render to texture, we have to be sure that finalize_texture()
* didn't yank out the pipe_resource that we earlier created a surface for.
* Check for that here and create a new surface if needed.
*/
static void
update_renderbuffer_surface(struct st_context *st,
struct st_renderbuffer *strb)
{
struct pipe_context *pipe = st->pipe;
struct pipe_resource *resource = strb->rtt ? strb->rtt->pt : strb->texture;
int rtt_width = strb->Base.Width;
int rtt_height = strb->Base.Height;
enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format);
if (!strb->surface ||
strb->surface->texture->nr_samples != strb->Base.NumSamples ||
strb->surface->format != format ||
strb->surface->texture != resource ||
strb->surface->width != rtt_width ||
strb->surface->height != rtt_height) {
GLuint level;
/* find matching mipmap level size */
for (level = 0; level <= resource->last_level; level++) {
if (u_minify(resource->width0, level) == rtt_width &&
u_minify(resource->height0, level) == rtt_height) {
struct pipe_surface surf_tmpl;
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = format;
surf_tmpl.u.tex.level = level;
surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
pipe_surface_reference(&strb->surface, NULL);
strb->surface = pipe->create_surface(pipe,
resource,
&surf_tmpl);
#if 0
printf("-- alloc new surface %d x %d into tex %p\n",
strb->surface->width, strb->surface->height,
texture);
#endif
break;
}
}
}
}
/**
* Update framebuffer state (color, depth, stencil, etc. buffers)
*/
@ -121,10 +71,10 @@ update_framebuffer_state( struct st_context *st )
if (strb) {
/*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/
if (strb->rtt ||
if (strb->is_rtt ||
(strb->texture && util_format_is_srgb(strb->texture->format))) {
/* rendering to a GL texture, may have to update surface */
update_renderbuffer_surface(st, strb);
st_update_renderbuffer_surface(st, strb);
}
if (strb->surface) {
@ -144,9 +94,9 @@ update_framebuffer_state( struct st_context *st )
*/
strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
if (strb) {
if (strb->rtt) {
if (strb->is_rtt) {
/* rendering to a GL texture, may have to update surface */
update_renderbuffer_surface(st, strb);
st_update_renderbuffer_surface(st, strb);
}
pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
}

View file

@ -878,7 +878,8 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
}
stmap = pipe_transfer_map(pipe, strb->texture,
strb->rtt_level, strb->rtt_face + strb->rtt_slice,
strb->surface->u.tex.level,
strb->surface->u.tex.first_layer,
usage, x, y,
width, height, &pt);
@ -1263,8 +1264,8 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
/* map the stencil buffer */
drawMap = pipe_transfer_map(pipe,
rbDraw->texture,
rbDraw->rtt_level,
rbDraw->rtt_face + rbDraw->rtt_slice,
rbDraw->surface->u.tex.level,
rbDraw->surface->u.tex.first_layer,
usage, dstx, dsty,
width, height, &ptDraw);
@ -1422,20 +1423,20 @@ blit_copy_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
memset(&blit, 0, sizeof(blit));
blit.src.resource = rbRead->texture;
blit.src.level = rbRead->rtt_level;
blit.src.level = rbRead->surface->u.tex.level;
blit.src.format = rbRead->texture->format;
blit.src.box.x = readX;
blit.src.box.y = readY;
blit.src.box.z = rbRead->rtt_face + rbRead->rtt_slice;
blit.src.box.z = rbRead->surface->u.tex.first_layer;
blit.src.box.width = readW;
blit.src.box.height = readH;
blit.src.box.depth = 1;
blit.dst.resource = rbDraw->texture;
blit.dst.level = rbDraw->rtt_level;
blit.dst.level = rbDraw->surface->u.tex.level;
blit.dst.format = rbDraw->texture->format;
blit.dst.box.x = drawX;
blit.dst.box.y = drawY;
blit.dst.box.z = rbDraw->rtt_face + rbDraw->rtt_slice;
blit.dst.box.z = rbDraw->surface->u.tex.first_layer;
blit.dst.box.width = drawW;
blit.dst.box.height = drawH;
blit.dst.box.depth = 1;
@ -1633,11 +1634,11 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
memset(&blit, 0, sizeof(blit));
blit.src.resource = rbRead->texture;
blit.src.level = rbRead->rtt_level;
blit.src.level = rbRead->surface->u.tex.level;
blit.src.format = rbRead->texture->format;
blit.src.box.x = readX;
blit.src.box.y = readY;
blit.src.box.z = rbRead->rtt_face + rbRead->rtt_slice;
blit.src.box.z = rbRead->surface->u.tex.first_layer;
blit.src.box.width = readW;
blit.src.box.height = readH;
blit.src.box.depth = 1;

View file

@ -388,6 +388,72 @@ st_bind_framebuffer(struct gl_context *ctx, GLenum target,
}
/**
* Create or update the pipe_surface of a FBO renderbuffer.
* This is usually called after st_finalize_texture.
*/
void
st_update_renderbuffer_surface(struct st_context *st,
struct st_renderbuffer *strb)
{
struct pipe_context *pipe = st->pipe;
struct pipe_resource *resource = strb->texture;
int rtt_width = strb->Base.Width;
int rtt_height = strb->Base.Height;
int rtt_depth = strb->Base.Depth;
enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format :
util_format_linear(resource->format);
unsigned first_layer, last_layer, level;
if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
rtt_depth = rtt_height;
rtt_height = 1;
}
/* find matching mipmap level size */
for (level = 0; level <= resource->last_level; level++) {
if (u_minify(resource->width0, level) == rtt_width &&
u_minify(resource->height0, level) == rtt_height &&
(resource->target != PIPE_TEXTURE_3D ||
u_minify(resource->depth0, level) == rtt_depth)) {
break;
}
}
assert(level <= resource->last_level);
/* determine the layer bounds */
if (strb->rtt_layered) {
first_layer = 0;
last_layer = util_max_layer(strb->texture, level);
}
else {
first_layer =
last_layer = strb->rtt_face + strb->rtt_slice;
}
if (!strb->surface ||
strb->surface->texture->nr_samples != strb->Base.NumSamples ||
strb->surface->format != format ||
strb->surface->texture != resource ||
strb->surface->width != rtt_width ||
strb->surface->height != rtt_height ||
strb->surface->u.tex.level != level ||
strb->surface->u.tex.first_layer != first_layer ||
strb->surface->u.tex.last_layer != last_layer) {
/* create a new pipe_surface */
struct pipe_surface surf_tmpl;
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = format;
surf_tmpl.u.tex.level = level;
surf_tmpl.u.tex.first_layer = first_layer;
surf_tmpl.u.tex.last_layer = last_layer;
pipe_surface_reference(&strb->surface, NULL);
strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl);
}
}
/**
* Called by ctx->Driver.RenderTexture
*/
@ -401,8 +467,6 @@ st_render_texture(struct gl_context *ctx,
struct gl_renderbuffer *rb = att->Renderbuffer;
struct st_renderbuffer *strb = st_renderbuffer(rb);
struct pipe_resource *pt;
struct st_texture_object *stObj;
struct pipe_surface surf_tmpl;
if (!st_finalize_texture(ctx, pipe, att->Texture))
return;
@ -410,31 +474,16 @@ st_render_texture(struct gl_context *ctx,
pt = st_get_texobj_resource(att->Texture);
assert(pt);
/* get the texture for the texture object */
stObj = st_texture_object(att->Texture);
/* point renderbuffer at texobject */
strb->rtt = stObj;
strb->rtt_level = att->TextureLevel;
strb->is_rtt = TRUE;
strb->rtt_face = att->CubeMapFace;
strb->rtt_slice = att->Zoffset;
pipe_resource_reference( &strb->texture, pt );
strb->rtt_layered = att->Layered;
pipe_resource_reference(&strb->texture, pt);
pipe_surface_release(pipe, &strb->surface);
assert(strb->rtt_level <= strb->texture->last_level);
/* new surface for rendering into the texture */
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = ctx->Color.sRGBEnabled
? strb->texture->format : util_format_linear(strb->texture->format);
surf_tmpl.u.tex.level = strb->rtt_level;
surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
strb->surface = pipe->create_surface(pipe,
strb->texture,
&surf_tmpl);
st_update_renderbuffer_surface(st, strb);
strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
@ -464,7 +513,7 @@ st_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb)
if (!strb)
return;
strb->rtt = NULL;
strb->is_rtt = FALSE;
/* restore previous framebuffer state */
st_invalidate_state(ctx, _NEW_BUFFERS);
@ -706,8 +755,8 @@ st_MapRenderbuffer(struct gl_context *ctx,
map = pipe_transfer_map(pipe,
strb->texture,
strb->rtt_level,
strb->rtt_face + strb->rtt_slice,
strb->surface->u.tex.level,
strb->surface->u.tex.first_layer,
usage, x, y2, w, h, &strb->transfer);
if (map) {
if (invert) {

View file

@ -58,8 +58,10 @@ struct st_renderbuffer
boolean software;
void *data;
struct st_texture_object *rtt; /**< GL render to texture's texture */
unsigned rtt_level, rtt_face, rtt_slice;
/* Inputs from Driver.RenderTexture, don't use directly. */
boolean is_rtt; /**< whether Driver.RenderTexture was called */
unsigned rtt_face, rtt_slice;
boolean rtt_layered; /**< whether glFramebufferTexture was called */
};
@ -73,6 +75,10 @@ st_renderbuffer(struct gl_renderbuffer *rb)
extern struct gl_renderbuffer *
st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw);
extern void
st_update_renderbuffer_surface(struct st_context *st,
struct st_renderbuffer *strb);
extern void
st_init_fbo_functions(struct dd_function_table *functions);

View file

@ -166,7 +166,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y,
}
blit.src.resource = src;
blit.src.level = strb->rtt_level;
blit.src.level = strb->surface->u.tex.level;
blit.src.format = src_format;
blit.dst.resource = dst;
blit.dst.level = 0;
@ -175,7 +175,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y,
blit.dst.box.x = 0;
blit.src.box.y = y;
blit.dst.box.y = 0;
blit.src.box.z = strb->rtt_face + strb->rtt_slice;
blit.src.box.z = strb->surface->u.tex.first_layer;
blit.dst.box.z = 0;
blit.src.box.width = blit.dst.box.width = width;
blit.src.box.height = blit.dst.box.height = height;

View file

@ -1156,8 +1156,8 @@ fallback_copy_texsubimage(struct gl_context *ctx,
map = pipe_transfer_map(pipe,
strb->texture,
strb->rtt_level,
strb->rtt_face + strb->rtt_slice,
strb->surface->u.tex.level,
strb->surface->u.tex.first_layer,
PIPE_TRANSFER_READ,
srcX, srcY,
width, height, &src_trans);