diff options
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r-- | src/mesa/state_tracker/st_atom.c | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom.h | 1 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_framebuffer.c | 65 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_pixeltransfer.c | 12 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_shader.c | 28 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_texture.c | 80 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_accum.c | 85 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_bitmap.c | 36 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawpixels.c | 107 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_fbo.c | 189 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_fbo.h | 6 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_feedback.c | 7 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_readpixels.c | 41 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_texture.c | 108 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.h | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_gen_mipmap.c | 6 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_texture.c | 61 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_texture.h | 14 |
18 files changed, 582 insertions, 270 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 18063adc79..ecfd117918 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -45,10 +45,10 @@ */ static const struct st_tracked_state *atoms[] = { - &st_update_framebuffer, &st_update_depth_stencil_alpha, &st_update_clip, + &st_finalize_textures, &st_update_shader, &st_update_rasterizer, @@ -58,6 +58,7 @@ static const struct st_tracked_state *atoms[] = &st_update_blend, &st_update_sampler, &st_update_texture, + &st_update_framebuffer, &st_update_vs_constants, &st_update_fs_constants, &st_update_pixel_transfer diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h index c6c6eba812..c7cffd85c8 100644 --- a/src/mesa/state_tracker/st_atom.h +++ b/src/mesa/state_tracker/st_atom.h @@ -55,6 +55,7 @@ extern const struct st_tracked_state st_update_scissor; extern const struct st_tracked_state st_update_blend; extern const struct st_tracked_state st_update_sampler; extern const struct st_tracked_state st_update_texture; +extern const struct st_tracked_state st_finalize_textures; extern const struct st_tracked_state st_update_fs_constants; extern const struct st_tracked_state st_update_vs_constants; extern const struct st_tracked_state st_update_pixel_transfer; diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index 0a6974d8a7..d46c3ee16c 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -34,13 +34,60 @@ #include "st_context.h" #include "st_atom.h" #include "st_cb_fbo.h" +#include "st_texture.h" #include "pipe/p_context.h" +#include "pipe/p_inlines.h" #include "cso_cache/cso_context.h" + +/** + * When doing GL render to texture, we have to be sure that finalize_texture() + * didn't yank out the pipe_texture 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_screen *screen = st->pipe->screen; + struct pipe_texture *texture = strb->rtt->pt; + int rtt_width = strb->Base.Width; + int rtt_height = strb->Base.Height; + + if (!strb->surface || + strb->surface->texture != texture || + strb->surface->width != rtt_width || + strb->surface->height != rtt_height) { + int level; + /* find matching mipmap level size */ + for (level = 0; level <= texture->last_level; level++) { + if (texture->width[level] == rtt_width && + texture->height[level] == rtt_height) { + + pipe_surface_reference(&strb->surface, NULL); + + strb->surface = screen->get_tex_surface(screen, + texture, + strb->rtt_face, + level, + strb->rtt_slice, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); +#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) - * XXX someday: separate draw/read buffers. */ static void update_framebuffer_state( struct st_context *st ) @@ -55,6 +102,8 @@ update_framebuffer_state( struct st_context *st ) framebuffer->width = fb->Width; framebuffer->height = fb->Height; + /*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/ + /* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state * to determine which surfaces to draw to */ @@ -62,6 +111,13 @@ update_framebuffer_state( struct st_context *st ) for (j = 0; j < MAX_DRAW_BUFFERS; j++) { for (i = 0; i < fb->_NumColorDrawBuffers[j]; i++) { strb = st_renderbuffer(fb->_ColorDrawBuffers[j][i]); + + /*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/ + if (strb->rtt) { + /* rendering to a GL texture, may have to update surface */ + update_renderbuffer_surface(st, strb); + } + assert(strb->surface); framebuffer->cbufs[framebuffer->num_cbufs] = strb->surface; framebuffer->num_cbufs++; @@ -71,6 +127,11 @@ update_framebuffer_state( struct st_context *st ) strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); if (strb) { strb = st_renderbuffer(strb->Base.Wrapped); + if (strb->rtt) { + /* rendering to a GL texture, may have to update surface */ + update_renderbuffer_surface(st, strb); + } + assert(strb->surface); framebuffer->zsbuf = strb->surface; } @@ -99,7 +160,7 @@ const struct st_tracked_state st_update_framebuffer = { "st_update_framebuffer", /* name */ { /* dirty */ _NEW_BUFFERS, /* mesa */ - 0, /* st */ + ST_NEW_FRAMEBUFFER, /* st */ }, update_framebuffer_state /* update */ }; diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index 999c148449..e500ac8684 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -126,7 +126,8 @@ create_color_map_texture(GLcontext *ctx) /* create texture for color map/table */ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, - texSize, texSize, 1, 0); + texSize, texSize, 1, 0, + PIPE_TEXTURE_USAGE_SAMPLER); return pt; } @@ -148,8 +149,10 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) uint *dest; uint i, j; - surface = screen->get_tex_surface(screen, pt, 0, 0, 0); - dest = (uint *) pipe_surface_map(surface); + surface = screen->get_tex_surface(screen, pt, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + dest = (uint *) screen->surface_map(screen, surface, + PIPE_BUFFER_USAGE_CPU_WRITE); /* Pack four 1D maps into a 2D texture: * R map is placed horizontally, indexed by S, in channel 0 @@ -168,9 +171,8 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) } } - pipe_surface_unmap(surface); + screen->surface_unmap(screen, surface); pipe_surface_reference(&surface, NULL); - pipe->texture_update(pipe, pt, 0, 0x1); } diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 7745591afb..a62ea8161c 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -44,6 +44,8 @@ #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" +#include "util/u_simple_shaders.h" + #include "cso_cache/cso_context.h" #include "st_context.h" @@ -252,6 +254,22 @@ st_free_translated_vertex_programs(struct st_context *st, } +static void * +get_passthrough_fs(struct st_context *st) +{ + struct pipe_shader_state shader; + + if (!st->passthrough_fs) { + st->passthrough_fs = + util_make_fragment_passthrough_shader(st->pipe, &shader); +#if 0 /* We actually need to keep the tokens around at this time */ + free((void *) shader.tokens); +#endif + } + + return st->passthrough_fs; +} + static void update_linkage( struct st_context *st ) @@ -277,7 +295,15 @@ update_linkage( struct st_context *st ) st_reference_fragprog(st, &st->fp, stfp); cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader); - cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); + + if (st->missing_textures) { + /* use a pass-through frag shader that uses no textures */ + void *fs = get_passthrough_fs(st); + cso_set_fragment_shader_handle(st->cso_context, fs); + } + else { + cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); + } st->vertex_result_to_slot = xvp->output_to_slot; } diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 767654f3d0..1ec671ed48 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -39,34 +39,13 @@ #include "pipe/p_context.h" #include "pipe/p_inlines.h" #include "cso_cache/cso_context.h" -#include "util/u_simple_shaders.h" -static void * -get_passthrough_fs(struct st_context *st) -{ - struct pipe_shader_state shader; - - if (!st->passthrough_fs) { - st->passthrough_fs = - util_make_fragment_passthrough_shader(st->pipe, &shader); - free((void *) shader.tokens); - } - - return st->passthrough_fs; -} - - -/** - * XXX This needs some work yet.... - * Need to "upload" texture images at appropriate times. - */ static void update_textures(struct st_context *st) { struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; GLuint su; - GLboolean missing_textures = GL_FALSE; st->state.num_textures = 0; @@ -85,13 +64,11 @@ update_textures(struct st_context *st) retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush); if (!retval) { /* out of mem */ - missing_textures = GL_TRUE; + /* missing texture */ continue; } st->state.num_textures = su + 1; - - stObj->teximage_realloc = TRUE; } pt = st_get_stobj_texture(stObj); @@ -103,12 +80,6 @@ update_textures(struct st_context *st) cso_set_sampler_textures(st->cso_context, st->state.num_textures, st->state.sampler_texture); - - if (missing_textures) { - /* use a pass-through frag shader that uses no textures */ - void *fs = get_passthrough_fs(st); - cso_set_fragment_shader_handle(st->cso_context, fs); - } } @@ -120,3 +91,52 @@ const struct st_tracked_state st_update_texture = { }, update_textures /* update */ }; + + + + +static void +finalize_textures(struct st_context *st) +{ + struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; + const GLboolean prev_missing_textures = st->missing_textures; + GLuint su; + + st->missing_textures = GL_FALSE; + + for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) { + if (fprog->Base.SamplersUsed & (1 << su)) { + const GLuint texUnit = fprog->Base.SamplerUnits[su]; + struct gl_texture_object *texObj + = st->ctx->Texture.Unit[texUnit]._Current; + struct st_texture_object *stObj = st_texture_object(texObj); + + if (texObj) { + GLboolean flush, retval; + + retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush); + if (!retval) { + /* out of mem */ + st->missing_textures = GL_TRUE; + continue; + } + + stObj->teximage_realloc = TRUE; + } + } + } + + if (prev_missing_textures != st->missing_textures) + st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; +} + + + +const struct st_tracked_state st_finalize_textures = { + "st_finalize_textures", /* name */ + { /* dirty */ + _NEW_TEXTURE, /* mesa */ + 0, /* st */ + }, + finalize_textures /* update */ +}; diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index 1636bed91a..8098d75e18 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -105,14 +105,18 @@ void st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) { struct st_renderbuffer *acc_strb = st_renderbuffer(rb); - struct pipe_surface *acc_ps = acc_strb->surface; + struct pipe_surface *acc_ps; + struct pipe_screen *screen = ctx->st->pipe->screen; const GLint xpos = ctx->DrawBuffer->_Xmin; const GLint ypos = ctx->DrawBuffer->_Ymin; const GLint width = ctx->DrawBuffer->_Xmax - xpos; const GLint height = ctx->DrawBuffer->_Ymax - ypos; GLvoid *map; - map = pipe_surface_map(acc_ps); + acc_ps = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + map = screen->surface_map(screen, acc_ps, + PIPE_BUFFER_USAGE_CPU_WRITE); /* note acc_strb->format might not equal acc_ps->format */ switch (acc_strb->format) { @@ -140,7 +144,8 @@ st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()"); } - pipe_surface_unmap(acc_ps); + screen->surface_unmap(screen, acc_ps); + pipe_surface_reference(&acc_ps, NULL); } @@ -150,10 +155,12 @@ accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias, GLint xpos, GLint ypos, GLint width, GLint height, struct st_renderbuffer *acc_strb) { + struct pipe_screen *screen = ctx->st->pipe->screen; struct pipe_surface *acc_ps = acc_strb->surface; GLvoid *map; - map = pipe_surface_map(acc_ps); + map = screen->surface_map(screen, acc_ps, + PIPE_BUFFER_USAGE_CPU_WRITE); /* note acc_strb->format might not equal acc_ps->format */ switch (acc_strb->format) { @@ -174,77 +181,107 @@ accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias, _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - pipe_surface_unmap(acc_ps); + screen->surface_unmap(screen, acc_ps); } static void accum_accum(struct pipe_context *pipe, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, - struct pipe_surface *acc_ps, - struct pipe_surface *color_ps) + struct st_renderbuffer *acc_strb, + struct st_renderbuffer *color_strb) { + struct pipe_screen *screen = pipe->screen; + struct pipe_surface *acc_surf, *color_surf; GLfloat *colorBuf, *accBuf; GLint i; + acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0, + (PIPE_BUFFER_USAGE_CPU_WRITE | + PIPE_BUFFER_USAGE_CPU_READ)); + + color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_READ); + colorBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); accBuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, colorBuf); - acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf); + pipe_get_tile_rgba(pipe, color_surf, xpos, ypos, width, height, colorBuf); + acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf); for (i = 0; i < 4 * width * height; i++) { accBuf[i] = accBuf[i] + colorBuf[i] * value; } - acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, accBuf); + acc_put_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, accBuf); free(colorBuf); free(accBuf); + pipe_surface_reference(&acc_surf, NULL); + pipe_surface_reference(&color_surf, NULL); } static void accum_load(struct pipe_context *pipe, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, - struct pipe_surface *acc_ps, - struct pipe_surface *color_ps) + struct st_renderbuffer *acc_strb, + struct st_renderbuffer *color_strb) { + struct pipe_screen *screen = pipe->screen; + struct pipe_surface *acc_surf, *color_surf; GLfloat *buf; GLint i; + acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + + color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_READ); + buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, buf); + pipe_get_tile_rgba(pipe, color_surf, xpos, ypos, width, height, buf); for (i = 0; i < 4 * width * height; i++) { buf[i] = buf[i] * value; } - acc_put_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, buf); + acc_put_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, buf); free(buf); + pipe_surface_reference(&acc_surf, NULL); + pipe_surface_reference(&color_surf, NULL); } static void accum_return(GLcontext *ctx, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, - struct pipe_surface *acc_ps, - struct pipe_surface *color_ps) + struct st_renderbuffer *acc_strb, + struct st_renderbuffer *color_strb) { struct pipe_context *pipe = ctx->st->pipe; + struct pipe_screen *screen = pipe->screen; const GLubyte *colormask = ctx->Color.ColorMask; + struct pipe_surface *acc_surf, *color_surf; GLfloat *abuf, *cbuf = NULL; GLint i, ch; abuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - acc_get_tile_rgba(pipe, acc_ps, xpos, ypos, width, height, abuf); + acc_surf = screen->get_tex_surface(screen, acc_strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_READ); + + color_surf = screen->get_tex_surface(screen, color_strb->texture, 0, 0, 0, + (PIPE_BUFFER_USAGE_CPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE)); + + acc_get_tile_rgba(pipe, acc_surf, xpos, ypos, width, height, abuf); if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) { cbuf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(pipe, color_ps, xpos, ypos, width, height, cbuf); + pipe_get_tile_rgba(pipe, color_surf, xpos, ypos, width, height, cbuf); } for (i = 0; i < width * height; i++) { @@ -259,11 +296,13 @@ accum_return(GLcontext *ctx, GLfloat value, } } - pipe_put_tile_rgba(pipe, color_ps, xpos, ypos, width, height, abuf); + pipe_put_tile_rgba(pipe, color_surf, xpos, ypos, width, height, abuf); free(abuf); if (cbuf) free(cbuf); + pipe_surface_reference(&acc_surf, NULL); + pipe_surface_reference(&color_surf, NULL); } @@ -276,8 +315,6 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value) = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); struct st_renderbuffer *color_strb = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); - struct pipe_surface *acc_ps = acc_strb->surface; - struct pipe_surface *color_ps = color_strb->surface; const GLint xpos = ctx->DrawBuffer->_Xmin; const GLint ypos = ctx->DrawBuffer->_Ymin; @@ -300,14 +337,14 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value) break; case GL_ACCUM: if (value != 0.0F) { - accum_accum(pipe, value, xpos, ypos, width, height, acc_ps, color_ps); + accum_accum(pipe, value, xpos, ypos, width, height, acc_strb, color_strb); } break; case GL_LOAD: - accum_load(pipe, value, xpos, ypos, width, height, acc_ps, color_ps); + accum_load(pipe, value, xpos, ypos, width, height, acc_strb, color_strb); break; case GL_RETURN: - accum_return(ctx, value, xpos, ypos, width, height, acc_ps, color_ps); + accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb); break; default: assert(0); diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index ce8fefe703..d39fce1bb7 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -321,16 +321,18 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height, * Create texture to hold bitmap pattern. */ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, ctx->st->bitmap.tex_format, - 0, width, height, 1, 0); + 0, width, height, 1, 0, + PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) { _mesa_unmap_bitmap_pbo(ctx, unpack); return NULL; } - surface = screen->get_tex_surface(screen, pt, 0, 0, 0); + surface = screen->get_tex_surface(screen, pt, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); /* map texture surface */ - dest = pipe_surface_map(surface); + dest = screen->surface_map(screen, surface, PIPE_BUFFER_USAGE_CPU_WRITE); /* Put image into texture surface */ memset(dest, 0xff, height * surface->pitch); @@ -340,9 +342,8 @@ make_bitmap_texture(GLcontext *ctx, GLsizei width, GLsizei height, _mesa_unmap_bitmap_pbo(ctx, unpack); /* Release surface */ - pipe_surface_unmap(surface); + screen->surface_unmap(screen, surface); pipe_surface_reference(&surface, NULL); - pipe->texture_update(pipe, pt, 0, 0x1); return pt; } @@ -539,13 +540,16 @@ reset_cache(struct st_context *st) cache->texture = st_texture_create(st, PIPE_TEXTURE_2D, st->bitmap.tex_format, 0, BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT, - 1, 0); + 1, 0, + PIPE_TEXTURE_USAGE_SAMPLER); /* Map the texture surface. * Subsequent glBitmap calls will write into the texture image. */ - cache->surf = screen->get_tex_surface(screen, cache->texture, 0, 0, 0); - cache->buffer = pipe_surface_map(cache->surf); + cache->surf = screen->get_tex_surface(screen, cache->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + cache->buffer = screen->surface_map(screen, cache->surf, + PIPE_BUFFER_USAGE_CPU_WRITE); /* init image to all 0xff */ memset(cache->buffer, 0xff, BITMAP_CACHE_WIDTH * BITMAP_CACHE_HEIGHT); @@ -562,6 +566,7 @@ st_flush_bitmap_cache(struct st_context *st) if (st->ctx->DrawBuffer) { struct bitmap_cache *cache = st->bitmap.cache; struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; assert(cache->xmin <= cache->xmax); /* @@ -574,11 +579,8 @@ st_flush_bitmap_cache(struct st_context *st) /* The texture surface has been mapped until now. * So unmap and release the texture surface before drawing. */ - pipe_surface_unmap(cache->surf); - pipe_surface_reference(&cache->surf, NULL); - - /* XXX is this needed? */ - pipe->texture_update(pipe, cache->texture, 0, 0x1); + screen->surface_unmap(screen, cache->surf); + screen->tex_surface_release(screen, &cache->surf); draw_bitmap_quad(st->ctx, cache->xpos, @@ -662,6 +664,9 @@ st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, struct st_context *st = ctx->st; struct pipe_texture *pt; + if (width == 0 || height == 0) + return; + st_validate_state(st); if (!st->bitmap.vs) { @@ -742,6 +747,11 @@ void st_destroy_bitmap(struct st_context *st) { struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + struct bitmap_cache *cache = st->bitmap.cache; + + screen->surface_unmap(screen, cache->surf); + screen->tex_surface_release(screen, &cache->surf); #if 0 if (st->bitmap.combined_prog) { diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 56b949cf96..4fede7a900 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -346,7 +346,8 @@ make_texture(struct st_context *st, return NULL; pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, - 1, 0); + 1, 0, + PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) { _mesa_unmap_drawpix_pbo(ctx, unpack); return NULL; @@ -362,10 +363,12 @@ make_texture(struct st_context *st, /* we'll do pixel transfer in a fragment shader */ ctx->_ImageTransferState = 0x0; - surface = screen->get_tex_surface(screen, pt, 0, 0, 0); + surface = screen->get_tex_surface(screen, pt, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); /* map texture surface */ - dest = pipe_surface_map(surface); + dest = screen->surface_map(screen, surface, + PIPE_BUFFER_USAGE_CPU_WRITE); /* Put image into texture surface. * Note that the image is actually going to be upside down in @@ -384,9 +387,8 @@ make_texture(struct st_context *st, unpack); /* unmap */ - pipe_surface_unmap(surface); + screen->surface_unmap(screen, surface); pipe_surface_reference(&surface, NULL); - pipe->texture_update(pipe, pt, 0, 0x1); assert(success); @@ -482,7 +484,7 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, ubyte *map; /* allocate/load buffer object with vertex data */ - buf = pipe_buffer_create(pipe,32, PIPE_BUFFER_USAGE_VERTEX, + buf = pipe_buffer_create(pipe, 32, PIPE_BUFFER_USAGE_VERTEX, sizeof(verts)); map = pipe_buffer_map(pipe, buf, PIPE_BUFFER_USAGE_CPU_WRITE); memcpy(map, verts, sizeof(verts)); @@ -492,8 +494,7 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, PIPE_PRIM_QUADS, 4, /* verts */ 3); /* attribs/vert */ - - pipe_buffer_destroy(pipe, buf); + pipe_buffer_reference(pipe->winsys, &buf, NULL); } } @@ -600,8 +601,10 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, x1 = x + width * ctx->Pixel.ZoomX; y0 = y; y1 = y + height * ctx->Pixel.ZoomY; + //if(!color) draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex); - + //else + //printf("skip draw quad\n"); /* restore state */ cso_restore_rasterizer(cso); cso_restore_viewport(cso); @@ -731,15 +734,23 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, { struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; - struct pipe_surface *ps = st->state.framebuffer.zsbuf; + struct pipe_screen *screen = pipe->screen; + struct st_renderbuffer *strb; + struct pipe_surface *ps; const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; GLint skipPixels; ubyte *stmap; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + strb = st_renderbuffer(ctx->DrawBuffer-> + Attachment[BUFFER_STENCIL].Renderbuffer); + ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + /* map the stencil buffer */ - stmap = pipe_surface_map(ps); + stmap = screen->surface_map(screen, ps, + PIPE_BUFFER_USAGE_CPU_WRITE); /* if width > MAX_WIDTH, have to process image in chunks */ skipPixels = 0; @@ -796,7 +807,8 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, } /* unmap the stencil buffer */ - pipe_surface_unmap(ps); + screen->surface_unmap(screen, ps); + pipe_surface_reference(&ps, NULL); } @@ -869,7 +881,8 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GLint dstx, GLint dsty) { struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); - struct pipe_surface *psDraw = rbDraw->surface; + struct pipe_screen *screen = ctx->st->pipe->screen; + struct pipe_surface *psDraw; ubyte *drawMap; ubyte *buffer; int i; @@ -884,8 +897,11 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, st_read_stencil_pixels(ctx, srcx, srcy, width, height, GL_UNSIGNED_BYTE, &ctx->DefaultPacking, buffer); + psDraw = screen->get_tex_surface(screen, rbDraw->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + /* map the stencil buffer */ - drawMap = pipe_surface_map(psDraw); + drawMap = screen->surface_map(screen, psDraw, PIPE_BUFFER_USAGE_CPU_WRITE); /* draw */ /* XXX PixelZoom not handled yet */ @@ -925,7 +941,8 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, free(buffer); /* unmap the stencil buffer */ - pipe_surface_unmap(psDraw); + screen->surface_unmap(screen, psDraw); + pipe_surface_reference(&psDraw, NULL); } @@ -940,7 +957,6 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct st_renderbuffer *rbRead; struct st_vertex_program *stvp; struct st_fragment_program *stfp; - struct pipe_surface *psRead; struct pipe_surface *psTex; struct pipe_texture *pt; GLfloat *color; @@ -971,8 +987,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, stvp = st_make_passthrough_vertex_shader(ctx->st, GL_TRUE); } - psRead = rbRead->surface; - srcFormat = psRead->format; + srcFormat = rbRead->texture->format; if (screen->is_format_supported(screen, srcFormat, PIPE_TEXTURE)) { texFormat = srcFormat; @@ -984,54 +999,72 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */ } else { - /* todo */ - assert(0); + /* default color format */ + texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE); + assert(texFormat != PIPE_FORMAT_NONE); } } pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0, - width, height, 1, 0); + width, height, 1, 0, + PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) return; - psTex = screen->get_tex_surface(screen, pt, 0, 0, 0); - if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { srcy = ctx->DrawBuffer->Height - srcy - height; } if (srcFormat == texFormat) { /* copy source framebuffer surface into mipmap/texture */ + struct pipe_surface *psRead = screen->get_tex_surface(screen, + rbRead->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ); + psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE ); pipe->surface_copy(pipe, FALSE, psTex, /* dest */ 0, 0, /* destx/y */ psRead, srcx, srcy, width, height); + pipe_surface_reference(&psRead, NULL); } - else if (type == GL_COLOR) { - /* alternate path using get/put_tile() */ - GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); + else { + /* CPU-based fallback/conversion */ + struct pipe_surface *psRead = screen->get_tex_surface(screen, + rbRead->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_READ); - pipe_get_tile_rgba(pipe, psRead, srcx, srcy, width, height, buf); - pipe_put_tile_rgba(pipe, psTex, 0, 0, width, height, buf); + psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE ); - free(buf); - } - else { - /* GL_DEPTH */ - GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); - pipe_get_tile_z(pipe, psRead, srcx, srcy, width, height, buf); - pipe_put_tile_z(pipe, psTex, 0, 0, width, height, buf); - free(buf); + if (type == GL_COLOR) { + /* alternate path using get/put_tile() */ + GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); + + pipe_get_tile_rgba(pipe, psRead, srcx, srcy, width, height, buf); + pipe_put_tile_rgba(pipe, psTex, 0, 0, width, height, buf); + + free(buf); + } + else { + /* GL_DEPTH */ + GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint)); + pipe_get_tile_z(pipe, psRead, srcx, srcy, width, height, buf); + pipe_put_tile_z(pipe, psTex, 0, 0, width, height, buf); + free(buf); + } + pipe_surface_reference(&psRead, NULL); } + pipe_surface_reference(&psTex, NULL); + /* draw textured quad */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, pt, stvp, stfp, color, GL_TRUE); - pipe_surface_reference(&psTex, NULL); pipe_texture_reference(&pt, NULL); } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index fc8a5ea7f6..3560a040c8 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -77,7 +77,6 @@ init_renderbuffer_bits(struct st_renderbuffer *strb, return info.size; } - /** * gl_renderbuffer::AllocStorage() * This is called to allocate the original drawing surface, and @@ -90,80 +89,94 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, { struct pipe_context *pipe = ctx->st->pipe; struct st_renderbuffer *strb = st_renderbuffer(rb); - enum pipe_format pipeFormat; - GLbitfield flags = 0x0; /* XXX needed? */ - int ret; - - if (!strb->surface) { - /* first time surface creation */ - strb->surface = pipe->winsys->surface_alloc(pipe->winsys); - assert(strb->surface); - assert(strb->surface->refcount); - assert(strb->surface->winsys); - if (!strb->surface) - return GL_FALSE; + struct pipe_texture template; + unsigned surface_usage; + + /* Free the old surface (and texture if we hold the last + * reference): + */ + pipe_surface_reference( &strb->surface, NULL ); + + memset(&template, 0, sizeof(template)); + + if (strb->format != PIPE_FORMAT_NONE) { + template.format = strb->format; } - else if (strb->surface->buffer) { - /* release/discard the old surface buffer */ - pipe_reference_buffer(pipe, &strb->surface->buffer, NULL); + else { + template.format = st_choose_renderbuffer_format(pipe, internalFormat); } - /* Determine surface format here */ - if (strb->format != PIPE_FORMAT_NONE) { - assert(strb->format != 0); - /* we'll hit this for front/back color bufs */ - pipeFormat = strb->format; + strb->Base.Width = width; + strb->Base.Height = height; + init_renderbuffer_bits(strb, template.format); + + template.target = PIPE_TEXTURE_2D; + template.compressed = 0; + template.cpp = pf_get_size(template.format); + template.width[0] = width; + template.height[0] = height; + template.depth[0] = 1; + template.last_level = 0; + + if (pf_is_depth_stencil(template.format)) { + template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; } else { - pipeFormat = st_choose_renderbuffer_format(pipe, internalFormat); + template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET); } - init_renderbuffer_bits(strb, pipeFormat); - - ret = pipe->winsys->surface_alloc_storage(pipe->winsys, - strb->surface, - width, - height, - pipeFormat, - flags); - if (ret || !strb->surface->buffer) { - if (pipeFormat == DEFAULT_ACCUM_PIPE_FORMAT) { - /* Accum buffer. Try a different surface format. Since accum - * buffers are s/w only for now, the surface pixel format doesn't - * really matter, only that the buffer is large enough. - */ - int sz, mult; - enum pipe_format accum_format; - - /* allocate a buffer of (typically) double height to get 64bpp */ - accum_format = st_choose_renderbuffer_format(pipe, GL_RGBA); - sz = pf_get_size(accum_format); - mult = pf_get_size(DEFAULT_ACCUM_PIPE_FORMAT) / sz; - - ret = pipe->winsys->surface_alloc_storage(pipe->winsys, - strb->surface, - width, height * mult, - accum_format, flags); - if (ret) - return GL_FALSE; /* we've _really_ failed */ - - } - else { - return GL_FALSE; /* out of memory, try s/w buffer? */ - } + + /* Probably need dedicated flags for surface usage too: + */ + surface_usage = (PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); +#if 0 + PIPE_BUFFER_USAGE_CPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE); +#endif + + strb->texture = pipe->screen->texture_create( pipe->screen, + &template ); + + /* Special path for accum buffers. + * + * Try a different surface format. Since accum buffers are s/w + * only for now, the surface pixel format doesn't really matter, + * only that the buffer is large enough. + */ + if (!strb->texture && template.format == DEFAULT_ACCUM_PIPE_FORMAT) + { + /* Actually, just setting this usage value should be sufficient + * to tell the driver to go ahead and allocate the buffer, even + * if HW doesn't support the format. + */ + template.tex_usage = 0; + surface_usage = (PIPE_BUFFER_USAGE_CPU_READ | + PIPE_BUFFER_USAGE_CPU_WRITE); + + strb->texture = pipe->screen->texture_create( pipe->screen, + &template ); + } - ASSERT(strb->surface->buffer); - ASSERT(strb->surface->format); - ASSERT(strb->surface->cpp); - ASSERT(strb->surface->width == width); - /*ASSERT(strb->surface->height == height);*/ - ASSERT(strb->surface->pitch); + if (!strb->texture) + return FALSE; - strb->Base.Width = width; - strb->Base.Height = height; + strb->surface = pipe->screen->get_tex_surface( pipe->screen, + strb->texture, + 0, 0, 0, + surface_usage ); + + assert(strb->surface->buffer); + assert(strb->surface->format); + assert(strb->surface->cpp); + assert(strb->surface->width == width); + assert(strb->surface->height == height); + assert(strb->surface->pitch); - return GL_TRUE; + + return strb->surface != NULL; } @@ -175,10 +188,8 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb) { struct st_renderbuffer *strb = st_renderbuffer(rb); ASSERT(strb); - if (strb->surface) { - struct pipe_winsys *ws = strb->surface->winsys; - ws->surface_release(ws, &strb->surface); - } + pipe_surface_reference(&strb->surface, NULL); + pipe_texture_reference(&strb->texture, NULL); free(strb); } @@ -341,6 +352,10 @@ st_render_texture(GLcontext *ctx, struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_texture *pt; + struct st_texture_object *stObj; + const struct gl_texture_image *texImage = + att->Texture->Image[att->CubeMapFace][att->TextureLevel]; + assert(!att->Renderbuffer); @@ -357,21 +372,27 @@ st_render_texture(GLcontext *ctx, strb = st_renderbuffer(rb); /* 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->rtt_face = att->CubeMapFace; + strb->rtt_slice = att->Zoffset; + + rb->Width = texImage->Width2; + rb->Height = texImage->Height2; + /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/ + pt = st_get_texobj_texture(att->Texture); assert(pt); - assert(pt->width[att->TextureLevel]); + /*printf("***** pipe texture %d x %d\n", pt->width[0], pt->height[0]);*/ + + pipe_texture_reference( &strb->texture, pt ); - rb->Width = pt->width[att->TextureLevel]; - rb->Height = pt->height[att->TextureLevel]; + pipe_surface_reference(&strb->surface, NULL); - /* the renderbuffer's surface is inside the texture */ - strb->surface = screen->get_tex_surface(screen, pt, - att->CubeMapFace, - att->TextureLevel, - att->Zoffset); - assert(strb->surface); - assert(screen->is_format_supported(screen, strb->surface->format, PIPE_TEXTURE)); - assert(screen->is_format_supported(screen, strb->surface->format, PIPE_SURFACE)); + /* the new surface will be created during framebuffer validation */ init_renderbuffer_bits(strb, pt->format); @@ -396,22 +417,22 @@ static void st_finish_render_texture(GLcontext *ctx, struct gl_renderbuffer_attachment *att) { + struct pipe_screen *screen = ctx->st->pipe->screen; struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer); assert(strb); ctx->st->pipe->flush(ctx->st->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); - ctx->st->pipe->texture_update(ctx->st->pipe, - st_get_texobj_texture(att->Texture), - att->CubeMapFace, 1 << att->TextureLevel); + if (strb->surface) + screen->tex_surface_release( screen, &strb->surface ); + + strb->rtt = NULL; /* printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface); */ - pipe_surface_reference(&strb->surface, NULL); - _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); /* restore previous framebuffer state */ diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h index c1aa14f9b2..87b0734a0c 100644 --- a/src/mesa/state_tracker/st_cb_fbo.h +++ b/src/mesa/state_tracker/st_cb_fbo.h @@ -41,8 +41,12 @@ struct st_renderbuffer { struct gl_renderbuffer Base; - struct pipe_surface *surface; + struct pipe_texture *texture; + struct pipe_surface *surface; /* temporary view into texture */ enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */ + + struct st_texture_object *rtt; /**< GL render to texture's texture */ + int rtt_level, rtt_face, rtt_slice; }; diff --git a/src/mesa/state_tracker/st_cb_feedback.c b/src/mesa/state_tracker/st_cb_feedback.c index 1b50792bd1..19021411cf 100644 --- a/src/mesa/state_tracker/st_cb_feedback.c +++ b/src/mesa/state_tracker/st_cb_feedback.c @@ -173,6 +173,12 @@ feedback_reset_stipple_counter( struct draw_stage *stage ) } +static void +feedback_destroy( struct draw_stage *stage ) +{ + /* no-op */ +} + /** * Create GL feedback drawing stage. */ @@ -188,6 +194,7 @@ draw_glfeedback_stage(GLcontext *ctx, struct draw_context *draw) fs->stage.tri = feedback_tri; fs->stage.flush = feedback_flush; fs->stage.reset_stipple_counter = feedback_reset_stipple_counter; + fs->stage.destroy = feedback_destroy; fs->ctx = ctx; return &fs->stage; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 745755566e..08934af319 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -61,13 +61,18 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, GLvoid *pixels) { struct gl_framebuffer *fb = ctx->ReadBuffer; + struct pipe_screen *screen = ctx->st->pipe->screen; struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer); - struct pipe_surface *ps = strb->surface; + struct pipe_surface *ps; ubyte *stmap; GLint j; + /* Create a CPU-READ surface/view into the renderbuffer's texture */ + ps = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_READ); + /* map the stencil buffer */ - stmap = pipe_surface_map(ps); + stmap = screen->surface_map(screen, ps, PIPE_BUFFER_USAGE_CPU_READ); /* width should never be > MAX_WIDTH since we did clipping earlier */ ASSERT(width <= MAX_WIDTH); @@ -124,7 +129,8 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, /* unmap the stencil buffer */ - pipe_surface_unmap(ps); + screen->surface_unmap(screen, ps); + pipe_surface_reference(&ps, NULL); } @@ -168,12 +174,16 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLvoid *dest) { struct pipe_context *pipe = ctx->st->pipe; + struct pipe_screen *screen = pipe->screen; GLfloat temp[MAX_WIDTH][4]; const GLbitfield transferOps = ctx->_ImageTransferState; GLint i, yStep, dfStride; GLfloat *df; struct st_renderbuffer *strb; struct gl_pixelstore_attrib clippedPacking = *pack; + struct pipe_surface *surf; + + assert(ctx->ReadBuffer->Width > 0); /* XXX convolution not done yet */ assert((transferOps & IMAGE_CONVOLUTION_BIT) == 0); @@ -229,6 +239,10 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, yStep = 1; } + /* Create a CPU-READ surface/view into the renderbuffer's texture */ + surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_READ); + /* * Copy pixels from pipe_surface to user memory */ @@ -240,15 +254,14 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width, format, type); - if (strb->surface->format == PIPE_FORMAT_S8Z24_UNORM || - strb->surface->format == PIPE_FORMAT_X8Z24_UNORM) { + if (surf->format == PIPE_FORMAT_S8Z24_UNORM || + surf->format == PIPE_FORMAT_X8Z24_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH], j; GLfloat zfloat[MAX_WIDTH]; const double scale = 1.0 / ((1 << 24) - 1); - pipe_get_tile_raw(pipe, strb->surface, x, y, - width, 1, ztemp, 0); + pipe_get_tile_raw(pipe, surf, x, y, width, 1, ztemp, 0); y += yStep; for (j = 0; j < width; j++) { zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff)); @@ -262,18 +275,18 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, /* untested, but simple: */ assert(format == GL_DEPTH_STENCIL_EXT); for (i = 0; i < height; i++) { - pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, dst, 0); + pipe_get_tile_raw(pipe, surf, x, y, width, 1, dst, 0); y += yStep; dst += dstStride; } } } - else if (strb->surface->format == PIPE_FORMAT_Z16_UNORM) { + else if (surf->format == PIPE_FORMAT_Z16_UNORM) { for (i = 0; i < height; i++) { GLushort ztemp[MAX_WIDTH], j; GLfloat zfloat[MAX_WIDTH]; const double scale = 1.0 / 0xffff; - pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, ztemp, 0); + pipe_get_tile_raw(pipe, surf, x, y, width, 1, ztemp, 0); y += yStep; for (j = 0; j < width; j++) { zfloat[j] = (float) (scale * ztemp[j]); @@ -283,12 +296,12 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, dst += dstStride; } } - else if (strb->surface->format == PIPE_FORMAT_Z32_UNORM) { + else if (surf->format == PIPE_FORMAT_Z32_UNORM) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH], j; GLfloat zfloat[MAX_WIDTH]; const double scale = 1.0 / 0xffffffff; - pipe_get_tile_raw(pipe, strb->surface, x, y, width, 1, ztemp, 0); + pipe_get_tile_raw(pipe, surf, x, y, width, 1, ztemp, 0); y += yStep; for (j = 0; j < width; j++) { zfloat[j] = (float) (scale * ztemp[j]); @@ -302,7 +315,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, /* RGBA format */ /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { - pipe_get_tile_rgba(pipe, strb->surface, x, y, width, 1, df); + pipe_get_tile_rgba(pipe, surf, x, y, width, 1, df); y += yStep; df += dfStride; if (!dfStride) { @@ -314,6 +327,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, } } + pipe_surface_reference(&surf, NULL); + _mesa_unmap_readpix_pbo(ctx, &clippedPacking); } diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index cc17bebc6b..e15ccec89b 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -272,6 +272,7 @@ guess_and_alloc_texture(struct st_context *st, GLuint height = stImage->base.Height2; GLuint depth = stImage->base.Depth2; GLuint i, comp_byte = 0; + enum pipe_format fmt; DBG("%s\n", __FUNCTION__); @@ -306,6 +307,11 @@ guess_and_alloc_texture(struct st_context *st, depth <<= 1; } + if (width == 0 || height == 0 || depth == 0) { + /* no texture needed */ + return; + } + /* Guess a reasonable value for lastLevel. This is probably going * to be wrong fairly often and might mean that we have to look at * resizable buffers, or require that buffers implement lazy @@ -326,14 +332,19 @@ guess_and_alloc_texture(struct st_context *st, if (stImage->base.IsCompressed) comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat); + fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat); stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), - st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat), + fmt, lastLevel, width, height, depth, - comp_byte); + comp_byte, + ( (pf_is_depth_stencil(fmt) ? + PIPE_TEXTURE_USAGE_DEPTH_STENCIL : + PIPE_TEXTURE_USAGE_RENDER_TARGET) | + PIPE_TEXTURE_USAGE_SAMPLER )); DBG("%s - success\n", __FUNCTION__); } @@ -478,7 +489,6 @@ st_TexImage(GLcontext * ctx, struct gl_texture_image *texImage, GLsizei imageSize, int compressed) { - struct pipe_context *pipe = ctx->st->pipe; struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); GLint postConvWidth, postConvHeight; @@ -637,8 +647,10 @@ st_TexImage(GLcontext * ctx, return; if (stImage->pt) { - texImage->Data = st_texture_image_map(ctx->st, stImage, 0); - dstRowStride = stImage->surface->pitch * stImage->surface->cpp; + texImage->Data = st_texture_image_map(ctx->st, stImage, 0, + PIPE_BUFFER_USAGE_CPU_WRITE); + if (stImage->surface) + dstRowStride = stImage->surface->pitch * stImage->surface->cpp; } else { /* Allocate regular memory and store the image there temporarily. */ @@ -656,6 +668,11 @@ st_TexImage(GLcontext * ctx, texImage->Data = malloc(sizeInBytes); } + if (!texImage->Data) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); + return; + } + DBG("Upload image %dx%dx%d row_len %x pitch %x\n", width, height, depth, width * texelBytes, dstRowStride); @@ -686,8 +703,9 @@ st_TexImage(GLcontext * ctx, } if (stImage->pt && i < depth) { - st_texture_image_unmap(stImage); - texImage->Data = st_texture_image_map(ctx->st, stImage, i); + st_texture_image_unmap(ctx->st, stImage); + texImage->Data = st_texture_image_map(ctx->st, stImage, i, + PIPE_BUFFER_USAGE_CPU_WRITE); src += srcImageStride; } } @@ -696,13 +714,10 @@ st_TexImage(GLcontext * ctx, _mesa_unmap_teximage_pbo(ctx, unpack); if (stImage->pt) { - st_texture_image_unmap(stImage); + st_texture_image_unmap(ctx->st, stImage); texImage->Data = NULL; } - if (stObj->pt) - pipe->texture_update(pipe, stObj->pt, stImage->face, (1 << level)); - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { ctx->Driver.GenerateMipmap(ctx, target, texObj); } @@ -795,7 +810,8 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, /* Image is stored in hardware format in a buffer managed by the * kernel. Need to explicitly map and unmap it. */ - texImage->Data = st_texture_image_map(ctx->st, stImage, 0); + texImage->Data = st_texture_image_map(ctx->st, stImage, 0, + PIPE_BUFFER_USAGE_CPU_READ); texImage->RowStride = stImage->surface->pitch; } else { @@ -825,8 +841,9 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, } if (stImage->pt && i < depth) { - st_texture_image_unmap(stImage); - texImage->Data = st_texture_image_map(ctx->st, stImage, i); + st_texture_image_unmap(ctx->st, stImage); + texImage->Data = st_texture_image_map(ctx->st, stImage, i, + PIPE_BUFFER_USAGE_CPU_READ); dest += dstImageStride; } } @@ -835,7 +852,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, /* Unmap */ if (stImage->pt) { - st_texture_image_unmap(stImage); + st_texture_image_unmap(ctx->st, stImage); texImage->Data = NULL; } } @@ -876,8 +893,6 @@ st_TexSubimage(GLcontext * ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - struct pipe_context *pipe = ctx->st->pipe; - struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride; GLuint srcImageStride = _mesa_image_image_stride(packing, width, height, @@ -899,8 +914,10 @@ st_TexSubimage(GLcontext * ctx, * from uploading the buffer under us. */ if (stImage->pt) { - texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset); - dstRowStride = stImage->surface->pitch * stImage->surface->cpp; + texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset, + PIPE_BUFFER_USAGE_CPU_WRITE); + if (stImage->surface) + dstRowStride = stImage->surface->pitch * stImage->surface->cpp; } if (!texImage->Data) { @@ -924,8 +941,9 @@ st_TexSubimage(GLcontext * ctx, if (stImage->pt && i < depth) { /* map next slice of 3D texture */ - st_texture_image_unmap(stImage); - texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i); + st_texture_image_unmap(ctx->st, stImage); + texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i, + PIPE_BUFFER_USAGE_CPU_WRITE); src += srcImageStride; } } @@ -937,11 +955,9 @@ st_TexSubimage(GLcontext * ctx, _mesa_unmap_teximage_pbo(ctx, packing); if (stImage->pt) { - st_texture_image_unmap(stImage); + st_texture_image_unmap(ctx->st, stImage); texImage->Data = NULL; } - - pipe->texture_update(pipe, stObj->pt, stImage->face, (1 << level)); } @@ -1059,8 +1075,11 @@ fallback_copy_texsubimage(GLcontext *ctx, } src_surf = strb->surface; + src_surf = screen->get_tex_surface(screen, strb->texture, face, level, destZ, + PIPE_BUFFER_USAGE_CPU_READ); - dest_surf = screen->get_tex_surface(screen, pt, face, level, destZ); + dest_surf = screen->get_tex_surface(screen, pt, face, level, destZ, + PIPE_BUFFER_USAGE_CPU_WRITE); assert(width <= MAX_WIDTH); @@ -1094,6 +1113,9 @@ fallback_copy_texsubimage(GLcontext *ctx, pipe_put_tile_rgba(pipe, dest_surf, destX, destY, width, 1, data); } } + + screen->tex_surface_release(screen, &dest_surf); + screen->tex_surface_release(screen, &src_surf); } @@ -1121,13 +1143,11 @@ do_copy_texsubimage(GLcontext *ctx, struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texObj, target, level); struct st_texture_image *stImage = st_texture_image(texImage); - struct st_texture_object *stObj = st_texture_object(texObj); GLenum baseFormat = texImage->InternalFormat; struct gl_framebuffer *fb = ctx->ReadBuffer; struct st_renderbuffer *strb; struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_surface *dest_surface; uint dest_format, src_format; uint do_flip = FALSE; GLboolean use_fallback = GL_TRUE; @@ -1158,12 +1178,7 @@ do_copy_texsubimage(GLcontext *ctx, src_format = strb->surface->format; dest_format = stImage->pt->format; - dest_surface = screen->get_tex_surface(screen, stImage->pt, stImage->face, - stImage->level, destZ); - - if (ctx->_ImageTransferState == 0x0 && - strb->surface->buffer && - dest_surface->buffer) { + if (ctx->_ImageTransferState == 0x0) { /* do blit-style copy */ /* XXX may need to invert image depending on window @@ -1186,6 +1201,14 @@ do_copy_texsubimage(GLcontext *ctx, x, y + height, dstx, dsty, width, height, GL_COPY); /* ? */ #else + struct pipe_surface *dest_surface; + + dest_surface = screen->get_tex_surface(screen, stImage->pt, stImage->face, + stImage->level, destZ, + PIPE_BUFFER_USAGE_GPU_WRITE); + + assert(strb->surface->buffer); + assert(dest_surface->buffer); if (src_format == dest_format) { pipe->surface_copy(pipe, @@ -1213,6 +1236,8 @@ do_copy_texsubimage(GLcontext *ctx, 0.0, PIPE_TEX_MIPFILTER_NEAREST); use_fallback = GL_FALSE; } + + pipe_surface_reference(&dest_surface, NULL); #endif } @@ -1223,10 +1248,6 @@ do_copy_texsubimage(GLcontext *ctx, srcX, srcY, width, height); } - pipe_surface_reference(&dest_surface, NULL); - - pipe->texture_update(pipe, stObj->pt, stImage->face, (1 << level)); - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { ctx->Driver.GenerateMipmap(ctx, target, texObj); } @@ -1483,20 +1504,28 @@ st_finalize_texture(GLcontext *ctx, stObj->pt->cpp != cpp || stObj->pt->compressed != firstImage->base.IsCompressed) { pipe_texture_release(&stObj->pt); + ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER; } } /* May need to create a new gallium texture: */ if (!stObj->pt) { + const enum pipe_format fmt = + st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat); stObj->pt = st_texture_create(ctx->st, gl_target_to_pipe(stObj->base.Target), - st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat), + fmt, stObj->lastLevel, firstImage->base.Width2, firstImage->base.Height2, firstImage->base.Depth2, - comp_byte); + comp_byte, + ( (pf_is_depth_stencil(fmt) ? + PIPE_TEXTURE_USAGE_DEPTH_STENCIL : + PIPE_TEXTURE_USAGE_RENDER_TARGET) | + PIPE_TEXTURE_USAGE_SAMPLER )); + if (!stObj->pt) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); return GL_FALSE; @@ -1516,7 +1545,6 @@ st_finalize_texture(GLcontext *ctx, if (stImage && stObj->pt != stImage->pt) { copy_image_data_to_texture(ctx->st, stObj, level, stImage); *needFlush = GL_TRUE; - pipe->texture_update(pipe, stObj->pt, face, (1 << level)); } } } diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 1ca779d0a9..69be4ebdd0 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -53,6 +53,7 @@ struct bitmap_cache; #define ST_NEW_MESA 0x1 /* Mesa state has changed */ #define ST_NEW_FRAGMENT_PROGRAM 0x2 #define ST_NEW_VERTEX_PROGRAM 0x4 +#define ST_NEW_FRAMEBUFFER 0x8 struct st_state_flags { @@ -121,6 +122,8 @@ struct st_context struct st_state_flags dirty; + GLboolean missing_textures; + GLfloat polygon_offset_scale; /* ?? */ /** Mapping from VERT_RESULT_x to post-transformed vertex slot */ diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 1a0e19c2f9..cfacfdd04c 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -123,8 +123,10 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target, const ubyte *srcData; ubyte *dstData; - srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice); - dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice); + srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice, + PIPE_BUFFER_USAGE_CPU_READ); + dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice, + PIPE_BUFFER_USAGE_CPU_WRITE); srcData = (ubyte *) pipe_buffer_map(pipe, srcSurf->buffer, PIPE_BUFFER_USAGE_CPU_READ) diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index f68bef1207..9553b34e31 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -75,7 +75,8 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, - GLuint compress_byte) + GLuint compress_byte, + GLuint usage ) { struct pipe_texture pt, *newtex; struct pipe_screen *screen = st->pipe->screen; @@ -98,6 +99,7 @@ st_texture_create(struct st_context *st, pt.depth[0] = depth0; pt.compressed = compress_byte ? 1 : 0; pt.cpp = pt.compressed ? compress_byte : st_sizeof_format(format); + pt.tex_usage = usage; newtex = screen->texture_create(screen, &pt); @@ -184,25 +186,33 @@ st_texture_image_offset(const struct pipe_texture * pt, */ GLubyte * st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, - GLuint zoffset) + GLuint zoffset, + GLuint flags ) { struct pipe_screen *screen = st->pipe->screen; struct pipe_texture *pt = stImage->pt; DBG("%s \n", __FUNCTION__); stImage->surface = screen->get_tex_surface(screen, pt, stImage->face, - stImage->level, zoffset); + stImage->level, zoffset, + flags); - return pipe_surface_map(stImage->surface); + if (stImage->surface) + return screen->surface_map(screen, stImage->surface, flags); + else + return NULL; } void -st_texture_image_unmap(struct st_texture_image *stImage) +st_texture_image_unmap(struct st_context *st, + struct st_texture_image *stImage) { + struct pipe_screen *screen = st->pipe->screen; + DBG("%s\n", __FUNCTION__); - pipe_surface_unmap(stImage->surface); + screen->surface_unmap(screen, stImage->surface); pipe_surface_reference(&stImage->surface, NULL); } @@ -224,12 +234,15 @@ st_surface_data(struct pipe_context *pipe, const void *src, unsigned src_pitch, unsigned srcx, unsigned srcy, unsigned width, unsigned height) { - pipe_copy_rect(pipe_surface_map(dst), + struct pipe_screen *screen = pipe->screen; + void *map = screen->surface_map(screen, dst, PIPE_BUFFER_USAGE_CPU_WRITE); + + pipe_copy_rect(map, dst->cpp, dst->pitch, dstx, dsty, width, height, src, src_pitch, srcx, srcy); - pipe_surface_unmap(dst); + screen->surface_unmap(screen, dst); } @@ -256,7 +269,8 @@ st_texture_image_data(struct pipe_context *pipe, if(dst->compressed) height /= 4; - dst_surface = screen->get_tex_surface(screen, dst, face, level, i); + dst_surface = screen->get_tex_surface(screen, dst, face, level, i, + PIPE_BUFFER_USAGE_CPU_WRITE); st_surface_data(pipe, dst_surface, 0, 0, /* dstx, dsty */ @@ -265,7 +279,7 @@ st_texture_image_data(struct pipe_context *pipe, 0, 0, /* source x, y */ dst->width[level], height); /* width, height */ - pipe_surface_reference(&dst_surface, NULL); + screen->tex_surface_release(screen, &dst_surface); srcUB += src_image_pitch * dst->cpp; } @@ -304,8 +318,27 @@ st_texture_image_copy(struct pipe_context *pipe, assert(src->width[srcLevel] == width); assert(src->height[srcLevel] == height); - dst_surface = screen->get_tex_surface(screen, dst, face, dstLevel, i); - src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i); +#if 0 + { + src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i, + PIPE_BUFFER_USAGE_CPU_READ); + ubyte *map = screen->surface_map(screen, src_surface, PIPE_BUFFER_USAGE_CPU_READ); + map += src_surface->width * src_surface->height * 4 / 2; + printf("%s center pixel: %d %d %d %d (pt %p[%d] -> %p[%d])\n", + __FUNCTION__, + map[0], map[1], map[2], map[3], + src, srcLevel, dst, dstLevel); + + screen->surface_unmap(screen, src_surface); + pipe_surface_reference(&src_surface, NULL); + } +#endif + + dst_surface = screen->get_tex_surface(screen, dst, face, dstLevel, i, + PIPE_BUFFER_USAGE_GPU_WRITE); + + src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i, + PIPE_BUFFER_USAGE_GPU_READ); pipe->surface_copy(pipe, FALSE, @@ -315,7 +348,7 @@ st_texture_image_copy(struct pipe_context *pipe, 0, 0, /* srcX, Y */ width, copyHeight); - pipe_surface_reference(&dst_surface, NULL); - pipe_surface_reference(&src_surface, NULL); + screen->tex_surface_release(screen, &src_surface); + screen->tex_surface_release(screen, &dst_surface); } } diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index b05762113c..3febe6a7cb 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -93,6 +93,11 @@ st_get_stobj_texture(struct st_texture_object *stObj) return stObj ? stObj->pt : NULL; } +static INLINE GLboolean pf_is_depth_stencil( enum pipe_format format ) +{ + return (pf_get_component_bits( format, PIPE_FORMAT_COMP_Z ) + + pf_get_component_bits( format, PIPE_FORMAT_COMP_S )) != 0; +} extern struct pipe_texture * @@ -103,7 +108,8 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, - GLuint compress_byte); + GLuint compress_byte, + GLuint tex_usage ); /* Check if an image fits into an existing texture object. @@ -119,10 +125,12 @@ st_texture_match_image(const struct pipe_texture *pt, extern GLubyte * st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, - GLuint zoffset); + GLuint zoffset, + GLuint flags); extern void -st_texture_image_unmap(struct st_texture_image *stImage); +st_texture_image_unmap(struct st_context *st, + struct st_texture_image *stImage); /* Return pointers to each 2d slice within an image. Indexed by depth |