diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-06-12 12:09:34 -0400 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2009-06-12 12:09:34 -0400 |
commit | 1036ef2bf468611d37b5df06fc4424f2002e3837 (patch) | |
tree | f0859a6d903c2570a0a00c918da88139f8f7d065 /src/mesa/state_tracker | |
parent | 917f8bc1a85e61311cef6478127b387df70fba14 (diff) | |
parent | 1cd0afffc9edbcac690f8ab436aecfced26b0aba (diff) |
Merge master and fix conflicts
Diffstat (limited to 'src/mesa/state_tracker')
33 files changed, 1621 insertions, 730 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index f79092291b..ca15ce1b47 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -37,11 +37,8 @@ -/* This is used to initialize st->atoms[]. We could use this list - * directly except for a single atom, st_update_constants, which has a - * .dirty value which changes according to the parameters of the - * current fragment and vertex programs, and so cannot be a static - * value. +/** + * This is used to initialize st->atoms[]. */ static const struct st_tracked_state *atoms[] = { @@ -67,34 +64,13 @@ static const struct st_tracked_state *atoms[] = void st_init_atoms( struct st_context *st ) { - GLuint i; - - st->atoms = _mesa_malloc(sizeof(atoms)); - st->nr_atoms = sizeof(atoms)/sizeof(*atoms); - memcpy(st->atoms, atoms, sizeof(atoms)); - - /* Patch in a pointer to the dynamic state atom: - */ - for (i = 0; i < st->nr_atoms; i++) { - if (st->atoms[i] == &st_update_vs_constants) { - st->atoms[i] = &st->constants.tracked_state[PIPE_SHADER_VERTEX]; - st->atoms[i][0] = st_update_vs_constants; - } - - if (st->atoms[i] == &st_update_fs_constants) { - st->atoms[i] = &st->constants.tracked_state[PIPE_SHADER_FRAGMENT]; - st->atoms[i][0] = st_update_fs_constants; - } - } + /* no-op */ } void st_destroy_atoms( struct st_context *st ) { - if (st->atoms) { - _mesa_free(st->atoms); - st->atoms = NULL; - } + /* no-op */ } @@ -172,8 +148,8 @@ void st_validate_state( struct st_context *st ) memset(&examined, 0, sizeof(examined)); prev = *state; - for (i = 0; i < st->nr_atoms; i++) { - const struct st_tracked_state *atom = st->atoms[i]; + for (i = 0; i < Elements(atoms); i++) { + const struct st_tracked_state *atom = atoms[i]; struct st_state_flags generated; // _mesa_printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st); @@ -185,7 +161,7 @@ void st_validate_state( struct st_context *st ) } if (check_state(state, &atom->dirty)) { - st->atoms[i]->update( st ); + atoms[i]->update( st ); // _mesa_printf("after: %x\n", atom->dirty.mesa); } @@ -203,11 +179,9 @@ void st_validate_state( struct st_context *st ) } else { - const GLuint nr = st->nr_atoms; - - for (i = 0; i < nr; i++) { - if (check_state(state, &st->atoms[i]->dirty)) - st->atoms[i]->update( st ); + for (i = 0; i < Elements(atoms); i++) { + if (check_state(state, &atoms[i]->dirty)) + atoms[i]->update( st ); } } diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c index fd81ac36d2..5d4d8eee02 100644 --- a/src/mesa/state_tracker/st_atom_constbuf.c +++ b/src/mesa/state_tracker/st_atom_constbuf.c @@ -24,11 +24,12 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ - /* - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - * Brian Paul - */ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Brian Paul + */ #include "main/imports.h" #include "shader/prog_parameter.h" @@ -42,63 +43,61 @@ #include "st_atom.h" #include "st_atom_constbuf.h" #include "st_program.h" +#include "st_inlines.h" /** * Pass the given program parameters to the graphics pipe as a * constant buffer. - * \param id either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT + * \param shader_type either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT */ void st_upload_constants( struct st_context *st, struct gl_program_parameter_list *params, - unsigned id) + unsigned shader_type) { struct pipe_context *pipe = st->pipe; - struct pipe_constant_buffer *cbuf = &st->state.constants[id]; + struct pipe_constant_buffer *cbuf = &st->state.constants[shader_type]; - assert(id == PIPE_SHADER_VERTEX || id == PIPE_SHADER_FRAGMENT); + assert(shader_type == PIPE_SHADER_VERTEX || + shader_type == PIPE_SHADER_FRAGMENT); /* update constants */ if (params && params->NumParameters) { const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4; - /* Update our own dependency flags. This works because this - * function will also be called whenever the program changes. - */ - st->constants.tracked_state[id].dirty.mesa = - (params->StateFlags | _NEW_PROGRAM); - _mesa_load_state_parameters(st->ctx, params); /* We always need to get a new buffer, to keep the drivers simple and * avoid gratuitous rendering synchronization. */ pipe_buffer_reference(&cbuf->buffer, NULL ); - cbuf->buffer = pipe_buffer_create(pipe->screen, 16, PIPE_BUFFER_USAGE_CONSTANT, + cbuf->buffer = pipe_buffer_create(pipe->screen, 16, + PIPE_BUFFER_USAGE_CONSTANT, paramBytes ); - if (0) - { - printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", - __FUNCTION__, id, params->NumParameters, params->StateFlags); + if (0) { + debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", + __FUNCTION__, shader_type, params->NumParameters, + params->StateFlags); _mesa_print_parameter_list(params); } /* load Mesa constants into the constant buffer */ if (cbuf->buffer) - pipe_buffer_write(pipe->screen, cbuf->buffer, - 0, paramBytes, - params->ParameterValues); + st_no_flush_pipe_buffer_write(st, cbuf->buffer, + 0, paramBytes, + params->ParameterValues); - st->pipe->set_constant_buffer(st->pipe, id, 0, cbuf); + st->pipe->set_constant_buffer(st->pipe, shader_type, 0, cbuf); } else { - st->constants.tracked_state[id].dirty.mesa = 0; - // st->pipe->set_constant_buffer(st->pipe, id, 0, NULL); + st->constants.tracked_state[shader_type].dirty.mesa = 0x0; } } -/* Vertex shader: + +/** + * Vertex shader: */ static void update_vs_constants(struct st_context *st ) { @@ -108,16 +107,20 @@ static void update_vs_constants(struct st_context *st ) st_upload_constants( st, params, PIPE_SHADER_VERTEX ); } + const struct st_tracked_state st_update_vs_constants = { "st_update_vs_constants", /* name */ { /* dirty */ - 0, /* set dynamically above */ /* mesa */ + (_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */ ST_NEW_VERTEX_PROGRAM, /* st */ }, update_vs_constants /* update */ }; -/* Fragment shader: + + +/** + * Fragment shader: */ static void update_fs_constants(struct st_context *st ) { @@ -127,10 +130,11 @@ static void update_fs_constants(struct st_context *st ) st_upload_constants( st, params, PIPE_SHADER_FRAGMENT ); } + const struct st_tracked_state st_update_fs_constants = { "st_update_fs_constants", /* name */ { /* dirty */ - 0, /* set dynamically above */ /* mesa */ + (_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */ ST_NEW_FRAGMENT_PROGRAM, /* st */ }, update_fs_constants /* update */ diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index df0f0931ea..4d897b677e 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -98,8 +98,6 @@ update_framebuffer_state( struct st_context *st ) struct st_renderbuffer *strb; GLuint i; - memset(framebuffer, 0, sizeof(*framebuffer)); - framebuffer->width = fb->Width; framebuffer->height = fb->Height; @@ -120,12 +118,20 @@ update_framebuffer_state( struct st_context *st ) } if (strb->surface) { - framebuffer->cbufs[framebuffer->nr_cbufs] = strb->surface; + pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs], + strb->surface); framebuffer->nr_cbufs++; } + strb->defined = GL_TRUE; /* we'll be drawing something */ } } + for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) { + pipe_surface_reference(&framebuffer->cbufs[i], NULL); + } + /* + * Depth/Stencil renderbuffer/surface. + */ strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); if (strb) { strb = st_renderbuffer(strb->Base.Wrapped); @@ -133,15 +139,14 @@ update_framebuffer_state( struct st_context *st ) /* rendering to a GL texture, may have to update surface */ update_renderbuffer_surface(st, strb); } - - framebuffer->zsbuf = strb->surface; + pipe_surface_reference(&framebuffer->zsbuf, strb->surface); } else { strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); if (strb) { strb = st_renderbuffer(strb->Base.Wrapped); assert(strb->surface); - framebuffer->zsbuf = strb->surface; + pipe_surface_reference(&framebuffer->zsbuf, strb->surface); } } diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index 8d0029dde5..eff3666ca8 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -45,6 +45,7 @@ #include "st_format.h" #include "st_program.h" #include "st_texture.h" +#include "st_inlines.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" @@ -125,8 +126,7 @@ 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, - PIPE_TEXTURE_USAGE_SAMPLER); + texSize, texSize, 1, PIPE_TEXTURE_USAGE_SAMPLER); return pt; } @@ -148,8 +148,9 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) uint *dest; uint i, j; - transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE, - 0, 0, texSize, texSize); + transfer = st_cond_flush_get_tex_transfer(st_context(ctx), + pt, 0, 0, 0, PIPE_TRANSFER_WRITE, + 0, 0, texSize, texSize); dest = (uint *) screen->transfer_map(screen, transfer); /* Pack four 1D maps into a 2D texture: diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index 61687fbc3e..5c7206409c 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -180,22 +180,7 @@ static void update_raster_state( struct st_context *st ) if (ctx->Polygon.StippleFlag) raster->poly_stipple_enable = 1; - - - /* _NEW_BUFFERS, _NEW_POLYGON - */ - if (raster->fill_cw != PIPE_POLYGON_MODE_FILL || - raster->fill_ccw != PIPE_POLYGON_MODE_FILL) - { - GLfloat mrd = (ctx->DrawBuffer ? - ctx->DrawBuffer->_MRD : - 1.0f); - - raster->offset_units = ctx->Polygon.OffsetFactor * mrd; - raster->offset_scale = (ctx->Polygon.OffsetUnits * mrd * - st->polygon_offset_scale); - } - + /* _NEW_POINT */ raster->point_size = ctx->Point.Size; @@ -207,7 +192,8 @@ static void update_raster_state( struct st_context *st ) raster->point_sprite = ctx->Point.PointSprite; for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { if (ctx->Point.CoordReplace[i]) { - if (ctx->Point.SpriteOrigin == GL_UPPER_LEFT) + if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^ + (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM)) raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_UPPER_LEFT; else raster->sprite_coord_mode[i] = PIPE_SPRITE_COORD_LOWER_LEFT; diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index fc1ff5be04..ee649be885 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -175,11 +175,12 @@ find_translated_vp(struct st_context *st, /* See if we need to translate vertex program to TGSI form */ if (xvp->serialNo != stvp->serialNo) { - GLuint outAttr, dummySlot; + GLuint outAttr; const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten; GLuint numVpOuts = 0; GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; - GLint maxGeneric; + GLbitfield usedGenerics = 0x0; + GLbitfield usedOutputSlots = 0x0; /* Compute mapping of vertex program outputs to slots, which depends * on the fragment program's input->slot mapping. @@ -192,10 +193,12 @@ find_translated_vp(struct st_context *st, if (outAttr == VERT_RESULT_HPOS) { /* always put xformed position into slot zero */ - xvp->output_to_slot[VERT_RESULT_HPOS] = 0; + GLuint slot = 0; + xvp->output_to_slot[VERT_RESULT_HPOS] = slot; xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION; xvp->output_to_semantic_index[outAttr] = 0; numVpOuts++; + usedOutputSlots |= (1 << slot); } else if (outputsWritten & (1 << outAttr)) { /* see if the frag prog wants this vert output */ @@ -209,6 +212,12 @@ find_translated_vp(struct st_context *st, xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot]; xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot]; numVpOuts++; + usedOutputSlots |= (1 << vpOutSlot); + } + else { +#if 0 /*debug*/ + printf("VP output %d not used by FP\n", outAttr); +#endif } } else if (outAttr == VERT_RESULT_PSIZ) @@ -226,45 +235,49 @@ find_translated_vp(struct st_context *st, /* must do these last */ if (emitPntSize) { - xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++; + GLuint slot = numVpOuts++; + xvp->output_to_slot[VERT_RESULT_PSIZ] = slot; xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE; xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0; + usedOutputSlots |= (1 << slot); } if (emitBFC0) { - xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++; + GLuint slot = numVpOuts++; + xvp->output_to_slot[VERT_RESULT_BFC0] = slot; xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0; + usedOutputSlots |= (1 << slot); } if (emitBFC1) { - xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++; - xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; - xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1; + GLuint slot = numVpOuts++; + xvp->output_to_slot[VERT_RESULT_BFC1] = slot; + xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR; + xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1; + usedOutputSlots |= (1 << slot); } - /* Unneeded vertex program outputs will go to this slot. - * We could use this info to do dead code elimination in the - * vertex program. - */ - dummySlot = numVpOuts; - - /* find max GENERIC slot index */ - maxGeneric = -1; + /* build usedGenerics mask */ + usedGenerics = 0x0; for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) { - maxGeneric = MAX2(maxGeneric, - xvp->output_to_semantic_index[outAttr]); + usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]); } } - /* Map vert program outputs that aren't used to the dummy slot - * (and an unused generic attribute slot). + /* For each vertex program output that doesn't match up to a fragment + * program input, map the vertex program output to a free slot and + * free generic attribute. */ for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { if (outputsWritten & (1 << outAttr)) { if (xvp->output_to_slot[outAttr] == UNUSED) { - xvp->output_to_slot[outAttr] = dummySlot; + GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1; + GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1; + usedGenerics |= (1 << freeGeneric); + usedOutputSlots |= (1 << freeSlot); + xvp->output_to_slot[outAttr] = freeSlot; xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC; - xvp->output_to_semantic_index[outAttr] = maxGeneric + 1; + xvp->output_to_semantic_index[outAttr] = freeGeneric; } } diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index 3f9a825a15..95181578f6 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -40,16 +40,14 @@ #include "st_draw.h" #include "st_public.h" #include "st_format.h" +#include "st_texture.h" +#include "st_inlines.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" #include "util/u_tile.h" -#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \ - us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) ) - - /** * For hardware that supports deep color buffers, we could accelerate * most/all the accum operations with blending/texturing. @@ -57,73 +55,20 @@ */ -/** - * Wrapper for pipe_get_tile_rgba(). Do format/cpp override to make the - * tile util function think the surface is 16bit/channel, even if it's not. - * See also: st_renderbuffer_alloc_storage() - */ -static void -acc_get_tile_rgba(struct pipe_context *pipe, struct pipe_transfer *acc_pt, - uint x, uint y, uint w, uint h, float *p) -{ - const enum pipe_format f = acc_pt->format; - const struct pipe_format_block b = acc_pt->block; - - acc_pt->format = DEFAULT_ACCUM_PIPE_FORMAT; - acc_pt->block.size = 8; - acc_pt->block.width = 1; - acc_pt->block.height = 1; - - pipe_get_tile_rgba(acc_pt, x, y, w, h, p); - - acc_pt->format = f; - acc_pt->block = b; -} - - -/** - * Wrapper for pipe_put_tile_rgba(). Do format/cpp override to make the - * tile util function think the surface is 16bit/channel, even if it's not. - * See also: st_renderbuffer_alloc_storage() - */ -static void -acc_put_tile_rgba(struct pipe_context *pipe, struct pipe_transfer *acc_pt, - uint x, uint y, uint w, uint h, const float *p) -{ - enum pipe_format f = acc_pt->format; - const struct pipe_format_block b = acc_pt->block; - - acc_pt->format = DEFAULT_ACCUM_PIPE_FORMAT; - acc_pt->block.size = 8; - acc_pt->block.width = 1; - acc_pt->block.height = 1; - - pipe_put_tile_rgba(acc_pt, x, y, w, h, p); - - acc_pt->format = f; - acc_pt->block = b; -} - - - void st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) { struct st_renderbuffer *acc_strb = st_renderbuffer(rb); - struct pipe_transfer *acc_pt; - 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; - GLubyte *map; + size_t stride = acc_strb->stride; + GLubyte *data = acc_strb->data; - acc_pt = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, xpos, ypos, - width, height); - map = screen->transfer_map(screen, acc_pt); - - /* note acc_strb->format might not equal acc_pt->format */ + if(!data) + return; + switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: { @@ -133,7 +78,7 @@ st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]); int i, j; for (i = 0; i < height; i++) { - GLshort *dst = (GLshort *) (map + i * acc_pt->stride + xpos * 8); + GLshort *dst = (GLshort *) (data + (ypos + i) * stride + xpos * 8); for (j = 0; j < width; j++) { dst[0] = r; dst[1] = g; @@ -147,9 +92,6 @@ st_clear_accum_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) default: _mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()"); } - - screen->transfer_unmap(screen, acc_pt); - screen->tex_transfer_destroy(acc_pt); } @@ -159,25 +101,18 @@ 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_transfer *acc_pt; - GLubyte *map; + size_t stride = acc_strb->stride; + GLubyte *data = acc_strb->data; - acc_pt = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ_WRITE, xpos, ypos, - width, height); - map = screen->transfer_map(screen, acc_pt); - - /* note acc_strb->format might not equal acc_pt->format */ switch (acc_strb->format) { case PIPE_FORMAT_R16G16B16A16_SNORM: { int i, j; for (i = 0; i < height; i++) { - GLshort *acc = (GLshort *) (map + (ypos + i) * acc_pt->stride + xpos * 8); + GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); for (j = 0; j < width * 4; j++) { - float val = SHORT_TO_FLOAT(acc[j]) * scale + bias; - acc[j] = FLOAT_TO_SHORT(val); + float val = SHORT_TO_FLOAT(*acc) * scale + bias; + *acc++ = FLOAT_TO_SHORT(val); } } } @@ -185,86 +120,95 @@ accum_mad(GLcontext *ctx, GLfloat scale, GLfloat bias, default: _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - - screen->transfer_unmap(screen, acc_pt); - screen->tex_transfer_destroy(acc_pt); } static void -accum_accum(struct pipe_context *pipe, GLfloat value, +accum_accum(struct st_context *st, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, struct st_renderbuffer *acc_strb, struct st_renderbuffer *color_strb) { + struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_transfer *acc_trans, *color_trans; - GLfloat *colorBuf, *accBuf; - GLint i; - - acc_trans = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ, xpos, ypos, - width, height); + struct pipe_transfer *color_trans; + size_t stride = acc_strb->stride; + GLubyte *data = acc_strb->data; + GLfloat *buf; - color_trans = screen->get_tex_transfer(screen, color_strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ, xpos, ypos, - width, height); + color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture, + 0, 0, 0, + PIPE_TRANSFER_READ, xpos, ypos, + width, height); - colorBuf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); - accBuf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); + buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(color_trans, 0, 0, width, height, colorBuf); - acc_get_tile_rgba(pipe, acc_trans, 0, 0, width, height, accBuf); + pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); - for (i = 0; i < 4 * width * height; i++) { - accBuf[i] = accBuf[i] + colorBuf[i] * value; + switch (acc_strb->format) { + case PIPE_FORMAT_R16G16B16A16_SNORM: + { + const GLfloat *color = buf; + int i, j; + for (i = 0; i < height; i++) { + GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); + for (j = 0; j < width * 4; j++) { + float val = *color++ * value; + *acc++ += FLOAT_TO_SHORT(val); + } + } + } + break; + default: + _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - screen->tex_transfer_destroy(acc_trans); - acc_trans = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, xpos, ypos, - width, height); - - acc_put_tile_rgba(pipe, acc_trans, 0, 0, width, height, accBuf); - - _mesa_free(colorBuf); - _mesa_free(accBuf); - screen->tex_transfer_destroy(acc_trans); + _mesa_free(buf); screen->tex_transfer_destroy(color_trans); } static void -accum_load(struct pipe_context *pipe, GLfloat value, +accum_load(struct st_context *st, GLfloat value, GLint xpos, GLint ypos, GLint width, GLint height, struct st_renderbuffer *acc_strb, struct st_renderbuffer *color_strb) { + struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_transfer *acc_trans, *color_trans; + struct pipe_transfer *color_trans; + size_t stride = acc_strb->stride; + GLubyte *data = acc_strb->data; GLfloat *buf; - GLint i; - acc_trans = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, xpos, ypos, - width, height); - - color_trans = screen->get_tex_transfer(screen, color_strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ, xpos, ypos, - width, height); + color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture, + 0, 0, 0, + PIPE_TRANSFER_READ, xpos, ypos, + width, height); buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); - for (i = 0; i < 4 * width * height; i++) { - buf[i] = buf[i] * value; + switch (acc_strb->format) { + case PIPE_FORMAT_R16G16B16A16_SNORM: + { + const GLfloat *color = buf; + int i, j; + for (i = 0; i < height; i++) { + GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8); + for (j = 0; j < width * 4; j++) { + float val = *color++ * value; + *acc++ = FLOAT_TO_SHORT(val); + } + } + } + break; + default: + _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - acc_put_tile_rgba(pipe, acc_trans, 0, 0, width, height, buf); - _mesa_free(buf); - screen->tex_transfer_destroy(acc_trans); screen->tex_transfer_destroy(color_trans); } @@ -278,45 +222,58 @@ accum_return(GLcontext *ctx, GLfloat value, struct pipe_context *pipe = ctx->st->pipe; struct pipe_screen *screen = pipe->screen; const GLubyte *colormask = ctx->Color.ColorMask; - struct pipe_transfer *acc_trans, *color_trans; - GLfloat *abuf, *cbuf = NULL; - GLint i, ch; - - abuf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); - - acc_trans = screen->get_tex_transfer(screen, acc_strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ, xpos, ypos, - width, height); + enum pipe_transfer_usage usage; + struct pipe_transfer *color_trans; + size_t stride = acc_strb->stride; + const GLubyte *data = acc_strb->data; + GLfloat *buf; - color_trans = screen->get_tex_transfer(screen, color_strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ_WRITE, xpos, ypos, - width, height); + buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); - acc_get_tile_rgba(pipe, acc_trans, 0, 0, width, height, abuf); + if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) + usage = PIPE_TRANSFER_READ_WRITE; + else + usage = PIPE_TRANSFER_WRITE; + + color_trans = st_cond_flush_get_tex_transfer(st_context(ctx), + color_strb->texture, 0, 0, 0, + usage, + xpos, ypos, + width, height); - if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) { - cbuf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); - pipe_get_tile_rgba(color_trans, 0, 0, width, height, cbuf); - } + if (usage != PIPE_TRANSFER_WRITE) + pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); - for (i = 0; i < width * height; i++) { - for (ch = 0; ch < 4; ch++) { - if (colormask[ch]) { - GLfloat val = abuf[i * 4 + ch] * value; - abuf[i * 4 + ch] = CLAMP(val, 0.0f, 1.0f); - } - else { - abuf[i * 4 + ch] = cbuf[i * 4 + ch]; + switch (acc_strb->format) { + case PIPE_FORMAT_R16G16B16A16_SNORM: + { + GLfloat *color = buf; + int i, j, ch; + for (i = 0; i < height; i++) { + const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8); + for (j = 0; j < width; j++) { + for (ch = 0; ch < 4; ch++) { + if (colormask[ch]) { + GLfloat val = SHORT_TO_FLOAT(*acc * value); + *color = CLAMP(val, 0.0f, 1.0f); + } + else { + /* No change */ + } + ++acc; + ++color; + } + } } } + break; + default: + _mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()"); } - pipe_put_tile_rgba(color_trans, 0, 0, width, height, abuf); + pipe_put_tile_rgba(color_trans, 0, 0, width, height, buf); - _mesa_free(abuf); - if (cbuf) - _mesa_free(cbuf); - screen->tex_transfer_destroy(acc_trans); + _mesa_free(buf); screen->tex_transfer_destroy(color_trans); } @@ -325,7 +282,6 @@ static void st_Accum(GLcontext *ctx, GLenum op, GLfloat value) { struct st_context *st = ctx->st; - struct pipe_context *pipe = st->pipe; struct st_renderbuffer *acc_strb = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); struct st_renderbuffer *color_strb @@ -336,6 +292,9 @@ st_Accum(GLcontext *ctx, GLenum op, GLfloat value) const GLint width = ctx->DrawBuffer->_Xmax - xpos; const GLint height = ctx->DrawBuffer->_Ymax - ypos; + if(!acc_strb->data) + return; + /* make sure color bufs aren't cached */ st_flush( st, PIPE_FLUSH_RENDER_CACHE, NULL ); @@ -352,11 +311,11 @@ 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_strb, color_strb); + accum_accum(st, value, xpos, ypos, width, height, acc_strb, color_strb); } break; case GL_LOAD: - accum_load(pipe, value, xpos, ypos, width, height, acc_strb, color_strb); + accum_load(st, value, xpos, ypos, width, height, acc_strb, color_strb); break; case GL_RETURN: accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb); diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 2d547dd072..8709633557 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -47,6 +47,8 @@ #include "st_cb_program.h" #include "st_mesa_to_tgsi.h" #include "st_texture.h" +#include "st_inlines.h" + #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" @@ -147,7 +149,7 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex) p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX; p->Instructions[ic].SrcReg[0].Index = 0; - p->Instructions[ic].SrcReg[0].NegateBase = NEGATE_XYZW; + p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW; ic++; /* END; */ @@ -330,15 +332,16 @@ 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, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) { _mesa_unmap_bitmap_pbo(ctx, unpack); return NULL; } - transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE, - 0, 0, width, height); + transfer = st_no_flush_get_tex_transfer(st_context(ctx), pt, 0, 0, 0, + PIPE_TRANSFER_WRITE, + 0, 0, width, height); dest = screen->transfer_map(screen, transfer); @@ -425,11 +428,11 @@ setup_bitmap_vertex_data(struct st_context *st, } /* put vertex data into vbuf */ - pipe_buffer_write(pipe->screen, - st->bitmap.vbuf, - st->bitmap.vbuf_slot * sizeof st->bitmap.vertices, - sizeof st->bitmap.vertices, - st->bitmap.vertices); + st_no_flush_pipe_buffer_write(st, + st->bitmap.vbuf, + st->bitmap.vbuf_slot * sizeof st->bitmap.vertices, + sizeof st->bitmap.vertices, + st->bitmap.vertices); return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices; } @@ -570,8 +573,10 @@ reset_cache(struct st_context *st) cache->ymin = 1000000; cache->ymax = -1000000; - if (cache->trans) + if (cache->trans) { screen->tex_transfer_destroy(cache->trans); + cache->trans = NULL; + } assert(!cache->texture); @@ -579,16 +584,27 @@ 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, - PIPE_TEXTURE_USAGE_SAMPLER); + 1, PIPE_TEXTURE_USAGE_SAMPLER); + +} + +static void +create_cache_trans(struct st_context *st) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + struct bitmap_cache *cache = st->bitmap.cache; + + if (cache->trans) + return; /* Map the texture transfer. * Subsequent glBitmap calls will write into the texture image. */ - cache->trans = screen->get_tex_transfer(screen, cache->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, 0, 0, - BITMAP_CACHE_WIDTH, - BITMAP_CACHE_HEIGHT); + cache->trans = st_no_flush_get_tex_transfer(st, cache->texture, 0, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, + BITMAP_CACHE_WIDTH, + BITMAP_CACHE_HEIGHT); cache->buffer = screen->transfer_map(screen, cache->trans); /* init image to all 0xff */ @@ -620,11 +636,13 @@ st_flush_bitmap_cache(struct st_context *st) /* The texture transfer has been mapped until now. * So unmap and release the texture transfer before drawing. */ - screen->transfer_unmap(screen, cache->trans); - cache->buffer = NULL; + if (cache->trans) { + screen->transfer_unmap(screen, cache->trans); + cache->buffer = NULL; - screen->tex_transfer_destroy(cache->trans); - cache->trans = NULL; + screen->tex_transfer_destroy(cache->trans); + cache->trans = NULL; + } draw_bitmap_quad(st->ctx, cache->xpos, @@ -709,6 +727,9 @@ accum_bitmap(struct st_context *st, if (y + height > cache->ymax) cache->ymax = y + height; + /* create the transfer if needed */ + create_cache_trans(st); + unpack_bitmap(st, px, py, width, height, unpack, bitmap, cache->buffer, BITMAP_CACHE_WIDTH); @@ -821,8 +842,7 @@ st_destroy_bitmap(struct st_context *st) struct pipe_screen *screen = pipe->screen; struct bitmap_cache *cache = st->bitmap.cache; - screen->transfer_unmap(screen, cache->trans); - screen->tex_transfer_destroy(cache->trans); + if (st->bitmap.vs) { cso_delete_vertex_shader(st->cso_context, st->bitmap.vs); @@ -834,7 +854,11 @@ st_destroy_bitmap(struct st_context *st) st->bitmap.vbuf = NULL; } - if (st->bitmap.cache) { + if (cache) { + if (cache->trans) { + screen->transfer_unmap(screen, cache->trans); + screen->tex_transfer_destroy(cache->trans); + } pipe_texture_reference(&st->bitmap.cache->texture, NULL); _mesa_free(st->bitmap.cache); st->bitmap.cache = NULL; diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c index 3651e4ae7d..7021d73208 100644 --- a/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -26,10 +26,17 @@ **************************************************************************/ +/** + * Functions for pixel buffer objects and vertex/element buffer objects. + */ + + #include "main/imports.h" #include "main/mtypes.h" +#include "main/arrayobj.h" #include "main/bufferobj.h" +#include "st_inlines.h" #include "st_context.h" #include "st_cb_bufferobjects.h" @@ -38,14 +45,6 @@ #include "pipe/p_inlines.h" - -/* Pixel buffers and Vertex/index buffers are handled through these - * mesa callbacks. Framebuffer/Renderbuffer objects are - * created/managed elsewhere. - */ - - - /** * There is some duplication between mesa's bufferobjects and our * bufmgr buffers. Both have an integer handle and a hashtable to @@ -97,13 +96,13 @@ st_bufferobj_subdata(GLcontext *ctx, GLsizeiptrARB size, const GLvoid * data, struct gl_buffer_object *obj) { - struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); if (offset >= st_obj->size || size > (st_obj->size - offset)) return; - pipe_buffer_write(pipe->screen, st_obj->buffer, offset, size, data); + st_cond_flush_pipe_buffer_write(st_context(ctx), st_obj->buffer, + offset, size, data); } @@ -117,13 +116,13 @@ st_bufferobj_get_subdata(GLcontext *ctx, GLsizeiptrARB size, GLvoid * data, struct gl_buffer_object *obj) { - struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); if (offset >= st_obj->size || size > (st_obj->size - offset)) return; - pipe_buffer_read(pipe->screen, st_obj->buffer, offset, size, data); + st_cond_flush_pipe_buffer_read(st_context(ctx), st_obj->buffer, + offset, size, data); } @@ -168,10 +167,16 @@ st_bufferobj_data(GLcontext *ctx, st_obj->buffer = pipe_buffer_create( pipe->screen, 32, buffer_usage, size ); + if (!st_obj->buffer) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB"); + return; + } + st_obj->size = size; if (data) - st_bufferobj_subdata(ctx, target, 0, size, data, obj); + st_no_flush_pipe_buffer_write(st_context(ctx), st_obj->buffer, 0, + size, data); } @@ -182,9 +187,8 @@ static void * st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access, struct gl_buffer_object *obj) { - struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - GLuint flags; + uint flags; switch (access) { case GL_WRITE_ONLY: @@ -200,8 +204,10 @@ st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access, break; } - obj->Pointer = pipe_buffer_map(pipe->screen, st_obj->buffer, flags); - if(obj->Pointer) { + obj->Pointer = st_cond_flush_pipe_buffer_map(st_context(ctx), + st_obj->buffer, + flags); + if (obj->Pointer) { obj->Offset = 0; obj->Length = obj->Size; } @@ -209,7 +215,6 @@ st_bufferobj_map(GLcontext *ctx, GLenum target, GLenum access, } - /** * Called via glMapBufferRange(). */ @@ -220,7 +225,7 @@ st_bufferobj_map_range(GLcontext *ctx, GLenum target, { struct pipe_context *pipe = st_context(ctx)->pipe; struct st_buffer_object *st_obj = st_buffer_object(obj); - GLuint flags = 0; + uint flags = 0x0; char *map; if (access & GL_MAP_WRITE_BIT) @@ -242,8 +247,8 @@ st_bufferobj_map_range(GLcontext *ctx, GLenum target, map = obj->Pointer = pipe_buffer_map_range(pipe->screen, st_obj->buffer, offset, length, flags); if(obj->Pointer) { - obj->Offset = 0; - obj->Length = obj->Size; + obj->Offset = offset; + obj->Length = length; map += offset; } @@ -262,7 +267,6 @@ st_bufferobj_flush_mapped_range(GLcontext *ctx, GLenum target, /* Subrange is relative to mapped range */ assert(offset >= 0); assert(length >= 0); - assert(offset < obj->Length); assert(offset + length <= obj->Length); pipe_buffer_flush_mapped_range(pipe->screen, st_obj->buffer, @@ -287,6 +291,43 @@ st_bufferobj_unmap(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj) } +/** + * Called via glCopyBufferSubData(). + */ +static void +st_copy_buffer_subdata(GLcontext *ctx, + struct gl_buffer_object *src, + struct gl_buffer_object *dst, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size) +{ + struct pipe_context *pipe = st_context(ctx)->pipe; + struct st_buffer_object *srcObj = st_buffer_object(src); + struct st_buffer_object *dstObj = st_buffer_object(dst); + ubyte *srcPtr, *dstPtr; + + /* buffer should not already be mapped */ + assert(!src->Pointer); + assert(!dst->Pointer); + + srcPtr = (ubyte *) pipe_buffer_map_range(pipe->screen, + srcObj->buffer, + readOffset, size, + PIPE_BUFFER_USAGE_CPU_READ); + + dstPtr = (ubyte *) pipe_buffer_map_range(pipe->screen, + dstObj->buffer, + writeOffset, size, + PIPE_BUFFER_USAGE_CPU_WRITE); + + if (srcPtr && dstPtr) + _mesa_memcpy(dstPtr + writeOffset, srcPtr + readOffset, size); + + pipe_buffer_unmap(pipe->screen, srcObj->buffer); + pipe_buffer_unmap(pipe->screen, dstObj->buffer); +} + + void st_init_bufferobject_functions(struct dd_function_table *functions) { @@ -299,4 +340,9 @@ st_init_bufferobject_functions(struct dd_function_table *functions) functions->MapBufferRange = st_bufferobj_map_range; functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range; functions->UnmapBuffer = st_bufferobj_unmap; + functions->CopyBufferSubData = st_copy_buffer_subdata; + + /* For GL_APPLE_vertex_array_object */ + functions->NewArrayObject = _mesa_new_array_object; + functions->DeleteArrayObject = _mesa_delete_array_object; } diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 5bdc6a1330..668acbccb8 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -45,6 +45,7 @@ #include "st_program.h" #include "st_public.h" #include "st_mesa_to_tgsi.h" +#include "st_inlines.h" #include "pipe/p_context.h" #include "pipe/p_inlines.h" @@ -102,20 +103,6 @@ st_destroy_clear(struct st_context *st) } -static GLboolean -is_depth_stencil_format(enum pipe_format pipeFormat) -{ - switch (pipeFormat) { - case PIPE_FORMAT_S8Z24_UNORM: - case PIPE_FORMAT_Z24S8_UNORM: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - - /** * Draw a screen-aligned quadrilateral. * Coords are window coords with y=0=bottom. These will be passed @@ -166,10 +153,10 @@ draw_quad(GLcontext *ctx, } /* put vertex data into vbuf */ - pipe_buffer_write(pipe->screen, st->clear.vbuf, - st->clear.vbuf_slot * sizeof(st->clear.vertices), - sizeof(st->clear.vertices), - st->clear.vertices); + st_no_flush_pipe_buffer_write(st, st->clear.vbuf, + st->clear.vbuf_slot * sizeof(st->clear.vertices), + sizeof(st->clear.vertices), + st->clear.vertices); /* draw */ util_draw_vertex_buffer(pipe, @@ -330,7 +317,7 @@ static INLINE GLboolean check_clear_depth_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) { const struct st_renderbuffer *strb = st_renderbuffer(rb); - const GLboolean isDS = is_depth_stencil_format(strb->surface->format); + const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format); if (ctx->Scissor.Enabled) return TRUE; @@ -350,7 +337,7 @@ static INLINE GLboolean check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) { const struct st_renderbuffer *strb = st_renderbuffer(rb); - const GLboolean isDS = is_depth_stencil_format(strb->surface->format); + const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format); const GLuint stencilMax = (1 << rb->StencilBits) - 1; const GLboolean maskStencil = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax; diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index ebb1d1142a..2027b713ce 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -53,6 +53,8 @@ #include "st_format.h" #include "st_mesa_to_tgsi.h" #include "st_texture.h" +#include "st_inlines.h" + #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" @@ -144,6 +146,8 @@ combined_drawpix_fragment_program(GLcontext *ctx) st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo; st->pixel_xfer.user_prog_sn = st->fp->serialNo; st->pixel_xfer.combined_prog_sn = stfp->serialNo; + /* can't reference new program directly, already have a reference on it */ + st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); st->pixel_xfer.combined_prog = stfp; } @@ -351,8 +355,7 @@ make_texture(struct st_context *st, if (!pixels) return NULL; - pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, - 1, 0, + pt = st_texture_create(st, PIPE_TEXTURE_2D, pipeFormat, 0, width, height, 1, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) { _mesa_unmap_drawpix_pbo(ctx, unpack); @@ -369,9 +372,9 @@ make_texture(struct st_context *st, /* we'll do pixel transfer in a fragment shader */ ctx->_ImageTransferState = 0x0; - transfer = screen->get_tex_transfer(screen, pt, 0, 0, 0, - PIPE_TRANSFER_WRITE, 0, 0, - width, height); + transfer = st_no_flush_get_tex_transfer(st, pt, 0, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, + width, height); /* map texture transfer */ dest = screen->transfer_map(screen, transfer); @@ -491,7 +494,7 @@ draw_quad(GLcontext *ctx, GLfloat x0, GLfloat y0, GLfloat z, /* allocate/load buffer object with vertex data */ buf = pipe_buffer_create(pipe->screen, 32, PIPE_BUFFER_USAGE_VERTEX, sizeof(verts)); - pipe_buffer_write(pipe->screen, buf, 0, sizeof(verts), verts); + st_no_flush_pipe_buffer_write(st, buf, 0, sizeof(verts), verts); util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, @@ -627,13 +630,12 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *strb; + enum pipe_transfer_usage usage; struct pipe_transfer *pt; 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); @@ -641,9 +643,15 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, y = ctx->DrawBuffer->Height - y - height; } - pt = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, x, y, - width, height); + if(format != GL_DEPTH_STENCIL && + pf_get_component_bits( strb->format, PIPE_FORMAT_COMP_Z ) != 0) + usage = PIPE_TRANSFER_READ_WRITE; + else + usage = PIPE_TRANSFER_WRITE; + + pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, 0, 0, 0, + usage, x, y, + width, height); stmap = screen->transfer_map(screen, pt); @@ -693,6 +701,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, case PIPE_FORMAT_S8_UNORM: { ubyte *dest = stmap + spanY * pt->stride + spanX; + assert(usage == PIPE_TRANSFER_WRITE); memcpy(dest, sValues, spanWidth); } break; @@ -700,6 +709,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; + assert(usage == PIPE_TRANSFER_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = zValues[k] | (sValues[k] << 24); } @@ -707,6 +717,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, else { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; + assert(usage == PIPE_TRANSFER_READ_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24); } @@ -716,13 +727,15 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, if (format == GL_DEPTH_STENCIL) { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; + assert(usage == PIPE_TRANSFER_WRITE); for (k = 0; k < spanWidth; k++) { - dest[k] = zValues[k] | (sValues[k] << 24); + dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff); } } else { uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4); GLint k; + assert(usage == PIPE_TRANSFER_READ_WRITE); for (k = 0; k < spanWidth; k++) { dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff); } @@ -756,7 +769,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, struct st_vertex_program *stvp; struct st_context *st = ctx->st; struct pipe_surface *ps; - GLuint bufferFormat; const GLfloat *color; if (format == GL_STENCIL_INDEX || @@ -784,8 +796,6 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, color = NULL; } - bufferFormat = ps->format; - /* draw with textured quad */ { struct pipe_texture *pt @@ -810,6 +820,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, { struct st_renderbuffer *rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer); struct pipe_screen *screen = ctx->st->pipe->screen; + enum pipe_transfer_usage usage; struct pipe_transfer *ptDraw; ubyte *drawMap; ubyte *buffer; @@ -826,9 +837,15 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &ctx->DefaultPacking, buffer); - ptDraw = screen->get_tex_transfer(screen, rbDraw->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, dstx, dsty, - width, height); + if(pf_get_component_bits( rbDraw->format, PIPE_FORMAT_COMP_Z ) != 0) + usage = PIPE_TRANSFER_READ_WRITE; + else + usage = PIPE_TRANSFER_WRITE; + + ptDraw = st_cond_flush_get_tex_transfer(st_context(ctx), + rbDraw->texture, 0, 0, 0, + usage, dstx, dsty, + width, height); assert(ptDraw->block.width == 1); assert(ptDraw->block.height == 1); @@ -857,6 +874,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, { uint *dst4 = (uint *) dst; int j; + assert(usage == PIPE_TRANSFER_READ_WRITE); for (j = 0; j < width; j++) { *dst4 = (*dst4 & 0xffffff) | (src[j] << 24); dst4++; @@ -867,6 +885,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, { uint *dst4 = (uint *) dst; int j; + assert(usage == PIPE_TRANSFER_READ_WRITE); for (j = 0; j < width; j++) { *dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff); dst4++; @@ -874,6 +893,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, } break; case PIPE_FORMAT_S8_UNORM: + assert(usage == PIPE_TRANSFER_WRITE); memcpy(dst, src, width); break; default: @@ -904,11 +924,38 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, GLfloat *color; enum pipe_format srcFormat, texFormat; - /* make sure rendering has completed */ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); st_validate_state(st); + if (srcx < 0) { + width -= -srcx; + dstx += -srcx; + srcx = 0; + } + + if (srcy < 0) { + height -= -srcy; + dsty += -srcy; + srcy = 0; + } + + if (dstx < 0) { + width -= -dstx; + srcx += -dstx; + dstx = 0; + } + + if (dsty < 0) { + height -= -dsty; + srcy += -dsty; + dsty = 0; + } + + if (width < 0 || height < 0) + return; + + if (type == GL_STENCIL) { /* can't use texturing to do stencil */ copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty); @@ -950,15 +997,24 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, } } + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { + srcy = ctx->DrawBuffer->Height - srcy - height; + + if (srcy < 0) { + height -= -srcy; + srcy = 0; + } + + if (height < 0) + return; + } + pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, texFormat, 0, - width, height, 1, 0, + width, height, 1, PIPE_TEXTURE_USAGE_SAMPLER); if (!pt) return; - 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 */ @@ -978,13 +1034,13 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = - screen->get_tex_transfer(screen, rbRead->texture, 0, 0, 0, - PIPE_TRANSFER_READ, srcx, srcy, width, - height); + st_cond_flush_get_tex_transfer(st, rbRead->texture, 0, 0, 0, + PIPE_TRANSFER_READ, srcx, srcy, width, + height); struct pipe_transfer *ptTex = - screen->get_tex_transfer(screen, pt, 0, 0, 0, PIPE_TRANSFER_WRITE, - 0, 0, width, height); + st_cond_flush_get_tex_transfer(st, pt, 0, 0, 0, PIPE_TRANSFER_WRITE, + 0, 0, width, height); if (type == GL_COLOR) { /* alternate path using get/put_tile() */ diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index f74d0d46d0..ecdb988033 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -88,94 +88,92 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, { struct pipe_context *pipe = ctx->st->pipe; struct st_renderbuffer *strb = st_renderbuffer(rb); - struct pipe_texture template; - unsigned surface_usage; - - /* Free the old surface and texture - */ - pipe_surface_reference( &strb->surface, NULL ); - pipe_texture_reference( &strb->texture, NULL ); - - - memset(&template, 0, sizeof(template)); - - if (strb->format != PIPE_FORMAT_NONE) { - template.format = strb->format; - } - else { - template.format = st_choose_renderbuffer_format(pipe, internalFormat); - } - + enum pipe_format format; + + if (strb->format != PIPE_FORMAT_NONE) + format = strb->format; + else + format = st_choose_renderbuffer_format(pipe, internalFormat); + + /* init renderbuffer fields */ strb->Base.Width = width; strb->Base.Height = height; - init_renderbuffer_bits(strb, template.format); - - template.target = PIPE_TEXTURE_2D; - template.compressed = 0; - pf_get_block(template.format, &template.block); - template.width[0] = width; - template.height[0] = height; - template.depth[0] = 1; - template.last_level = 0; - template.nr_samples = rb->NumSamples; - - if (pf_is_depth_stencil(template.format)) { - template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + init_renderbuffer_bits(strb, format); + + strb->defined = GL_FALSE; /* undefined contents now */ + + if(strb->software) { + struct pipe_format_block block; + size_t size; + + _mesa_free(strb->data); + + assert(strb->format != PIPE_FORMAT_NONE); + pf_get_block(strb->format, &block); + + strb->stride = pf_get_stride(&block, width); + size = pf_get_2d_size(&block, strb->stride, height); + + strb->data = _mesa_malloc(size); + + return strb->data != NULL; } else { - template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_RENDER_TARGET); - } - - - /* 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 ); + struct pipe_texture template; + unsigned surface_usage; + + /* Free the old surface and texture + */ + pipe_surface_reference( &strb->surface, NULL ); + pipe_texture_reference( &strb->texture, NULL ); - /* 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. + /* Setup new texture template. */ - template.tex_usage = 0; - surface_usage = (PIPE_BUFFER_USAGE_CPU_READ | + memset(&template, 0, sizeof(template)); + template.target = PIPE_TEXTURE_2D; + template.format = format; + pf_get_block(format, &template.block); + template.width[0] = width; + template.height[0] = height; + template.depth[0] = 1; + template.last_level = 0; + template.nr_samples = rb->NumSamples; + if (pf_is_depth_stencil(format)) { + template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + } + else { + template.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET); + } + + /* 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 ); - } - - if (!strb->texture) - return FALSE; + if (!strb->texture) + return FALSE; - strb->surface = pipe->screen->get_tex_surface( pipe->screen, - strb->texture, - 0, 0, 0, - surface_usage ); + strb->surface = pipe->screen->get_tex_surface( pipe->screen, + strb->texture, + 0, 0, 0, + surface_usage ); - assert(strb->surface->texture); - assert(strb->surface->format); - assert(strb->surface->width == width); - assert(strb->surface->height == height); + assert(strb->surface->texture); + assert(strb->surface->format); + assert(strb->surface->width == width); + assert(strb->surface->height == height); - return strb->surface != NULL; + return strb->surface != NULL; + } } @@ -189,6 +187,7 @@ st_renderbuffer_delete(struct gl_renderbuffer *rb) ASSERT(strb); pipe_surface_reference(&strb->surface, NULL); pipe_texture_reference(&strb->texture, NULL); + _mesa_free(strb->data); _mesa_free(strb); } @@ -245,7 +244,7 @@ st_new_renderbuffer(GLcontext *ctx, GLuint name) * renderbuffer). The window system code determines the format. */ struct gl_renderbuffer * -st_new_renderbuffer_fb(enum pipe_format format, int samples) +st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) { struct st_renderbuffer *strb; @@ -259,7 +258,8 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples) strb->Base.ClassID = 0x4242; /* just a unique value */ strb->Base.NumSamples = samples; strb->format = format; - + strb->software = sw; + switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: @@ -290,7 +290,7 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples) strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT; strb->Base._BaseFormat = GL_STENCIL_INDEX; break; - case DEFAULT_ACCUM_PIPE_FORMAT: /*PIPE_FORMAT_R16G16B16A16_SNORM*/ + case PIPE_FORMAT_R16G16B16A16_SNORM: strb->Base.InternalFormat = GL_RGBA16; strb->Base._BaseFormat = GL_RGBA; break; @@ -346,6 +346,7 @@ st_render_texture(GLcontext *ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { + struct pipe_screen *screen = ctx->st->pipe->screen; struct st_renderbuffer *strb; struct gl_renderbuffer *rb; struct pipe_texture *pt = st_get_texobj_texture(att->Texture); @@ -368,6 +369,8 @@ st_render_texture(GLcontext *ctx, rb->AllocStorage = NULL; /* should not get called */ strb = st_renderbuffer(rb); + assert(strb->Base.RefCount > 0); + /* get the texture for the texture object */ stObj = st_texture_object(att->Texture); @@ -387,7 +390,14 @@ st_render_texture(GLcontext *ctx, pipe_surface_reference(&strb->surface, NULL); - /* the new surface will be created during framebuffer validation */ + /* new surface for rendering into the texture */ + strb->surface = screen->get_tex_surface(screen, + strb->texture, + strb->rtt_face, + strb->rtt_level, + strb->rtt_slice, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); init_renderbuffer_bits(strb, pt->format); @@ -455,6 +465,134 @@ st_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) } +/** + * Copy back color buffer to front color buffer. + */ +static void +copy_back_to_front(struct st_context *st, + struct gl_framebuffer *fb, + gl_buffer_index frontIndex, + gl_buffer_index backIndex) + +{ + struct st_framebuffer *stfb = (struct st_framebuffer *) fb; + struct pipe_surface *surf_front, *surf_back; + + (void) st_get_framebuffer_surface(stfb, frontIndex, &surf_front); + (void) st_get_framebuffer_surface(stfb, backIndex, &surf_back); + + if (surf_front && surf_back) { + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); + } +} + + +/** + * Check if we're drawing into, or read from, a front color buffer. If the + * front buffer is missing, create it now. + * + * The back color buffer must exist since we'll use its format/samples info + * for creating the front buffer. + * + * \param frontIndex either BUFFER_FRONT_LEFT or BUFFER_FRONT_RIGHT + * \param backIndex either BUFFER_BACK_LEFT or BUFFER_BACK_RIGHT + */ +static void +check_create_front_buffer(GLcontext *ctx, struct gl_framebuffer *fb, + gl_buffer_index frontIndex, + gl_buffer_index backIndex) +{ + if (fb->Attachment[frontIndex].Renderbuffer == NULL) { + GLboolean create = GL_FALSE; + + /* check if drawing to or reading from front buffer */ + if (fb->_ColorReadBufferIndex == frontIndex) { + create = GL_TRUE; + } + else { + GLuint b; + for (b = 0; b < fb->_NumColorDrawBuffers; b++) { + if (fb->_ColorDrawBufferIndexes[b] == frontIndex) { + create = GL_TRUE; + break; + } + } + } + + if (create) { + struct st_renderbuffer *back; + struct gl_renderbuffer *front; + enum pipe_format colorFormat; + uint samples; + + if (0) + _mesa_debug(ctx, "Allocate new front buffer\n"); + + /* get back renderbuffer info */ + back = st_renderbuffer(fb->Attachment[backIndex].Renderbuffer); + colorFormat = back->format; + samples = back->Base.NumSamples; + + /* create front renderbuffer */ + front = st_new_renderbuffer_fb(colorFormat, samples, FALSE); + _mesa_add_renderbuffer(fb, frontIndex, front); + + /* alloc texture/surface for new front buffer */ + front->AllocStorage(ctx, front, front->InternalFormat, + fb->Width, fb->Height); + + /* initialize the front color buffer contents by copying + * the back buffer. + */ + copy_back_to_front(ctx->st, fb, frontIndex, backIndex); + } + } +} + + +/** + * If front left/right color buffers are missing, create them now. + */ +static void +check_create_front_buffers(GLcontext *ctx, struct gl_framebuffer *fb) +{ + /* check if we need to create the front left buffer now */ + check_create_front_buffer(ctx, fb, BUFFER_FRONT_LEFT, BUFFER_BACK_LEFT); + + if (fb->Visual.stereoMode) { + check_create_front_buffer(ctx, fb, BUFFER_FRONT_RIGHT, BUFFER_BACK_RIGHT); + } + + st_invalidate_state(ctx, _NEW_BUFFERS); +} + + +/** + * Called via glDrawBuffer. + */ +static void +st_DrawBuffers(GLcontext *ctx, GLsizei count, const GLenum *buffers) +{ + (void) count; + (void) buffers; + check_create_front_buffers(ctx, ctx->DrawBuffer); +} + + +/** + * Called via glReadBuffer. + */ +static void +st_ReadBuffer(GLcontext *ctx, GLenum buffer) +{ + (void) buffer; + check_create_front_buffers(ctx, ctx->ReadBuffer); +} + + void st_init_fbo_functions(struct dd_function_table *functions) { functions->NewFramebuffer = st_new_framebuffer; @@ -467,4 +605,7 @@ void st_init_fbo_functions(struct dd_function_table *functions) /* no longer needed by core Mesa, drivers handle resizes... functions->ResizeBuffers = st_resize_buffers; */ + + functions->DrawBuffers = st_DrawBuffers; + functions->ReadBuffer = st_ReadBuffer; } diff --git a/src/mesa/state_tracker/st_cb_fbo.h b/src/mesa/state_tracker/st_cb_fbo.h index 44fa9fe9a4..bea6eb89c3 100644 --- a/src/mesa/state_tracker/st_cb_fbo.h +++ b/src/mesa/state_tracker/st_cb_fbo.h @@ -30,10 +30,6 @@ #define ST_CB_FBO_H -#define DEFAULT_ACCUM_PIPE_FORMAT PIPE_FORMAT_R16G16B16A16_SNORM - - - /** * Derived renderbuffer class. Just need to add a pointer to the * pipe surface. @@ -44,7 +40,15 @@ struct st_renderbuffer struct pipe_texture *texture; struct pipe_surface *surface; /* temporary view into texture */ enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */ - + GLboolean defined; /**< defined contents? */ + + /** + * Used only when hardware accumulation buffers are not supported. + */ + boolean software; + size_t stride; + void *data; + struct st_texture_object *rtt; /**< GL render to texture's texture */ int rtt_level, rtt_face, rtt_slice; @@ -62,7 +66,7 @@ st_renderbuffer(struct gl_renderbuffer *rb) extern struct gl_renderbuffer * -st_new_renderbuffer_fb(enum pipe_format format, int samples); +st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw); extern void st_init_fbo_functions(struct dd_function_table *functions); diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index 7d7d3823c9..8ceeeabcd3 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -47,10 +47,19 @@ #include "util/u_blit.h" +/** Check if we have a front color buffer and if it's been drawn to. */ static INLINE GLboolean is_front_buffer_dirty(struct st_context *st) { - return st->frontbuffer_status == FRONT_STATUS_DIRTY; + if (st->frontbuffer_status == FRONT_STATUS_DIRTY) { + return GL_TRUE; + } + else { + GLframebuffer *fb = st->ctx->DrawBuffer; + struct st_renderbuffer *strb + = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + return strb && strb->defined; + } } @@ -82,7 +91,7 @@ display_front_buffer(struct st_context *st) void st_flush( struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence ) { - FLUSH_VERTICES(st->ctx, 0); + FLUSH_CURRENT(st->ctx, 0); /* Release any vertex buffers that might potentially be accessed in * successive frames: diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c index 7dd2352739..3bcccd0df4 100644 --- a/src/mesa/state_tracker/st_cb_rasterpos.c +++ b/src/mesa/state_tracker/st_cb_rasterpos.c @@ -194,9 +194,10 @@ new_draw_rastpos_stage(GLcontext *ctx, struct draw_context *draw) rs->stage.destroy = rastpos_destroy; rs->ctx = ctx; - for (i = 0; i < VERT_ATTRIB_MAX; i++) { + for (i = 0; i < Elements(rs->array); i++) { rs->array[i].Size = 4; rs->array[i].Type = GL_FLOAT; + rs->array[i].Format = GL_RGBA; rs->array[i].Stride = 0; rs->array[i].StrideB = 0; rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i]; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 9ce5f3fe84..ccf1a0b563 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -42,13 +42,15 @@ #include "pipe/p_defines.h" #include "pipe/p_inlines.h" #include "util/u_tile.h" + #include "st_context.h" #include "st_cb_bitmap.h" #include "st_cb_readpixels.h" #include "st_cb_fbo.h" #include "st_format.h" #include "st_public.h" - +#include "st_texture.h" +#include "st_inlines.h" /** * Special case for reading stencil buffer. @@ -73,8 +75,11 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, } /* Create a read transfer from the renderbuffer's texture */ - pt = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ, x, y, width, height); + + pt = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, + 0, 0, 0, + PIPE_TRANSFER_READ, x, y, + width, height); /* map the stencil buffer */ stmap = screen->transfer_map(screen, pt); @@ -107,7 +112,7 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, case PIPE_FORMAT_S8Z24_UNORM: if (format == GL_DEPTH_STENCIL) { const uint *src = (uint *) (stmap + srcY * pt->stride); - const GLfloat scale = 1.0 / (0xffffff); + const GLfloat scale = 1.0f / (0xffffff); GLint k; for (k = 0; k < width; k++) { sValues[k] = src[k] >> 24; @@ -125,7 +130,7 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, case PIPE_FORMAT_Z24S8_UNORM: if (format == GL_DEPTH_STENCIL) { const uint *src = (uint *) (stmap + srcY * pt->stride); - const GLfloat scale = 1.0 / (0xffffff); + const GLfloat scale = 1.0f / (0xffffff); GLint k; for (k = 0; k < width; k++) { sValues[k] = src[k] & 0xff; @@ -240,8 +245,10 @@ st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, y = strb->texture->height[0] - y - height; } - trans = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ, x, y, width, height); + trans = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, + 0, 0, 0, + PIPE_TRANSFER_READ, x, y, + width, height); if (!trans) { return GL_FALSE; } @@ -350,7 +357,6 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, if (!dest) return; - /* make sure rendering has completed */ st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); if (format == GL_STENCIL_INDEX || @@ -395,8 +401,10 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, } /* Create a read transfer from the renderbuffer's texture */ - trans = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ, x, y, width, height); + trans = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, + 0, 0, 0, + PIPE_TRANSFER_READ, x, y, + width, height); /* determine bottom-to-top vs. top-to-bottom order */ if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { @@ -437,11 +445,16 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, } } else { - /* untested, but simple: */ + /* XXX: unreachable code -- should be before st_read_stencil_pixels */ assert(format == GL_DEPTH_STENCIL_EXT); for (i = 0; i < height; i++) { + GLuint *zshort = (GLuint *)dst; pipe_get_tile_raw(trans, 0, y, width, 1, dst, 0); y += yStep; + /* Reverse into 24/8 */ + for (j = 0; j < width; j++) { + zshort[j] = (zshort[j] << 8) | (zshort[j] >> 24); + } dst += dstStride; } } @@ -464,7 +477,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, } } else { - /* untested, but simple: */ + /* XXX: unreachable code -- should be before st_read_stencil_pixels */ assert(format == GL_DEPTH_STENCIL_EXT); for (i = 0; i < height; i++) { pipe_get_tile_raw(trans, 0, y, width, 1, dst, 0); diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 8013e69e8e..14b78d1253 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -26,6 +26,7 @@ **************************************************************************/ #include "main/mfeatures.h" +#include "main/bufferobj.h" #if FEATURE_convolve #include "main/convolve.h" #endif @@ -49,12 +50,15 @@ #include "state_tracker/st_public.h" #include "state_tracker/st_texture.h" #include "state_tracker/st_gen_mipmap.h" +#include "state_tracker/st_inlines.h" +#include "state_tracker/st_atom.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" #include "util/u_tile.h" #include "util/u_blit.h" +#include "util/u_surface.h" #define DBG if (0) printf @@ -88,7 +92,7 @@ gl_target_to_pipe(GLenum target) * Return nominal bytes per texel for a compressed format, 0 for non-compressed * format. */ -static int +static GLuint compressed_num_bytes(GLuint mesaFormat) { switch(mesaFormat) { @@ -110,6 +114,25 @@ compressed_num_bytes(GLuint mesaFormat) } +static GLboolean +is_compressed_mesa_format(const struct gl_texture_format *format) +{ + switch (format->MesaFormat) { + case MESA_FORMAT_RGB_DXT1: + case MESA_FORMAT_RGBA_DXT1: + case MESA_FORMAT_RGBA_DXT3: + case MESA_FORMAT_RGBA_DXT5: + case MESA_FORMAT_SRGB_DXT1: + case MESA_FORMAT_SRGBA_DXT1: + case MESA_FORMAT_SRGBA_DXT3: + case MESA_FORMAT_SRGBA_DXT5: + return GL_TRUE; + default: + return GL_FALSE; + } +} + + /** called via ctx->Driver.NewTextureImage() */ static struct gl_texture_image * st_NewTextureImage(GLcontext * ctx) @@ -169,7 +192,7 @@ st_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage) * than COPY_DWORDS would: * XXX Put this in src/mesa/main/imports.h ??? */ -#if defined(i386) || defined(__i386__) +#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) static INLINE void * __memcpy(void *to, const void *from, size_t n) { @@ -227,6 +250,21 @@ logbase2(int n) /** + * Return default texture usage bitmask for the given texture format. + */ +static GLuint +default_usage(enum pipe_format fmt) +{ + GLuint usage = PIPE_TEXTURE_USAGE_SAMPLER; + if (pf_is_depth_stencil(fmt)) + usage |= PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + else + usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; + return usage; +} + + +/** * Allocate a pipe_texture object for the given st_texture_object using * the given st_texture_image to guess the mipmap size/levels. * @@ -250,7 +288,7 @@ guess_and_alloc_texture(struct st_context *st, GLuint width = stImage->base.Width2; /* size w/out border */ GLuint height = stImage->base.Height2; GLuint depth = stImage->base.Depth2; - GLuint i, comp_byte = 0; + GLuint i, usage; enum pipe_format fmt; DBG("%s\n", __FUNCTION__); @@ -308,10 +346,10 @@ guess_and_alloc_texture(struct st_context *st, lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); } - if (stImage->base.IsCompressed) - comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat); - fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat); + + usage = default_usage(fmt); + stObj->pt = st_texture_create(st, gl_target_to_pipe(stObj->base.Target), fmt, @@ -319,11 +357,7 @@ guess_and_alloc_texture(struct st_context *st, width, height, depth, - comp_byte, - ( (pf_is_depth_stencil(fmt) ? - PIPE_TEXTURE_USAGE_DEPTH_STENCIL : - PIPE_TEXTURE_USAGE_RENDER_TARGET) | - PIPE_TEXTURE_USAGE_SAMPLER )); + usage); DBG("%s - success\n", __FUNCTION__); } @@ -368,6 +402,109 @@ strip_texture_border(GLint border, /** + * Try to do texture compression via rendering. If the Gallium driver + * can render into a compressed surface this will allow us to do texture + * compression. + * \return GL_TRUE for success, GL_FALSE for failure + */ +static GLboolean +compress_with_blit(GLcontext * ctx, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *unpack, + struct gl_texture_image *texImage) +{ + const GLuint dstImageOffsets[1] = {0}; + struct st_texture_image *stImage = st_texture_image(texImage); + struct pipe_screen *screen = ctx->st->pipe->screen; + const struct gl_texture_format *mesa_format; + struct pipe_texture templ; + struct pipe_texture *src_tex; + struct pipe_surface *dst_surface; + struct pipe_transfer *tex_xfer; + void *map; + + + if (!stImage->pt) { + /* XXX: Can this happen? Should we assert? */ + return GL_FALSE; + } + + /* get destination surface (in the compressed texture) */ + dst_surface = screen->get_tex_surface(screen, stImage->pt, + stImage->face, stImage->level, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + if (!dst_surface) { + /* can't render into this format (or other problem) */ + return GL_FALSE; + } + + /* Choose format for the temporary RGBA texture image. + */ + mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type); + assert(mesa_format); + if (!mesa_format) + return GL_FALSE; + + /* Create the temporary source texture + */ + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.format = st_mesa_format_to_pipe_format(mesa_format->MesaFormat); + pf_get_block(templ.format, &templ.block); + templ.width[0] = width; + templ.height[0] = height; + templ.depth[0] = 1; + templ.last_level = 0; + templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + src_tex = screen->texture_create(screen, &templ); + + if (!src_tex) + return GL_FALSE; + + /* Put user's tex data into the temporary texture + */ + tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx), src_tex, + 0, 0, 0, /* face, level are zero */ + PIPE_TRANSFER_WRITE, + 0, 0, width, height); /* x, y, w, h */ + map = screen->transfer_map(screen, tex_xfer); + + mesa_format->StoreImage(ctx, 2, GL_RGBA, mesa_format, + map, /* dest ptr */ + 0, 0, 0, /* dest x/y/z offset */ + tex_xfer->stride, /* dest row stride (bytes) */ + dstImageOffsets, /* image offsets (for 3D only) */ + width, height, 1, /* size */ + format, type, /* source format/type */ + pixels, /* source data */ + unpack); /* source data packing */ + + screen->transfer_unmap(screen, tex_xfer); + screen->tex_transfer_destroy(tex_xfer); + + /* copy / compress image */ + util_blit_pixels_tex(ctx->st->blit, + src_tex, /* pipe_texture (src) */ + 0, 0, /* src x0, y0 */ + width, height, /* src x1, y1 */ + dst_surface, /* pipe_surface (dst) */ + xoffset, yoffset, /* dst x0, y0 */ + xoffset + width, /* dst x1 */ + yoffset + height, /* dst y1 */ + 0.0, /* z */ + PIPE_TEX_MIPFILTER_NEAREST); + + pipe_surface_reference(&dst_surface, NULL); + pipe_texture_reference(&src_tex, NULL); + + return GL_TRUE; +} + + +/** * Do glTexImage1/2/3D(). */ static void @@ -381,8 +518,9 @@ st_TexImage(GLcontext * ctx, const struct gl_pixelstore_attrib *unpack, struct gl_texture_object *texObj, struct gl_texture_image *texImage, - GLsizei imageSize, int compressed) + GLsizei imageSize, GLboolean compressed_src) { + struct pipe_screen *screen = ctx->st->pipe->screen; struct st_texture_object *stObj = st_texture_object(texObj); struct st_texture_image *stImage = st_texture_image(texImage); GLint postConvWidth, postConvHeight; @@ -395,8 +533,7 @@ st_TexImage(GLcontext * ctx, /* gallium does not support texture borders, strip it off */ if (border) { - strip_texture_border(border, &width, &height, &depth, - unpack, &unpackNB); + strip_texture_border(border, &width, &height, &depth, unpack, &unpackNB); unpack = &unpackNB; texImage->Width = width; texImage->Height = height; @@ -512,11 +649,12 @@ st_TexImage(GLcontext * ctx, * the expectation that the texture will be set up but nothing * more will be done. This is where those calls return: */ - if (compressed) { + if (compressed_src) { pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels, unpack, "glCompressedTexImage"); - } else { + } + else { pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, format, type, pixels, unpack, "glTexImage"); @@ -524,12 +662,28 @@ st_TexImage(GLcontext * ctx, if (!pixels) return; + /* See if we can do texture compression with a blit/render. + */ + if (!compressed_src && + !ctx->Mesa_DXTn && + is_compressed_mesa_format(texImage->TexFormat) && + screen->is_format_supported(screen, + stImage->pt->format, + stImage->pt->target, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { + if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth, + format, type, pixels, unpack, texImage)) { + goto done; + } + } + if (stImage->pt) { texImage->Data = st_texture_image_map(ctx->st, stImage, 0, PIPE_TRANSFER_WRITE, 0, 0, stImage->base.Width, stImage->base.Height); - dstRowStride = stImage->transfer->stride; + if(stImage->transfer) + dstRowStride = stImage->transfer->stride; } else { /* Allocate regular memory and store the image there temporarily. */ @@ -559,16 +713,16 @@ st_TexImage(GLcontext * ctx, * the blitter to copy. Or, use the hardware to do the format * conversion and copy: */ - if (compressed) { + if (compressed_src) { memcpy(texImage->Data, pixels, imageSize); } else { - GLuint srcImageStride = _mesa_image_image_stride(unpack, width, height, - format, type); - int i; + const GLuint srcImageStride = + _mesa_image_image_stride(unpack, width, height, format, type); + GLint i; const GLubyte *src = (const GLubyte *) pixels; - for (i = 0; i++ < depth;) { + for (i = 0; i < depth; i++) { if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, texImage->TexFormat, @@ -581,9 +735,11 @@ st_TexImage(GLcontext * ctx, _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); } - if (stImage->pt && i < depth) { + if (stImage->pt && i + 1 < depth) { + /* unmap this slice */ st_texture_image_unmap(ctx->st, stImage); - texImage->Data = st_texture_image_map(ctx->st, stImage, i, + /* map next slice of 3D texture */ + texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1, PIPE_TRANSFER_WRITE, 0, 0, stImage->base.Width, stImage->base.Height); @@ -594,7 +750,8 @@ st_TexImage(GLcontext * ctx, _mesa_unmap_teximage_pbo(ctx, unpack); - if (stImage->pt) { +done: + if (stImage->pt && texImage->Data) { st_texture_image_unmap(ctx->st, stImage); texImage->Data = NULL; } @@ -616,9 +773,9 @@ st_TexImage3D(GLcontext * ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - st_TexImage(ctx, 3, target, level, - internalFormat, width, height, depth, border, - format, type, pixels, unpack, texObj, texImage, 0, 0); + st_TexImage(ctx, 3, target, level, internalFormat, width, height, depth, + border, format, type, pixels, unpack, texObj, texImage, + 0, GL_FALSE); } @@ -632,9 +789,8 @@ st_TexImage2D(GLcontext * ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - st_TexImage(ctx, 2, target, level, - internalFormat, width, height, 1, border, - format, type, pixels, unpack, texObj, texImage, 0, 0); + st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border, + format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE); } @@ -648,9 +804,8 @@ st_TexImage1D(GLcontext * ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - st_TexImage(ctx, 1, target, level, - internalFormat, width, 1, 1, border, - format, type, pixels, unpack, texObj, texImage, 0, 0); + st_TexImage(ctx, 1, target, level, internalFormat, width, 1, 1, border, + format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE); } @@ -662,12 +817,96 @@ st_CompressedTexImage2D(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - st_TexImage(ctx, 2, target, level, - internalFormat, width, height, 1, border, - 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1); + st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border, + 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, GL_TRUE); } + +/** + * glGetTexImage() helper: decompress a compressed texture by rendering + * a textured quad. Store the results in the user's buffer. + */ +static void +decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid *pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + struct pipe_screen *screen = ctx->st->pipe->screen; + struct st_texture_image *stImage = st_texture_image(texImage); + const GLuint width = texImage->Width; + const GLuint height = texImage->Height; + struct pipe_surface *dst_surface; + struct pipe_texture *dst_texture; + struct pipe_transfer *tex_xfer; + + /* create temp / dest surface */ + if (!util_create_rgba_surface(screen, width, height, + &dst_texture, &dst_surface)) { + _mesa_problem(ctx, "util_create_rgba_surface() failed " + "in decompress_with_blit()"); + return; + } + + /* blit/render/decompress */ + util_blit_pixels_tex(ctx->st->blit, + stImage->pt, /* pipe_texture (src) */ + 0, 0, /* src x0, y0 */ + width, height, /* src x1, y1 */ + dst_surface, /* pipe_surface (dst) */ + 0, 0, /* dst x0, y0 */ + width, height, /* dst x1, y1 */ + 0.0, /* z */ + PIPE_TEX_MIPFILTER_NEAREST); + + /* map the dst_surface so we can read from it */ + tex_xfer = st_cond_flush_get_tex_transfer(st_context(ctx), + dst_texture, 0, 0, 0, + PIPE_TRANSFER_READ, + 0, 0, width, height); + + pixels = _mesa_map_readpix_pbo(ctx, &ctx->Pack, pixels); + + /* copy/pack data into user buffer */ + if (st_equal_formats(stImage->pt->format, format, type)) { + /* memcpy */ + const uint bytesPerRow = width * pf_get_size(stImage->pt->format); + ubyte *map = screen->transfer_map(screen, tex_xfer); + GLuint row; + for (row = 0; row < height; row++) { + GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, + height, format, type, row, 0); + memcpy(dest, map, bytesPerRow); + map += tex_xfer->stride; + } + screen->transfer_unmap(screen, tex_xfer); + } + else { + /* format translation via floats */ + GLuint row; + for (row = 0; row < height; row++) { + const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ + GLfloat rgba[4 * MAX_WIDTH]; + GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, + height, format, type, row, 0); + + /* get float[4] rgba row from surface */ + pipe_get_tile_rgba(tex_xfer, 0, row, width, 1, rgba); + + _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, + type, dest, &ctx->Pack, transferOps); + } + } + + _mesa_unmap_readpix_pbo(ctx, &ctx->Pack); + + /* destroy the temp / dest surface */ + util_destroy_rgba_surface(dst_texture, dst_surface); +} + + + /** * Need to map texture image into memory before copying image data, * then unmap it. @@ -676,22 +915,36 @@ static void st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, GLenum format, GLenum type, GLvoid * pixels, struct gl_texture_object *texObj, - struct gl_texture_image *texImage, int compressed) + struct gl_texture_image *texImage, GLboolean compressed_dst) { struct st_texture_image *stImage = st_texture_image(texImage); - GLuint dstImageStride = _mesa_image_image_stride(&ctx->Pack, - texImage->Width, - texImage->Height, - format, type); - GLuint depth; - GLuint i; + const GLuint dstImageStride = + _mesa_image_image_stride(&ctx->Pack, texImage->Width, texImage->Height, + format, type); + GLuint depth, i; GLubyte *dest; + if (stImage->pt && + pf_is_compressed(stImage->pt->format) && + !compressed_dst) { + /* Need to decompress the texture. + * We'll do this by rendering a textured quad. + * Note that we only expect RGBA formats (no Z/depth formats). + */ + decompress_with_blit(ctx, target, level, format, type, pixels, + texObj, texImage); + return; + } + /* Map */ if (stImage->pt) { /* Image is stored in hardware format in a buffer managed by the * kernel. Need to explicitly map and unmap it. */ + + st_teximage_flush_before_map(ctx->st, stImage->pt, 0, level, + PIPE_TRANSFER_READ); + texImage->Data = st_texture_image_map(ctx->st, stImage, 0, PIPE_TRANSFER_READ, 0, 0, stImage->base.Width, @@ -715,18 +968,21 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, dest = (GLubyte *) pixels; - for (i = 0; i++ < depth;) { - if (compressed) { + for (i = 0; i < depth; i++) { + if (compressed_dst) { _mesa_get_compressed_teximage(ctx, target, level, dest, texObj, texImage); - } else { + } + else { _mesa_get_teximage(ctx, target, level, format, type, dest, texObj, texImage); } - if (stImage->pt && i < depth) { + if (stImage->pt && i + 1 < depth) { + /* unmap this slice */ st_texture_image_unmap(ctx->st, stImage); - texImage->Data = st_texture_image_map(ctx->st, stImage, i, + /* map next slice of 3D texture */ + texImage->Data = st_texture_image_map(ctx->st, stImage, i + 1, PIPE_TRANSFER_READ, 0, 0, stImage->base.Width, stImage->base.Height); @@ -750,8 +1006,8 @@ st_GetTexImage(GLcontext * ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - st_get_tex_image(ctx, target, level, format, type, pixels, - texObj, texImage, 0); + st_get_tex_image(ctx, target, level, format, type, pixels, texObj, texImage, + GL_FALSE); } @@ -761,17 +1017,14 @@ st_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { - st_get_tex_image(ctx, target, level, 0, 0, pixels, - (struct gl_texture_object *) texObj, - (struct gl_texture_image *) texImage, 1); + st_get_tex_image(ctx, target, level, 0, 0, pixels, texObj, texImage, + GL_TRUE); } static void -st_TexSubimage(GLcontext * ctx, - GLint dims, - GLenum target, GLint level, +st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint width, GLint height, GLint depth, GLenum format, GLenum type, const void *pixels, @@ -779,11 +1032,12 @@ st_TexSubimage(GLcontext * ctx, struct gl_texture_object *texObj, struct gl_texture_image *texImage) { + struct pipe_screen *screen = ctx->st->pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); GLuint dstRowStride; - GLuint srcImageStride = _mesa_image_image_stride(packing, width, height, - format, type); - int i; + const GLuint srcImageStride = + _mesa_image_image_stride(packing, width, height, format, type); + GLint i; const GLubyte *src; DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__, @@ -796,10 +1050,28 @@ st_TexSubimage(GLcontext * ctx, if (!pixels) return; + /* See if we can do texture compression with a blit/render. + */ + if (!ctx->Mesa_DXTn && + is_compressed_mesa_format(texImage->TexFormat) && + screen->is_format_supported(screen, + stImage->pt->format, + stImage->pt->target, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { + if (compress_with_blit(ctx, target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, packing, texImage)) { + goto done; + } + } + /* Map buffer if necessary. Need to lock to prevent other contexts * from uploading the buffer under us. */ if (stImage->pt) { + st_teximage_flush_before_map(ctx->st, stImage->pt, 0, level, + PIPE_TRANSFER_WRITE); texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset, PIPE_TRANSFER_WRITE, xoffset, yoffset, @@ -814,7 +1086,7 @@ st_TexSubimage(GLcontext * ctx, src = (const GLubyte *) pixels; dstRowStride = stImage->transfer->stride; - for (i = 0; i++ < depth;) { + for (i = 0; i < depth; i++) { if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, texImage->TexFormat, texImage->Data, @@ -826,10 +1098,12 @@ st_TexSubimage(GLcontext * ctx, _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); } - if (stImage->pt && i < depth) { - /* map next slice of 3D texture */ + if (stImage->pt && i + 1 < depth) { + /* unmap this slice */ st_texture_image_unmap(ctx->st, stImage); - texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i, + /* map next slice of 3D texture */ + texImage->Data = st_texture_image_map(ctx->st, stImage, + zoffset + i + 1, PIPE_TRANSFER_WRITE, xoffset, yoffset, width, height); @@ -837,88 +1111,74 @@ st_TexSubimage(GLcontext * ctx, } } - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - ctx->Driver.GenerateMipmap(ctx, target, texObj); - } - _mesa_unmap_teximage_pbo(ctx, packing); +done: if (stImage->pt) { st_texture_image_unmap(ctx->st, stImage); texImage->Data = NULL; } + + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + ctx->Driver.GenerateMipmap(ctx, target, texObj); + } } static void -st_TexSubImage3D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) +st_TexSubImage3D(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) { - st_TexSubimage(ctx, 3, target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, packing, texObj, texImage); + st_TexSubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, + width, height, depth, format, type, + pixels, packing, texObj, texImage); } static void -st_TexSubImage2D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) +st_TexSubImage2D(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) { - st_TexSubimage(ctx, 2, target, level, - xoffset, yoffset, 0, - width, height, 1, - format, type, pixels, packing, texObj, texImage); + st_TexSubimage(ctx, 2, target, level, xoffset, yoffset, 0, + width, height, 1, format, type, + pixels, packing, texObj, texImage); } static void -st_TexSubImage1D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) +st_TexSubImage1D(GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) { - st_TexSubimage(ctx, 1, target, level, - xoffset, 0, 0, - width, 1, 1, + st_TexSubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1, format, type, pixels, packing, texObj, texImage); } /** - * Do a CopyTexSubImage operation using a read transfer from the source, a write - * transfer to the destination and get_tile()/put_tile() to access the pixels/texels. + * Do a CopyTexSubImage operation using a read transfer from the source, + * a write transfer to the destination and get_tile()/put_tile() to access + * the pixels/texels. * * Note: srcY=0=TOP of renderbuffer */ static void -fallback_copy_texsubimage(GLcontext *ctx, - GLenum target, - GLint level, +fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, struct st_renderbuffer *strb, struct st_texture_image *stImage, GLenum baseFormat, @@ -937,12 +1197,15 @@ fallback_copy_texsubimage(GLcontext *ctx, srcY = strb->Base.Height - srcY - height; } - src_trans = screen->get_tex_transfer( screen, - strb->texture, - 0, 0, 0, - PIPE_TRANSFER_READ, - srcX, srcY, - width, height); + src_trans = st_cond_flush_get_tex_transfer( st_context(ctx), + strb->texture, + 0, 0, 0, + PIPE_TRANSFER_READ, + srcX, srcY, + width, height); + + st_teximage_flush_before_map(ctx->st, stImage->pt, 0, 0, + PIPE_TRANSFER_WRITE); texDest = st_texture_image_map(ctx->st, stImage, 0, PIPE_TRANSFER_WRITE, destX, destY, width, height); @@ -980,8 +1243,8 @@ fallback_copy_texsubimage(GLcontext *ctx, if (tempSrc && texDest) { const GLint dims = 2; + const GLint dstRowStride = stImage->transfer->stride; struct gl_texture_image *texImage = &stImage->base; - GLint dstRowStride = stImage->transfer->stride; struct gl_pixelstore_attrib unpack = ctx->DefaultPacking; if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { @@ -1054,8 +1317,12 @@ st_copy_texsubimage(GLcontext *ctx, GLboolean use_fallback = GL_TRUE; GLboolean matching_base_formats; - /* any rendering in progress must complete before we grab the fb image */ - st_finish(ctx->st); + /* any rendering in progress must flushed before we grab the fb image */ + st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + + /* make sure finalize_textures has been called? + */ + if (0) st_validate_state(ctx->st); /* determine if copying depth or color data */ if (texBaseFormat == GL_DEPTH_COMPONENT || @@ -1070,6 +1337,39 @@ st_copy_texsubimage(GLcontext *ctx, strb = st_renderbuffer(fb->_ColorReadBuffer); } + if (!strb || !strb->surface || !stImage->pt) { + debug_printf("%s: null strb or stImage\n", __FUNCTION__); + return; + } + + if (srcX < 0) { + width -= -srcX; + destX += -srcX; + srcX = 0; + } + + if (srcY < 0) { + height -= -srcY; + destY += -srcY; + srcY = 0; + } + + if (destX < 0) { + width -= -destX; + srcX += -destX; + destX = 0; + } + + if (destY < 0) { + height -= -destY; + srcY += -destY; + destY = 0; + } + + if (width < 0 || height < 0) + return; + + assert(strb); assert(strb->surface); assert(stImage->pt); @@ -1095,7 +1395,6 @@ st_copy_texsubimage(GLcontext *ctx, if (src_format == dest_format && !do_flip) { /* use surface_copy() / blit */ - dest_surface = screen->get_tex_surface(screen, stImage->pt, stImage->face, stImage->level, destZ, @@ -1122,7 +1421,7 @@ st_copy_texsubimage(GLcontext *ctx, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { /* draw textured quad to do the copy */ - int srcY0, srcY1; + GLint srcY0, srcY1; dest_surface = screen->get_tex_surface(screen, stImage->pt, stImage->face, stImage->level, @@ -1179,11 +1478,6 @@ st_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texObj, target, level); -#if 0 - if (border) - goto fail; -#endif - /* Setup or redefine the texture object, texture and texture * image. Don't populate yet. */ @@ -1274,8 +1568,8 @@ calculate_first_last_level(struct st_texture_object *stObj) * and having firstLevel and lastLevel as signed prevents the need for * extra sign checks. */ - int firstLevel; - int lastLevel; + GLint firstLevel; + GLint lastLevel; /* Yes, this looks overly complicated, but it's all needed. */ @@ -1329,16 +1623,21 @@ copy_image_data_to_texture(struct st_context *st, /* More straightforward upload. */ - st_texture_image_data(st->pipe, - stObj->pt, - stImage->face, - dstLevel, - stImage->base.Data, - stImage->base.RowStride * - stObj->pt->block.size, - stImage->base.RowStride * - stImage->base.Height * - stObj->pt->block.size); + + st_teximage_flush_before_map(st, stObj->pt, stImage->face, dstLevel, + PIPE_TRANSFER_WRITE); + + + st_texture_image_data(st, + stObj->pt, + stImage->face, + dstLevel, + stImage->base.Data, + stImage->base.RowStride * + stObj->pt->block.size, + stImage->base.RowStride * + stImage->base.Height * + stObj->pt->block.size); _mesa_align_free(stImage->base.Data); stImage->base.Data = NULL; } @@ -1360,9 +1659,7 @@ st_finalize_texture(GLcontext *ctx, { struct st_texture_object *stObj = st_texture_object(tObj); const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; - int comp_byte = 0; - int cpp; - GLuint face; + GLuint cpp, face; struct st_texture_image *firstImage; *needFlush = GL_FALSE; @@ -1384,14 +1681,12 @@ st_finalize_texture(GLcontext *ctx, if (firstImage->pt && firstImage->pt != stObj->pt && firstImage->pt->last_level >= stObj->lastLevel) { - pipe_texture_reference(&stObj->pt, firstImage->pt); } /* FIXME: determine format block instead of cpp */ if (firstImage->base.IsCompressed) { - comp_byte = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat); - cpp = comp_byte; + cpp = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat); } else { cpp = firstImage->base.TexFormat->TexelBytes; @@ -1409,8 +1704,9 @@ st_finalize_texture(GLcontext *ctx, stObj->pt->width[0] != firstImage->base.Width2 || stObj->pt->height[0] != firstImage->base.Height2 || stObj->pt->depth[0] != firstImage->base.Depth2 || - stObj->pt->block.size/stObj->pt->block.width != cpp || /* Nominal bytes per pixel */ - stObj->pt->compressed != firstImage->base.IsCompressed) { + /* Nominal bytes per pixel: */ + stObj->pt->block.size / stObj->pt->block.width != cpp) + { pipe_texture_reference(&stObj->pt, NULL); ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER; } @@ -1421,6 +1717,8 @@ st_finalize_texture(GLcontext *ctx, if (!stObj->pt) { const enum pipe_format fmt = st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat); + GLuint usage = default_usage(fmt); + stObj->pt = st_texture_create(ctx->st, gl_target_to_pipe(stObj->base.Target), fmt, @@ -1428,11 +1726,7 @@ st_finalize_texture(GLcontext *ctx, firstImage->base.Width2, firstImage->base.Height2, firstImage->base.Depth2, - comp_byte, - ( (pf_is_depth_stencil(fmt) ? - PIPE_TEXTURE_USAGE_DEPTH_STENCIL : - PIPE_TEXTURE_USAGE_RENDER_TARGET) | - PIPE_TEXTURE_USAGE_SAMPLER )); + usage); if (!stObj->pt) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index b27274725f..92ddffc014 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -177,6 +177,12 @@ struct st_context *st_create_context(struct pipe_context *pipe, ctx = _mesa_create_context(visual, shareCtx, &funcs, NULL); + /* XXX: need a capability bit in gallium to query if the pipe + * driver prefers DP4 or MUL/MAD for vertex transformation. + */ + if (debug_get_bool_option("MESA_MVP_DP4", FALSE)) + _mesa_set_mvp_with_dp4( ctx, GL_TRUE ); + return st_create_context_priv(ctx, pipe); } @@ -227,6 +233,7 @@ void st_destroy_context( struct st_context *st ) struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; GLcontext *ctx = st->ctx; + GLuint i; /* need to unbind and destroy CSO objects before anything else */ cso_release_all(st->cso_context); @@ -234,6 +241,12 @@ void st_destroy_context( struct st_context *st ) st_reference_fragprog(st, &st->fp, NULL); st_reference_vertprog(st, &st->vp, NULL); + /* release framebuffer surfaces */ + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { + pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL); + } + pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL); + _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache); _vbo_DestroyContext(st->ctx); @@ -250,9 +263,10 @@ void st_destroy_context( struct st_context *st ) } -void st_make_current(struct st_context *st, - struct st_framebuffer *draw, - struct st_framebuffer *read) +GLboolean +st_make_current(struct st_context *st, + struct st_framebuffer *draw, + struct st_framebuffer *read) { /* Call this periodically to detect when the user has begun using * GL rendering from multiple threads. @@ -261,7 +275,8 @@ void st_make_current(struct st_context *st, if (st) { GLboolean firstTime = st->ctx->FirstTimeCurrent; - _mesa_make_current(st->ctx, &draw->Base, &read->Base); + if(!_mesa_make_current(st->ctx, &draw->Base, &read->Base)) + return GL_FALSE; /* Need to initialize viewport here since draw->Base->Width/Height * will still be zero at this point. * This could be improved, but would require rather extensive work @@ -273,12 +288,19 @@ void st_make_current(struct st_context *st, _mesa_set_scissor(st->ctx, 0, 0, w, h); } + return GL_TRUE; } else { - _mesa_make_current(NULL, NULL, NULL); + return _mesa_make_current(NULL, NULL, NULL); } } +struct st_context *st_get_current(void) +{ + GET_CURRENT_CONTEXT(ctx); + + return (ctx == NULL) ? NULL : ctx->st; +} void st_copy_context_state(struct st_context *dst, struct st_context *src, diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index ae8c2978bf..18adb35e87 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -45,6 +45,7 @@ struct blit_state; struct bitmap_cache; +/** XXX we'd like to get rid of these */ #define FRONT_STATUS_UNDEFINED 0 #define FRONT_STATUS_DIRTY 1 #define FRONT_STATUS_COPY_OF_BACK 2 @@ -111,22 +112,15 @@ struct st_context struct gl_fragment_program *fragment_program; } cb; - GLuint frontbuffer_status; /**< one of FRONT_STATUS_ */ + GLuint frontbuffer_status; /**< one of FRONT_STATUS_ (XXX to be removed) */ char vendor[100]; char renderer[100]; - /* State to be validated: - */ - struct st_tracked_state **atoms; - GLuint nr_atoms; - struct st_state_flags dirty; GLboolean missing_textures; - GLfloat polygon_offset_scale; /* ?? */ - /** Mapping from VERT_RESULT_x to post-transformed vertex slot */ const GLuint *vertex_result_to_slot; diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 225541a30b..8e036223c6 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -159,12 +159,21 @@ static GLuint fixed_types[4] = { * Return a PIPE_FORMAT_x for the given GL datatype and size. */ GLuint -st_pipe_vertex_format(GLenum type, GLuint size, GLboolean normalized) +st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, + GLboolean normalized) { assert((type >= GL_BYTE && type <= GL_DOUBLE) || type == GL_FIXED); assert(size >= 1); assert(size <= 4); + assert(format == GL_RGBA || format == GL_BGRA); + + if (format == GL_BGRA) { + /* this is an odd-ball case */ + assert(type == GL_UNSIGNED_BYTE); + assert(normalized); + return PIPE_FORMAT_B8G8R8A8_UNORM; + } if (normalized) { switch (type) { @@ -392,6 +401,7 @@ setup_interleaved_attribs(GLcontext *ctx, velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, arrays[mesaAttr]->Size, + arrays[mesaAttr]->Format, arrays[mesaAttr]->Normalized); assert(velements[attr].src_format); } @@ -479,6 +489,7 @@ setup_non_interleaved_attribs(GLcontext *ctx, velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, arrays[mesaAttr]->Size, + arrays[mesaAttr]->Format, arrays[mesaAttr]->Normalized); assert(velements[attr].src_format); } diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h index da04fce8e2..dcfe7e1536 100644 --- a/src/mesa/state_tracker/st_draw.h +++ b/src/mesa/state_tracker/st_draw.h @@ -62,7 +62,8 @@ st_feedback_draw_vbo(GLcontext *ctx, /* Internal function: */ extern GLuint -st_pipe_vertex_format(GLenum type, GLuint size, GLboolean normalized); +st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, + GLboolean normalized); /** diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index e533afd051..2712c131c0 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -178,6 +178,7 @@ st_feedback_draw_vbo(GLcontext *ctx, velements[attr].src_format = st_pipe_vertex_format(arrays[mesaAttr]->Type, arrays[mesaAttr]->Size, + arrays[mesaAttr]->Format, arrays[mesaAttr]->Normalized); assert(velements[attr].src_format); @@ -196,13 +197,10 @@ st_feedback_draw_vbo(GLcontext *ctx, draw_set_vertex_elements(draw, vp->num_inputs, velements); if (ib) { - unsigned indexSize; struct gl_buffer_object *bufobj = ib->obj; - struct st_buffer_object *stobj = st_buffer_object(bufobj); + unsigned indexSize; void *map; - index_buffer_handle = stobj->buffer; - switch (ib->type) { case GL_UNSIGNED_INT: indexSize = 4; @@ -215,9 +213,19 @@ st_feedback_draw_vbo(GLcontext *ctx, return; } - map = pipe_buffer_map(pipe->screen, index_buffer_handle, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer(draw, indexSize, map); + if (bufobj && bufobj->Name) { + struct st_buffer_object *stobj = st_buffer_object(bufobj); + + index_buffer_handle = stobj->buffer; + + map = pipe_buffer_map(pipe->screen, index_buffer_handle, + PIPE_BUFFER_USAGE_CPU_READ); + + draw_set_mapped_element_buffer(draw, indexSize, map); + } + else { + draw_set_mapped_element_buffer(draw, indexSize, (void *) ib->ptr); + } } else { /* no index/element buffer */ @@ -252,7 +260,7 @@ st_feedback_draw_vbo(GLcontext *ctx, draw_set_mapped_vertex_buffer(draw, i, NULL); } } - if (ib) { + if (index_buffer_handle) { pipe_buffer_unmap(pipe->screen, index_buffer_handle); draw_set_mapped_element_buffer(draw, 0, NULL); } diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 8f6be50774..8ed1211db6 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -138,6 +138,7 @@ void st_init_extensions(struct st_context *st) /* * Extensions that are supported by all Gallium drivers: */ + ctx->Extensions.ARB_copy_buffer = GL_TRUE; ctx->Extensions.ARB_multisample = GL_TRUE; ctx->Extensions.ARB_fragment_program = GL_TRUE; ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */ @@ -167,6 +168,9 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_texture_env_combine = GL_TRUE; ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; ctx->Extensions.EXT_texture_lod_bias = GL_TRUE; + ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; + + ctx->Extensions.APPLE_vertex_array_object = GL_TRUE; ctx->Extensions.NV_blend_square = GL_TRUE; ctx->Extensions.NV_texgen_reflection = GL_TRUE; diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c index 9e2d60c926..b243c249e3 100644 --- a/src/mesa/state_tracker/st_format.c +++ b/src/mesa/state_tracker/st_format.c @@ -392,7 +392,7 @@ default_depth_format(struct pipe_screen *screen, * or PIPE_TEXTURE_USAGE_SAMPLER */ enum pipe_format -st_choose_format(struct pipe_context *pipe, GLint internalFormat, +st_choose_format(struct pipe_context *pipe, GLenum internalFormat, enum pipe_texture_target target, unsigned tex_usage) { struct pipe_screen *screen = pipe->screen; @@ -594,9 +594,13 @@ st_choose_format(struct pipe_context *pipe, GLint internalFormat, static GLboolean -is_stencil_format(GLenum format) +is_depth_or_stencil_format(GLenum internalFormat) { - switch (format) { + switch (internalFormat) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: @@ -614,10 +618,10 @@ is_stencil_format(GLenum format) * Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces. */ enum pipe_format -st_choose_renderbuffer_format(struct pipe_context *pipe, GLint internalFormat) +st_choose_renderbuffer_format(struct pipe_context *pipe, GLenum internalFormat) { uint usage; - if (is_stencil_format(internalFormat)) + if (is_depth_or_stencil_format(internalFormat)) usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; else usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; @@ -716,3 +720,23 @@ st_ChooseTextureFormat(GLcontext *ctx, GLint internalFormat, return translate_gallium_format_to_mesa_format(pFormat); } + + +/** + * Test if a gallium format is equivalent to a GL format/type. + */ +GLboolean +st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type) +{ + switch (pFormat) { + case PIPE_FORMAT_R8G8B8A8_UNORM: + return format == GL_RGBA && type == GL_UNSIGNED_BYTE; + case PIPE_FORMAT_B8G8R8A8_UNORM: + return format == GL_BGRA && type == GL_UNSIGNED_BYTE; + case PIPE_FORMAT_R5G6B5_UNORM: + return format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5; + /* XXX more combos... */ + default: + return GL_FALSE; + } +} diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h index 3f5ac3201b..9d9e02fe9b 100644 --- a/src/mesa/state_tracker/st_format.h +++ b/src/mesa/state_tracker/st_format.h @@ -64,11 +64,11 @@ st_mesa_format_to_pipe_format(GLuint mesaFormat); extern enum pipe_format -st_choose_format(struct pipe_context *pipe, GLint internalFormat, +st_choose_format(struct pipe_context *pipe, GLenum internalFormat, enum pipe_texture_target target, unsigned tex_usage); extern enum pipe_format -st_choose_renderbuffer_format(struct pipe_context *pipe, GLint internalFormat); +st_choose_renderbuffer_format(struct pipe_context *pipe, GLenum internalFormat); extern const struct gl_texture_format * @@ -76,4 +76,8 @@ st_ChooseTextureFormat(GLcontext * ctx, GLint internalFormat, GLenum format, GLenum type); +extern GLboolean +st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type); + + #endif /* ST_CB_TEXIMAGE_H */ diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index daaad65cca..7072cbe62c 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -58,25 +58,25 @@ st_create_framebuffer( const __GLcontextModes *visual, _mesa_initialize_framebuffer(&stfb->Base, visual); - { - /* fake frontbuffer */ - /* XXX allocation should only happen in the unusual case - it's actually needed */ - struct gl_renderbuffer *rb - = st_new_renderbuffer_fb(colorFormat, samples); - _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb); - } - if (visual->doubleBufferMode) { struct gl_renderbuffer *rb - = st_new_renderbuffer_fb(colorFormat, samples); + = st_new_renderbuffer_fb(colorFormat, samples, FALSE); _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb); } + else { + /* Only allocate front buffer right now if we're single buffered. + * If double-buffered, allocate front buffer on demand later. + * See check_create_front_buffers(). + */ + struct gl_renderbuffer *rb + = st_new_renderbuffer_fb(colorFormat, samples, FALSE); + _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb); + } if (depthFormat == stencilFormat && depthFormat != PIPE_FORMAT_NONE) { /* combined depth/stencil buffer */ struct gl_renderbuffer *depthStencilRb - = st_new_renderbuffer_fb(depthFormat, samples); + = st_new_renderbuffer_fb(depthFormat, samples, FALSE); /* note: bind RB to two attachment points */ _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthStencilRb); _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, depthStencilRb); @@ -87,34 +87,35 @@ st_create_framebuffer( const __GLcontextModes *visual, if (visual->depthBits == 32) { /* 32-bit depth buffer */ struct gl_renderbuffer *depthRb - = st_new_renderbuffer_fb(depthFormat, samples); + = st_new_renderbuffer_fb(depthFormat, samples, FALSE); _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb); } else if (visual->depthBits == 24) { /* 24-bit depth buffer, ignore stencil bits */ struct gl_renderbuffer *depthRb - = st_new_renderbuffer_fb(depthFormat, samples); + = st_new_renderbuffer_fb(depthFormat, samples, FALSE); _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb); } else if (visual->depthBits > 0) { /* 16-bit depth buffer */ struct gl_renderbuffer *depthRb - = st_new_renderbuffer_fb(depthFormat, samples); + = st_new_renderbuffer_fb(depthFormat, samples, FALSE); _mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, depthRb); } if (visual->stencilBits > 0) { /* 8-bit stencil */ struct gl_renderbuffer *stencilRb - = st_new_renderbuffer_fb(stencilFormat, samples); + = st_new_renderbuffer_fb(stencilFormat, samples, FALSE); _mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, stencilRb); } } if (visual->accumRedBits > 0) { /* 16-bit/channel accum */ + /* TODO: query the pipe screen for accumulation buffer format support */ struct gl_renderbuffer *accumRb - = st_new_renderbuffer_fb(DEFAULT_ACCUM_PIPE_FORMAT, 0); /* XXX accum isn't multisampled right? */ + = st_new_renderbuffer_fb(PIPE_FORMAT_R16G16B16A16_SNORM, 0, TRUE); _mesa_add_renderbuffer(&stfb->Base, BUFFER_ACCUM, accumRb); } @@ -293,6 +294,115 @@ st_notify_swapbuffers(struct st_framebuffer *stfb) } +/** + * Swap the front/back color buffers. Exchange the front/back pointers + * and update some derived state. + * No need to call st_notify_swapbuffers() first. + * + * For a single-buffered framebuffer, no swap occurs, but we still return + * the pointer(s) to the front color buffer(s). + * + * \param front_left returns pointer to front-left renderbuffer after swap + * \param front_right returns pointer to front-right renderbuffer after swap + */ +void +st_swapbuffers(struct st_framebuffer *stfb, + struct pipe_surface **front_left, + struct pipe_surface **front_right) +{ + struct gl_framebuffer *fb = &stfb->Base; + + GET_CURRENT_CONTEXT(ctx); + + if (ctx && ctx->DrawBuffer == &stfb->Base) { + st_flush( ctx->st, + PIPE_FLUSH_RENDER_CACHE | + PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_FRAME, + NULL ); + } + + if (!fb->Visual.doubleBufferMode) { + /* single buffer mode - return pointers to front surfaces */ + if (front_left) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + *front_left = strb->surface; + } + if (front_right) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer); + *front_right = strb ? strb->surface : NULL; + } + return; + } + + /* swap left buffers */ + if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer && + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) { + struct gl_renderbuffer *rbTemp; + rbTemp = fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; + fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer = + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer; + fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer = rbTemp; + if (front_left) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + *front_left = strb->surface; + } + /* mark back buffer contents as undefined */ + { + struct st_renderbuffer *back = + st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); + back->defined = GL_FALSE; + } + } + else { + /* no front buffer, display the back buffer */ + if (front_left) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); + *front_left = strb->surface; + } + } + + /* swap right buffers (for stereo) */ + if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer && + fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) { + struct gl_renderbuffer *rbTemp; + rbTemp = fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer; + fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer = + fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer; + fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer = rbTemp; + if (front_right) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer); + *front_right = strb->surface; + } + /* mark back buffer contents as undefined */ + { + struct st_renderbuffer *back = + st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); + back->defined = GL_FALSE; + } + } + else { + /* no front right buffer, display back right buffer (if exists) */ + if (front_right) { + struct st_renderbuffer *strb = + st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer); + *front_right = strb ? strb->surface : NULL; + } + } + + /* Update the _ColorDrawBuffers[] array and _ColorReadBuffer pointer */ + _mesa_update_framebuffer(ctx); + + /* Make sure we draw into the new back surface */ + st_invalidate_state(ctx, _NEW_BUFFERS); +} + + void *st_framebuffer_private( struct st_framebuffer *stfb ) { return stfb->Private; diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 9cc2176d5e..dc6d77825f 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -47,6 +47,7 @@ #include "st_program.h" #include "st_texture.h" #include "st_cb_texture.h" +#include "st_inlines.h" /** @@ -86,7 +87,7 @@ st_render_mipmap(struct st_context *st, assert(target != GL_TEXTURE_3D); /* not done yet */ /* check if we can render in the texture's format */ - if (!screen->is_format_supported(screen, pt->format, target, + if (!screen->is_format_supported(screen, pt->format, pt->target, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { return FALSE; } @@ -122,27 +123,34 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target, struct pipe_transfer *srcTrans, *dstTrans; const ubyte *srcData; ubyte *dstData; + int srcStride, dstStride; - srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice, - PIPE_TRANSFER_READ, 0, 0, - pt->width[srcLevel], - pt->height[srcLevel]); - dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice, - PIPE_TRANSFER_WRITE, 0, 0, - pt->width[dstLevel], - pt->height[dstLevel]); + srcTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face, + srcLevel, zslice, + PIPE_TRANSFER_READ, 0, 0, + pt->width[srcLevel], + pt->height[srcLevel]); + + dstTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face, + dstLevel, zslice, + PIPE_TRANSFER_WRITE, 0, 0, + pt->width[dstLevel], + pt->height[dstLevel]); srcData = (ubyte *) screen->transfer_map(screen, srcTrans); dstData = (ubyte *) screen->transfer_map(screen, dstTrans); + srcStride = srcTrans->stride / srcTrans->block.size; + dstStride = dstTrans->stride / dstTrans->block.size; + _mesa_generate_mipmap_level(target, datatype, comps, 0 /*border*/, pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel], srcData, - srcTrans->stride, /* stride in bytes */ + srcStride, /* stride in texels */ pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel], dstData, - dstTrans->stride); /* stride in bytes */ + dstStride); /* stride in texels */ screen->transfer_unmap(screen, srcTrans); screen->transfer_unmap(screen, dstTrans); diff --git a/src/mesa/state_tracker/st_inlines.h b/src/mesa/state_tracker/st_inlines.h new file mode 100644 index 0000000000..a41cfeb96f --- /dev/null +++ b/src/mesa/state_tracker/st_inlines.h @@ -0,0 +1,154 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * Functions for checking if buffers/textures are referenced when we need + * to read/write from/to them. Flush when needed. + */ + +#ifndef ST_INLINES_H +#define ST_INLINES_H + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_defines.h" +#include "pipe/p_inlines.h" +#include "pipe/p_state.h" + +#include "st_context.h" +#include "st_texture.h" +#include "st_public.h" + +static INLINE struct pipe_transfer * +st_cond_flush_get_tex_transfer(struct st_context *st, + struct pipe_texture *pt, + unsigned int face, + unsigned int level, + unsigned int zslice, + enum pipe_transfer_usage usage, + unsigned int x, unsigned int y, + unsigned int w, unsigned int h) +{ + struct pipe_screen *screen = st->pipe->screen; + + st_teximage_flush_before_map(st, pt, face, level, usage); + return screen->get_tex_transfer(screen, pt, face, level, zslice, usage, + x, y, w, h); +} + +static INLINE struct pipe_transfer * +st_no_flush_get_tex_transfer(struct st_context *st, + struct pipe_texture *pt, + unsigned int face, + unsigned int level, + unsigned int zslice, + enum pipe_transfer_usage usage, + unsigned int x, unsigned int y, + unsigned int w, unsigned int h) +{ + struct pipe_screen *screen = st->pipe->screen; + + return screen->get_tex_transfer(screen, pt, face, level, + zslice, usage, x, y, w, h); +} + +static INLINE void * +st_cond_flush_pipe_buffer_map(struct st_context *st, + struct pipe_buffer *buf, + unsigned int map_flags) +{ + struct pipe_context *pipe = st->pipe; + unsigned int referenced = pipe->is_buffer_referenced(pipe, buf); + + if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) || + (map_flags & PIPE_BUFFER_USAGE_CPU_WRITE))) + st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL); + + return pipe_buffer_map(pipe->screen, buf, map_flags); +} + +static INLINE void * +st_no_flush_pipe_buffer_map(struct st_context *st, + struct pipe_buffer *buf, + unsigned int map_flags) +{ + return pipe_buffer_map(st->pipe->screen, buf, map_flags); +} + + +static INLINE void +st_cond_flush_pipe_buffer_write(struct st_context *st, + struct pipe_buffer *buf, + unsigned int offset, + unsigned int size, + const void * data) +{ + struct pipe_context *pipe = st->pipe; + + if (pipe->is_buffer_referenced(pipe, buf)) + st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL); + + pipe_buffer_write(pipe->screen, buf, offset, size, data); +} + +static INLINE void +st_no_flush_pipe_buffer_write(struct st_context *st, + struct pipe_buffer *buf, + unsigned int offset, + unsigned int size, + const void * data) +{ + pipe_buffer_write(st->pipe->screen, buf, offset, size, data); +} + +static INLINE void +st_cond_flush_pipe_buffer_read(struct st_context *st, + struct pipe_buffer *buf, + unsigned int offset, + unsigned int size, + void * data) +{ + struct pipe_context *pipe = st->pipe; + + if (pipe->is_buffer_referenced(pipe, buf) & PIPE_REFERENCED_FOR_WRITE) + st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL); + + pipe_buffer_read(pipe->screen, buf, offset, size, data); +} + +static INLINE void +st_no_flush_pipe_buffer_read(struct st_context *st, + struct pipe_buffer *buf, + unsigned int offset, + unsigned int size, + void * data) +{ + pipe_buffer_read(st->pipe->screen, buf, offset, size, data); +} + +#endif + diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index ffa607dd87..43c9afccc3 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -275,8 +275,8 @@ compile_instruction( /* swizzle (ext swizzle also depends on negation) */ { GLuint swz[4]; - GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE && - inst->SrcReg[i].NegateBase != NEGATE_XYZW); + GLboolean extended = (inst->SrcReg[i].Negate != NEGATE_NONE && + inst->SrcReg[i].Negate != NEGATE_XYZW); for( j = 0; j < 4; j++ ) { swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j ); if (swz[j] > SWIZZLE_W) @@ -296,20 +296,20 @@ compile_instruction( } } - if( inst->SrcReg[i].NegateBase == NEGATE_XYZW ) { + if( inst->SrcReg[i].Negate == NEGATE_XYZW ) { fullsrc->SrcRegister.Negate = 1; } - else if( inst->SrcReg[i].NegateBase != NEGATE_NONE ) { - if( inst->SrcReg[i].NegateBase & NEGATE_X ) { + else if( inst->SrcReg[i].Negate != NEGATE_NONE ) { + if( inst->SrcReg[i].Negate & NEGATE_X ) { fullsrc->SrcRegisterExtSwz.NegateX = 1; } - if( inst->SrcReg[i].NegateBase & NEGATE_Y ) { + if( inst->SrcReg[i].Negate & NEGATE_Y ) { fullsrc->SrcRegisterExtSwz.NegateY = 1; } - if( inst->SrcReg[i].NegateBase & NEGATE_Z ) { + if( inst->SrcReg[i].Negate & NEGATE_Z ) { fullsrc->SrcRegisterExtSwz.NegateZ = 1; } - if( inst->SrcReg[i].NegateBase & NEGATE_W ) { + if( inst->SrcReg[i].Negate & NEGATE_W ) { fullsrc->SrcRegisterExtSwz.NegateW = 1; } } @@ -318,10 +318,6 @@ compile_instruction( fullsrc->SrcRegisterExtMod.Absolute = 1; } - if( inst->SrcReg[i].NegateAbs ) { - fullsrc->SrcRegisterExtMod.Negate = 1; - } - if( inst->SrcReg[i].RelAddr ) { fullsrc->SrcRegister.Indirect = 1; diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 6348e83d8a..72ca852458 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -49,26 +49,12 @@ #include "cso_cache/cso_context.h" -#define ST_MAX_SHADER_TOKENS 4096 +#define ST_MAX_SHADER_TOKENS (8 * 1024) #define TGSI_DEBUG 0 -/** XXX we should use the version of this from u_memory.h but including - * that header causes symbol collisions. - */ -static INLINE void * -mem_dup(const void *src, uint size) -{ - void *dup = _mesa_malloc(size); - if (dup) - _mesa_memcpy(dup, src, size); - return dup; -} - - - /** * Translate a Mesa vertex shader into a TGSI shader. * \param outputMapping to map vertex program output registers (VERT_RESULT_x) @@ -84,7 +70,7 @@ st_translate_vertex_program(struct st_context *st, const ubyte *outputSemanticIndex) { struct pipe_context *pipe = st->pipe; - struct tgsi_token tokens[ST_MAX_SHADER_TOKENS]; + struct tgsi_token *tokens; GLuint defaultOutputMapping[VERT_RESULT_MAX]; struct pipe_shader_state vs; GLuint attr, i; @@ -102,6 +88,13 @@ st_translate_vertex_program(struct st_context *st, GLbitfield input_flags[MAX_PROGRAM_INPUTS]; GLbitfield output_flags[MAX_PROGRAM_OUTPUTS]; + tokens = (struct tgsi_token *)MALLOC(ST_MAX_SHADER_TOKENS * sizeof *tokens); + if(!tokens) { + /* FIXME: propagate error to the caller */ + assert(0); + return; + } + memset(&vs, 0, sizeof(vs)); memset(input_flags, 0, sizeof(input_flags)); memset(output_flags, 0, sizeof(output_flags)); @@ -169,6 +162,14 @@ st_translate_vertex_program(struct st_context *st, case VERT_ATTRIB_GENERIC5: case VERT_ATTRIB_GENERIC6: case VERT_ATTRIB_GENERIC7: + case VERT_ATTRIB_GENERIC8: + case VERT_ATTRIB_GENERIC9: + case VERT_ATTRIB_GENERIC10: + case VERT_ATTRIB_GENERIC11: + case VERT_ATTRIB_GENERIC12: + case VERT_ATTRIB_GENERIC13: + case VERT_ATTRIB_GENERIC14: + case VERT_ATTRIB_GENERIC15: assert(attr < VERT_ATTRIB_MAX); vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; vs_input_semantic_index[slot] = num_generic++; @@ -289,9 +290,6 @@ st_translate_vertex_program(struct st_context *st, } } - assert(vs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION); - - if (outputMapping) { /* find max output slot referenced to compute vs_num_outputs */ GLuint maxSlot = 0; @@ -339,7 +337,9 @@ st_translate_vertex_program(struct st_context *st, assert(num_tokens < ST_MAX_SHADER_TOKENS); vs.tokens = (struct tgsi_token *) - mem_dup(tokens, num_tokens * sizeof(tokens[0])); + _mesa_realloc(tokens, + ST_MAX_SHADER_TOKENS * sizeof *tokens, + num_tokens * sizeof *tokens); stvp->num_inputs = vs_num_inputs; stvp->state = vs; /* struct copy */ @@ -367,7 +367,7 @@ st_translate_fragment_program(struct st_context *st, const GLuint inputMapping[]) { struct pipe_context *pipe = st->pipe; - struct tgsi_token tokens[ST_MAX_SHADER_TOKENS]; + struct tgsi_token *tokens; GLuint outputMapping[FRAG_RESULT_MAX]; GLuint defaultInputMapping[FRAG_ATTRIB_MAX]; struct pipe_shader_state fs; @@ -387,6 +387,13 @@ st_translate_fragment_program(struct st_context *st, GLbitfield input_flags[MAX_PROGRAM_INPUTS]; GLbitfield output_flags[MAX_PROGRAM_OUTPUTS]; + tokens = (struct tgsi_token *)MALLOC(ST_MAX_SHADER_TOKENS * sizeof *tokens); + if(!tokens) { + /* FIXME: propagate error to the caller */ + assert(0); + return; + } + memset(&fs, 0, sizeof(fs)); memset(input_flags, 0, sizeof(input_flags)); memset(output_flags, 0, sizeof(output_flags)); @@ -484,14 +491,14 @@ st_translate_fragment_program(struct st_context *st, /* handled above */ assert(0); break; - case FRAG_RESULT_COLOR: + default: + assert(attr == FRAG_RESULT_COLOR || + (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; fs_output_semantic_index[fs_num_outputs] = numColors; outputMapping[attr] = fs_num_outputs; numColors++; break; - default: - assert(0); } output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr]; @@ -528,7 +535,9 @@ st_translate_fragment_program(struct st_context *st, assert(num_tokens < ST_MAX_SHADER_TOKENS); fs.tokens = (struct tgsi_token *) - mem_dup(tokens, num_tokens * sizeof(tokens[0])); + _mesa_realloc(tokens, + ST_MAX_SHADER_TOKENS * sizeof *tokens, + num_tokens * sizeof *tokens); stfp->state = fs; /* struct copy */ stfp->driver_shader = pipe->create_fs_state(pipe, &fs); diff --git a/src/mesa/state_tracker/st_public.h b/src/mesa/state_tracker/st_public.h index 030314372f..04d3a3d7c2 100644 --- a/src/mesa/state_tracker/st_public.h +++ b/src/mesa/state_tracker/st_public.h @@ -91,9 +91,11 @@ void *st_framebuffer_private( struct st_framebuffer *stfb ); void st_unreference_framebuffer( struct st_framebuffer *stfb ); -void st_make_current(struct st_context *st, - struct st_framebuffer *draw, - struct st_framebuffer *read); +GLboolean st_make_current(struct st_context *st, + struct st_framebuffer *draw, + struct st_framebuffer *read); + +struct st_context *st_get_current(void); void st_flush( struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence ); @@ -101,6 +103,10 @@ void st_finish( struct st_context *st ); void st_notify_swapbuffers(struct st_framebuffer *stfb); +void st_swapbuffers(struct st_framebuffer *stfb, + struct pipe_surface **front_left, + struct pipe_surface **front_right); + int st_set_teximage(struct pipe_texture *pt, int target); /** Redirect rendering into stfb's surface to a texture image */ diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 3f90ad502c..10faa633ea 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -30,6 +30,7 @@ #include "st_public.h" #include "st_texture.h" #include "st_cb_fbo.h" +#include "st_inlines.h" #include "main/enums.h" #include "main/teximage.h" #include "main/texstore.h" @@ -78,7 +79,6 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, - GLuint compress_byte, GLuint usage ) { struct pipe_texture pt, *newtex; @@ -101,7 +101,6 @@ st_texture_create(struct st_context *st, pt.width[0] = width0; pt.height[0] = height0; pt.depth[0] = depth0; - pt.compressed = compress_byte ? 1 : 0; pf_get_block(format, &pt.block); pt.tex_usage = usage; @@ -128,8 +127,7 @@ st_texture_match_image(const struct pipe_texture *pt, /* Check if this image's format matches the established texture's format. */ - if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format || - image->IsCompressed != pt->compressed) + if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format) return GL_FALSE; /* Test if this image's size matches what's expected in the @@ -191,13 +189,15 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, GLuint zoffset, enum pipe_transfer_usage usage, GLuint x, GLuint y, GLuint w, GLuint h) { - struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; struct pipe_texture *pt = stImage->pt; + DBG("%s \n", __FUNCTION__); - stImage->transfer = screen->get_tex_transfer(screen, pt, stImage->face, - stImage->level, zoffset, - usage, x, y, w, h); + stImage->transfer = st_no_flush_get_tex_transfer(st, pt, stImage->face, + stImage->level, zoffset, + usage, x, y, w, h); if (stImage->transfer) return screen->transfer_map(screen, stImage->transfer); @@ -254,13 +254,14 @@ st_surface_data(struct pipe_context *pipe, /* Upload data for a particular image. */ void -st_texture_image_data(struct pipe_context *pipe, +st_texture_image_data(struct st_context *st, struct pipe_texture *dst, GLuint face, GLuint level, void *src, GLuint src_row_stride, GLuint src_image_stride) { + struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; GLuint depth = dst->depth[level]; GLuint i; @@ -268,11 +269,12 @@ st_texture_image_data(struct pipe_context *pipe, struct pipe_transfer *dst_transfer; DBG("%s\n", __FUNCTION__); + for (i = 0; i < depth; i++) { - dst_transfer = screen->get_tex_transfer(screen, dst, face, level, i, - PIPE_TRANSFER_WRITE, 0, 0, - dst->width[level], - dst->height[level]); + dst_transfer = st_no_flush_get_tex_transfer(st, dst, face, level, i, + PIPE_TRANSFER_WRITE, 0, 0, + dst->width[level], + dst->height[level]); st_surface_data(pipe, dst_transfer, 0, 0, /* dstx, dsty */ @@ -484,3 +486,20 @@ st_release_teximage(struct st_framebuffer *stfb, uint surfIndex, return 1; } + +void +st_teximage_flush_before_map(struct st_context *st, + struct pipe_texture *pt, + unsigned int face, + unsigned int level, + enum pipe_transfer_usage usage) +{ + struct pipe_context *pipe = st->pipe; + unsigned referenced = + pipe->is_texture_referenced(pipe, pt, face, level); + + if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) || + usage == PIPE_TRANSFER_WRITE || + usage == PIPE_TRANSFER_READ_WRITE)) + st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL); +} diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index 28c2f580f6..b9d447cb56 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -108,7 +108,6 @@ st_texture_create(struct st_context *st, GLuint width0, GLuint height0, GLuint depth0, - GLuint compress_byte, GLuint tex_usage ); @@ -157,7 +156,7 @@ st_texture_texel_offset(const struct pipe_texture * pt, /* Upload an image into a texture */ extern void -st_texture_image_data(struct pipe_context *pipe, +st_texture_image_data(struct st_context *st, struct pipe_texture *dst, GLuint face, GLuint level, void *src, GLuint src_row_pitch, GLuint src_image_pitch); @@ -171,5 +170,10 @@ st_texture_image_copy(struct pipe_context *pipe, struct pipe_texture *src, GLuint face); - +extern void +st_teximage_flush_before_map(struct st_context *st, + struct pipe_texture *pt, + unsigned int face, + unsigned int level, + enum pipe_transfer_usage usage); #endif |