diff options
Diffstat (limited to 'src/mesa/state_tracker')
52 files changed, 1523 insertions, 881 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index e29ab46ef99..bf160fe1080 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -147,7 +147,11 @@ void st_validate_state( struct st_context *st ) /*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/ +#ifdef NDEBUG + if (0) { +#else if (1) { +#endif /* Debug version which enforces various sanity checks on the * state flags which are generated and checked to help ensure * state atoms are ordered correctly in the list. diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c index 8d1dc792bc8..05667a74305 100644 --- a/src/mesa/state_tracker/st_atom_constbuf.c +++ b/src/mesa/state_tracker/st_atom_constbuf.c @@ -56,7 +56,6 @@ void st_upload_constants( struct st_context *st, unsigned shader_type) { struct pipe_context *pipe = st->pipe; - struct pipe_resource **cbuf = &st->state.constants[shader_type]; assert(shader_type == PIPE_SHADER_VERTEX || shader_type == PIPE_SHADER_FRAGMENT || @@ -64,17 +63,24 @@ void st_upload_constants( struct st_context *st, /* update constants */ if (params && params->NumParameters) { + struct pipe_resource *cbuf; const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4; + /* Update the constants which come from fixed-function state, such as + * transformation matrices, fog factors, etc. The rest of the values in + * the parameters list are explicitly set by the user with glUniform, + * glProgramParameter(), etc. + */ _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. + * Let's use a user buffer to avoid an unnecessary copy. */ - pipe_resource_reference(cbuf, NULL ); - *cbuf = pipe_buffer_create(pipe->screen, - PIPE_BIND_CONSTANT_BUFFER, - paramBytes ); + cbuf = pipe_user_buffer_create(pipe->screen, + params->ParameterValues, + paramBytes, + PIPE_BIND_CONSTANT_BUFFER); if (ST_DEBUG & DEBUG_CONSTANTS) { debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", @@ -83,17 +89,15 @@ void st_upload_constants( struct st_context *st, _mesa_print_parameter_list(params); } - /* load Mesa constants into the constant buffer */ - pipe_buffer_write(st->pipe, *cbuf, - 0, paramBytes, - params->ParameterValues); + st->pipe->set_constant_buffer(st->pipe, shader_type, 0, cbuf); + pipe_resource_reference(&cbuf, NULL); - st->pipe->set_constant_buffer(st->pipe, shader_type, 0, *cbuf); + st->state.constants[shader_type].ptr = params->ParameterValues; + st->state.constants[shader_type].size = paramBytes; } - else if (*cbuf) { - st->constants.tracked_state[shader_type].dirty.mesa = 0x0; - - pipe_resource_reference(cbuf, NULL); + else if (st->state.constants[shader_type].ptr) { + st->state.constants[shader_type].ptr = NULL; + st->state.constants[shader_type].size = 0; st->pipe->set_constant_buffer(st->pipe, shader_type, 0, NULL); } } diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index 036bc60049a..2843b7b1764 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -51,7 +51,7 @@ static void update_renderbuffer_surface(struct st_context *st, struct st_renderbuffer *strb) { - struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *pipe = st->pipe; struct pipe_resource *resource = strb->rtt->pt; int rtt_width = strb->Base.Width; int rtt_height = strb->Base.Height; @@ -65,15 +65,19 @@ update_renderbuffer_surface(struct st_context *st, for (level = 0; level <= resource->last_level; level++) { if (u_minify(resource->width0, level) == rtt_width && u_minify(resource->height0, level) == rtt_height) { + struct pipe_surface surf_tmpl; + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = resource->format; + surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; + surf_tmpl.u.tex.level = level; + surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; + surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; pipe_surface_reference(&strb->surface, NULL); - strb->surface = screen->get_tex_surface(screen, - resource, - strb->rtt_face, - level, - strb->rtt_slice, - PIPE_BIND_RENDER_TARGET); + strb->surface = pipe->create_surface(pipe, + resource, + &surf_tmpl); #if 0 printf("-- alloc new surface %d x %d into tex %p\n", strb->surface->width, strb->surface->height, diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index 6be03376d01..378b30e57cc 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -122,8 +122,8 @@ load_color_map_texture(struct gl_context *ctx, struct pipe_resource *pt) uint i, j; transfer = pipe_get_transfer(st_context(ctx)->pipe, - pt, 0, 0, 0, PIPE_TRANSFER_WRITE, - 0, 0, texSize, texSize); + pt, 0, 0, PIPE_TRANSFER_WRITE, + 0, 0, texSize, texSize); dest = (uint *) pipe_transfer_map(pipe, transfer); /* Pack four 1D maps into a 2D texture: diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index f147d768084..b67068df373 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -121,6 +121,18 @@ static void xlate_border_color(const GLfloat *colorIn, GLenum baseFormat, GLfloat *colorOut) { switch (baseFormat) { + case GL_RED: + colorOut[0] = colorIn[0]; + colorOut[1] = 0.0F; + colorOut[2] = 0.0F; + colorOut[3] = 1.0F; + break; + case GL_RG: + colorOut[0] = colorIn[0]; + colorOut[1] = colorIn[1]; + colorOut[2] = 0.0F; + colorOut[3] = 1.0F; + break; case GL_RGB: colorOut[0] = colorIn[0]; colorOut[1] = colorIn[1]; diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 05442ef91b5..c311d043931 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -50,99 +50,6 @@ #include "st_program.h" - -/** - * Translate fragment program if needed. - */ -static void -translate_fp(struct st_context *st, - struct st_fragment_program *stfp) -{ - if (!stfp->tgsi.tokens) { - assert(stfp->Base.Base.NumInstructions > 0); - - st_translate_fragment_program(st, stfp); - } -} - -/* - * Translate geometry program if needed. - */ -static void -translate_gp(struct st_context *st, - struct st_geometry_program *stgp) -{ - if (!stgp->tgsi.tokens) { - assert(stgp->Base.Base.NumInstructions > 1); - - st_translate_geometry_program(st, stgp); - } -} - -/** - * Find a translated vertex program that corresponds to stvp and - * has outputs matched to stfp's inputs. - * This performs vertex and fragment translation (to TGSI) when needed. - */ -static struct st_vp_varient * -find_translated_vp(struct st_context *st, - struct st_vertex_program *stvp ) -{ - struct st_vp_varient *vpv; - struct st_vp_varient_key key; - - /* Nothing in our key yet. This will change: - */ - memset(&key, 0, sizeof key); - - /* When this is true, we will add an extra input to the vertex - * shader translation (for edgeflags), an extra output with - * edgeflag semantics, and extend the vertex shader to pass through - * the input to the output. We'll need to use similar logic to set - * up the extra vertex_element input for edgeflags. - * _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA - */ - key.passthrough_edgeflags = (st->vertdata_edgeflags && ( - st->ctx->Polygon.FrontMode != GL_FILL || - st->ctx->Polygon.BackMode != GL_FILL)); - - - /* Do we need to throw away old translations after a change in the - * GL program string? - */ - if (stvp->serialNo != stvp->lastSerialNo) { - /* These may have changed if the program string changed. - */ - st_prepare_vertex_program( st, stvp ); - - /* We are now up-to-date: - */ - stvp->lastSerialNo = stvp->serialNo; - } - - /* See if we've got a translated vertex program whose outputs match - * the fragment program's inputs. - */ - for (vpv = stvp->varients; vpv; vpv = vpv->next) { - if (memcmp(&vpv->key, &key, sizeof key) == 0) { - break; - } - } - - /* No? Perform new translation here. */ - if (!vpv) { - vpv = st_translate_vertex_program(st, stvp, &key); - if (!vpv) - return NULL; - - vpv->next = stvp->varients; - stvp->varients = vpv; - } - - return vpv; -} - - /** * Return pointer to a pass-through fragment shader. * This shader is used when a texture is missing/incomplete. @@ -167,12 +74,16 @@ static void update_fp( struct st_context *st ) { struct st_fragment_program *stfp; + struct st_fp_variant_key key; assert(st->ctx->FragmentProgram._Current); stfp = st_fragment_program(st->ctx->FragmentProgram._Current); assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); - translate_fp(st, stfp); + memset(&key, 0, sizeof(key)); + key.st = st; + + st->fp_variant = st_get_fp_variant(st, stfp, &key); st_reference_fragprog(st, &st->fp, stfp); @@ -182,7 +93,8 @@ update_fp( struct st_context *st ) cso_set_fragment_shader_handle(st->cso_context, fs); } else { - cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); + cso_set_fragment_shader_handle(st->cso_context, + st->fp_variant->driver_shader); } } @@ -206,6 +118,7 @@ static void update_vp( struct st_context *st ) { struct st_vertex_program *stvp; + struct st_vp_variant_key key; /* find active shader and params -- Should be covered by * ST_NEW_VERTEX_PROGRAM @@ -214,12 +127,26 @@ update_vp( struct st_context *st ) stvp = st_vertex_program(st->ctx->VertexProgram._Current); assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); - st->vp_varient = find_translated_vp(st, stvp); + memset(&key, 0, sizeof key); + key.st = st; /* variants are per-context */ + + /* When this is true, we will add an extra input to the vertex + * shader translation (for edgeflags), an extra output with + * edgeflag semantics, and extend the vertex shader to pass through + * the input to the output. We'll need to use similar logic to set + * up the extra vertex_element input for edgeflags. + * _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA + */ + key.passthrough_edgeflags = (st->vertdata_edgeflags && ( + st->ctx->Polygon.FrontMode != GL_FILL || + st->ctx->Polygon.BackMode != GL_FILL)); + + st->vp_variant = st_get_vp_variant(st, stvp, &key); st_reference_vertprog(st, &st->vp, stvp); cso_set_vertex_shader_handle(st->cso_context, - st->vp_varient->driver_shader); + st->vp_variant->driver_shader); st->vertex_result_to_slot = stvp->result_to_output; } @@ -231,14 +158,16 @@ const struct st_tracked_state st_update_vp = { _NEW_POLYGON, /* mesa */ ST_NEW_VERTEX_PROGRAM | ST_NEW_EDGEFLAGS_DATA /* st */ }, - update_vp /* update */ + update_vp /* update */ }; + + static void update_gp( struct st_context *st ) { - struct st_geometry_program *stgp; + struct st_gp_variant_key key; if (!st->ctx->GeometryProgram._Current) { cso_set_geometry_shader_handle(st->cso_context, NULL); @@ -248,18 +177,22 @@ update_gp( struct st_context *st ) stgp = st_geometry_program(st->ctx->GeometryProgram._Current); assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM); - translate_gp(st, stgp); + memset(&key, 0, sizeof(key)); + key.st = st; + + st->gp_variant = st_get_gp_variant(st, stgp, &key); st_reference_geomprog(st, &st->gp, stgp); - cso_set_geometry_shader_handle(st->cso_context, stgp->driver_shader); + cso_set_geometry_shader_handle(st->cso_context, + st->gp_variant->driver_shader); } const struct st_tracked_state st_update_gp = { - "st_update_gp", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_GEOMETRY_PROGRAM /* st */ + "st_update_gp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_GEOMETRY_PROGRAM /* st */ }, - update_gp /* update */ + update_gp /* update */ }; diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index 6c5caf42e35..35921f4f614 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -33,6 +33,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "st_debug.h" #include "st_context.h" @@ -138,10 +139,10 @@ accum_accum(struct st_context *st, GLfloat value, debug_printf("%s: fallback processing\n", __FUNCTION__); color_trans = pipe_get_transfer(st->pipe, - color_strb->texture, - 0, 0, 0, - PIPE_TRANSFER_READ, xpos, ypos, - width, height); + color_strb->texture, + 0, 0, + PIPE_TRANSFER_READ, xpos, ypos, + width, height); buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); @@ -187,9 +188,9 @@ accum_load(struct st_context *st, GLfloat value, debug_printf("%s: fallback processing\n", __FUNCTION__); color_trans = pipe_get_transfer(st->pipe, color_strb->texture, - 0, 0, 0, - PIPE_TRANSFER_READ, xpos, ypos, - width, height); + 0, 0, + PIPE_TRANSFER_READ, xpos, ypos, + width, height); buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); @@ -241,12 +242,12 @@ accum_return(struct gl_context *ctx, GLfloat value, usage = PIPE_TRANSFER_READ_WRITE; else usage = PIPE_TRANSFER_WRITE; - + color_trans = pipe_get_transfer(st_context(ctx)->pipe, - color_strb->texture, 0, 0, 0, - usage, - xpos, ypos, - width, height); + color_strb->texture, 0, 0, + usage, + xpos, ypos, + width, height); if (usage & PIPE_TRANSFER_READ) pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf); diff --git a/src/mesa/state_tracker/st_cb_accum.h b/src/mesa/state_tracker/st_cb_accum.h index b8c9c350031..050a21483e4 100644 --- a/src/mesa/state_tracker/st_cb_accum.h +++ b/src/mesa/state_tracker/st_cb_accum.h @@ -30,7 +30,11 @@ #define ST_CB_ACCUM_H -#include "main/mtypes.h" +#include "main/mfeatures.h" + +struct dd_function_table; +struct gl_context; +struct gl_renderbuffer; #if FEATURE_accum diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 3c0ee6c2883..e23fe86daeb 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -34,6 +34,7 @@ #include "main/image.h" #include "main/bufferobj.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "program/program.h" #include "program/prog_print.h" @@ -185,48 +186,47 @@ find_free_bit(uint bitfield) /** * Combine basic bitmap fragment program with the user-defined program. + * \param st current context + * \param fpIn the incoming fragment program + * \param fpOut the new fragment program which does fragment culling + * \param bitmap_sampler sampler number for the bitmap texture */ -static struct st_fragment_program * -combined_bitmap_fragment_program(struct gl_context *ctx) +void +st_make_bitmap_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut, + GLuint *bitmap_sampler) { - struct st_context *st = st_context(ctx); - struct st_fragment_program *stfp = st->fp; - - if (!stfp->bitmap_program) { - /* - * Generate new program which is the user-defined program prefixed - * with the bitmap sampler/kill instructions. - */ - struct st_fragment_program *bitmap_prog; - uint sampler; - - sampler = find_free_bit(st->fp->Base.Base.SamplersUsed); - bitmap_prog = make_bitmap_fragment_program(ctx, sampler); + struct st_fragment_program *bitmap_prog; + struct gl_program *newProg; + uint sampler; - stfp->bitmap_program = (struct st_fragment_program *) - _mesa_combine_programs(ctx, - &bitmap_prog->Base.Base, &stfp->Base.Base); - stfp->bitmap_program->bitmap_sampler = sampler; + /* + * Generate new program which is the user-defined program prefixed + * with the bitmap sampler/kill instructions. + */ + sampler = find_free_bit(fpIn->Base.SamplersUsed); + bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler); - /* done with this after combining */ - st_reference_fragprog(st, &bitmap_prog, NULL); + newProg = _mesa_combine_programs(st->ctx, + &bitmap_prog->Base.Base, + &fpIn->Base); + /* done with this after combining */ + st_reference_fragprog(st, &bitmap_prog, NULL); #if 0 - { - struct gl_program *p = &stfp->bitmap_program->Base.Base; - printf("Combined bitmap program:\n"); - _mesa_print_program(p); - printf("InputsRead: 0x%x\n", p->InputsRead); - printf("OutputsWritten: 0x%x\n", p->OutputsWritten); - _mesa_print_parameter_list(p->Parameters); - } -#endif - - /* translate to TGSI tokens */ - st_translate_fragment_program(st, stfp->bitmap_program); + { + printf("Combined bitmap program:\n"); + _mesa_print_program(newProg); + printf("InputsRead: 0x%x\n", newProg->InputsRead); + printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); + _mesa_print_parameter_list(newProg->Parameters); } +#endif - return stfp->bitmap_program; + /* return results */ + *fpOut = (struct gl_fragment_program *) newProg; + *bitmap_sampler = sampler; } @@ -283,9 +283,9 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height, return NULL; } - transfer = pipe_get_transfer(st->pipe, pt, 0, 0, 0, - PIPE_TRANSFER_WRITE, - 0, 0, width, height); + transfer = pipe_get_transfer(st->pipe, pt, 0, 0, + PIPE_TRANSFER_WRITE, + 0, 0, width, height); dest = pipe_transfer_map(pipe, transfer); @@ -349,7 +349,8 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized, if (!st->bitmap.vbuf) { st->bitmap.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, - max_slots * sizeof(st->bitmap.vertices)); + max_slots * + sizeof(st->bitmap.vertices)); } /* Positions are in clip coords since we need to do clipping in case @@ -389,10 +390,11 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized, /* put vertex data into vbuf */ pipe_buffer_write_nooverlap(st->pipe, - st->bitmap.vbuf, - st->bitmap.vbuf_slot * sizeof st->bitmap.vertices, - sizeof st->bitmap.vertices, - st->bitmap.vertices); + 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; } @@ -411,11 +413,16 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; - struct st_fragment_program *stfp; + struct st_fp_variant *fpv; + struct st_fp_variant_key key; GLuint maxSize; GLuint offset; - stfp = combined_bitmap_fragment_program(ctx); + memset(&key, 0, sizeof(key)); + key.st = st; + key.bitmap = GL_TRUE; + + fpv = st_get_fp_variant(st, st->fp, &key); /* As an optimization, Mesa's fragment programs will sometimes get the * primary color from a statevar/constant rather than a varying variable. @@ -428,7 +435,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, GLfloat colorSave[4]; COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); - st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); } @@ -437,7 +444,8 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* XXX if the bitmap is larger than the max texture size, break * it up into chunks. */ - maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + maxSize = 1 << (pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); assert(width <= (GLsizei)maxSize); assert(height <= (GLsizei)maxSize); @@ -454,7 +462,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_set_rasterizer(cso, &st->bitmap.rasterizer); /* fragment shader state: TEX lookup program */ - cso_set_fragment_shader_handle(cso, stfp->driver_shader); + cso_set_fragment_shader_handle(cso, fpv->driver_shader); /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, st->bitmap.vs); @@ -462,21 +470,22 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* user samplers, plus our bitmap sampler */ { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers); + uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers); uint i; for (i = 0; i < st->state.num_samplers; i++) { samplers[i] = &st->state.samplers[i]; } - samplers[stfp->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; + samplers[fpv->bitmap_sampler] = + &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers); } /* user textures, plus the bitmap texture */ { struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; - uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures); + uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_textures); memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views)); - sampler_views[stfp->bitmap_sampler] = sv; + sampler_views[fpv->bitmap_sampler] = sv; cso_set_fragment_sampler_views(cso, num, sampler_views); } @@ -504,7 +513,9 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, z = z * 2.0 - 1.0; /* draw textured quad */ - offset = setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color); + offset = setup_bitmap_vertex_data(st, + sv->texture->target != PIPE_TEXTURE_RECT, + x, y, width, height, z, color); util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, @@ -573,6 +584,9 @@ print_cache(const struct bitmap_cache *cache) } +/** + * Create gallium pipe_transfer object for the bitmap cache. + */ static void create_cache_trans(struct st_context *st) { @@ -585,10 +599,10 @@ create_cache_trans(struct st_context *st) /* Map the texture transfer. * Subsequent glBitmap calls will write into the texture image. */ - cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0, 0, - PIPE_TRANSFER_WRITE, 0, 0, - BITMAP_CACHE_WIDTH, - BITMAP_CACHE_HEIGHT); + cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, + BITMAP_CACHE_WIDTH, + BITMAP_CACHE_HEIGHT); cache->buffer = pipe_transfer_map(pipe, cache->trans); /* init image to all 0xff */ @@ -651,7 +665,9 @@ st_flush_bitmap_cache(struct st_context *st) } } -/* Flush bitmap cache and release vertex buffer. + +/** + * Flush bitmap cache and release vertex buffer. */ void st_flush_bitmap( struct st_context *st ) @@ -737,7 +753,8 @@ accum_bitmap(struct st_context *st, * Called via ctx->Driver.Bitmap() */ static void -st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, +st_Bitmap(struct gl_context *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { struct st_context *st = st_context(ctx); @@ -764,7 +781,8 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei heigh pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); if (pt) { - struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt); + struct pipe_sampler_view *sv = + st_create_texture_sampler_view(st->pipe, pt); assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT); @@ -814,15 +832,18 @@ st_init_bitmap(struct st_context *st) st->bitmap.rasterizer.gl_rasterization_rules = 1; /* find a usable texture format */ - if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D, 0, + if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, + PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) { st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM; } - else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, PIPE_TEXTURE_2D, 0, + else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, + PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) { st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM; } - else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, PIPE_TEXTURE_2D, 0, + else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, + PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) { st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM; } @@ -845,8 +866,6 @@ st_destroy_bitmap(struct st_context *st) struct pipe_context *pipe = st->pipe; struct bitmap_cache *cache = st->bitmap.cache; - - if (st->bitmap.vs) { cso_delete_vertex_shader(st->cso_context, st->bitmap.vs); st->bitmap.vs = NULL; diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h index d04b2b67795..ed141580376 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.h +++ b/src/mesa/state_tracker/st_cb_bitmap.h @@ -31,9 +31,12 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; struct st_context; +struct gl_fragment_program; +struct st_fragment_program; #if FEATURE_drawpix @@ -47,6 +50,12 @@ extern void st_destroy_bitmap(struct st_context *st); extern void +st_make_bitmap_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut, + GLuint *bitmap_sampler); + +extern void st_flush_bitmap_cache(struct st_context *st); /* Flush bitmap cache and release vertex buffer. Needed at end of diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index af41835326a..6d02a7dccd4 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -33,6 +33,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "st_context.h" #include "st_texture.h" @@ -40,7 +41,6 @@ #include "st_cb_fbo.h" #include "util/u_blit.h" -#include "util/u_inlines.h" void @@ -115,17 +115,14 @@ st_BlitFramebuffer(struct gl_context *ctx, st_texture_object(srcAtt->Texture); struct st_renderbuffer *dstRb = st_renderbuffer(drawFB->_ColorDrawBuffers[0]); - struct pipe_subresource srcSub; struct pipe_surface *dstSurf = dstRb->surface; if (!srcObj->pt) return; - srcSub.face = srcAtt->CubeMapFace; - srcSub.level = srcAtt->TextureLevel; - - util_blit_pixels(st->blit, srcObj->pt, srcSub, - srcX0, srcY0, srcX1, srcY1, srcAtt->Zoffset, + util_blit_pixels(st->blit, srcObj->pt, srcAtt->TextureLevel, + srcX0, srcY0, srcX1, srcY1, + srcAtt->Zoffset + srcAtt->CubeMapFace, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } @@ -136,14 +133,11 @@ st_BlitFramebuffer(struct gl_context *ctx, st_renderbuffer(drawFB->_ColorDrawBuffers[0]); struct pipe_surface *srcSurf = srcRb->surface; struct pipe_surface *dstSurf = dstRb->surface; - struct pipe_subresource srcSub; - - srcSub.face = srcSurf->face; - srcSub.level = srcSurf->level; util_blit_pixels(st->blit, - srcRb->texture, srcSub, srcX0, srcY0, srcX1, srcY1, - srcSurf->zslice, + srcRb->texture, srcSurf->u.tex.level, + srcX0, srcY0, srcX1, srcY1, + srcSurf->u.tex.first_layer, dstSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } @@ -176,11 +170,11 @@ st_BlitFramebuffer(struct gl_context *ctx, /* Blitting depth and stencil values between combined * depth/stencil buffers. This is the ideal case for such buffers. */ - util_blit_pixels(st->blit, srcDepthRb->texture, - u_subresource(srcDepthRb->surface->face, - srcDepthRb->surface->level), + util_blit_pixels(st->blit, + srcDepthRb->texture, + srcDepthRb->surface->u.tex.level, srcX0, srcY0, srcX1, srcY1, - srcDepthRb->surface->zslice, + srcDepthRb->surface->u.tex.first_layer, dstDepthSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } @@ -189,10 +183,9 @@ st_BlitFramebuffer(struct gl_context *ctx, if (mask & GL_DEPTH_BUFFER_BIT) { util_blit_pixels(st->blit, srcDepthRb->texture, - u_subresource(srcDepthRb->surface->face, - srcDepthRb->surface->level), + srcDepthRb->surface->u.tex.level, srcX0, srcY0, srcX1, srcY1, - srcDepthRb->surface->zslice, + srcDepthRb->surface->u.tex.first_layer, dstDepthSurf, dstX0, dstY0, dstX1, dstY1, 0.0, pFilter); } diff --git a/src/mesa/state_tracker/st_cb_blit.h b/src/mesa/state_tracker/st_cb_blit.h index c230652cefc..c6d9a367955 100644 --- a/src/mesa/state_tracker/st_cb_blit.h +++ b/src/mesa/state_tracker/st_cb_blit.h @@ -30,6 +30,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; struct st_context; diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c index 27540c36ce7..d4d9af4ada3 100644 --- a/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -211,6 +211,13 @@ st_bufferobj_data(struct gl_context *ctx, /** + * Dummy data whose's pointer is used for zero size buffers or ranges. + */ +static long st_bufferobj_zero_length = 0; + + + +/** * Called via glMapBufferARB(). */ static void * @@ -233,10 +240,16 @@ st_bufferobj_map(struct gl_context *ctx, GLenum target, GLenum access, break; } - obj->Pointer = pipe_buffer_map(st_context(ctx)->pipe, - st_obj->buffer, - flags, - &st_obj->transfer); + /* Handle zero-size buffers here rather than in drivers */ + if (obj->Size == 0) { + obj->Pointer = &st_bufferobj_zero_length; + } + else { + obj->Pointer = pipe_buffer_map(st_context(ctx)->pipe, + st_obj->buffer, + flags, + &st_obj->transfer); + } if (obj->Pointer) { obj->Offset = 0; @@ -247,13 +260,6 @@ st_bufferobj_map(struct gl_context *ctx, GLenum target, GLenum access, /** - * Dummy data whose's pointer is used for zero length ranges. - */ -static long -st_bufferobj_zero_length_range = 0; - - -/** * Called via glMapBufferRange(). */ static void * @@ -273,6 +279,12 @@ st_bufferobj_map_range(struct gl_context *ctx, GLenum target, if (access & GL_MAP_FLUSH_EXPLICIT_BIT) flags |= PIPE_TRANSFER_FLUSH_EXPLICIT; + + if (access & GL_MAP_INVALIDATE_RANGE_BIT) + flags |= PIPE_TRANSFER_DISCARD; + + if (access & GL_MAP_INVALIDATE_BUFFER_BIT) + flags |= PIPE_TRANSFER_DISCARD; if (access & GL_MAP_UNSYNCHRONIZED_BIT) flags |= PIPE_TRANSFER_UNSYNCHRONIZED; @@ -293,7 +305,7 @@ st_bufferobj_map_range(struct gl_context *ctx, GLenum target, * length range from the pipe driver. */ if (!length) { - obj->Pointer = &st_bufferobj_zero_length_range; + obj->Pointer = &st_bufferobj_zero_length; } else { obj->Pointer = pipe_buffer_map_range(pipe, @@ -348,7 +360,7 @@ st_bufferobj_unmap(struct gl_context *ctx, GLenum target, struct gl_buffer_objec struct st_buffer_object *st_obj = st_buffer_object(obj); if (obj->Length) - pipe_buffer_unmap(pipe, st_obj->buffer, st_obj->transfer); + pipe_buffer_unmap(pipe, st_obj->transfer); st_obj->transfer = NULL; obj->Pointer = NULL; @@ -397,8 +409,8 @@ st_copy_buffer_subdata(struct gl_context *ctx, if (srcPtr && dstPtr) memcpy(dstPtr + writeOffset, srcPtr + readOffset, size); - pipe_buffer_unmap(pipe, srcObj->buffer, src_transfer); - pipe_buffer_unmap(pipe, dstObj->buffer, dst_transfer); + pipe_buffer_unmap(pipe, src_transfer); + pipe_buffer_unmap(pipe, dst_transfer); } diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index bd1dd78b23c..6571bf237fb 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -470,13 +470,9 @@ st_Clear(struct gl_context *ctx, GLbitfield mask) if (mask & (1 << b)) { struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[b].Renderbuffer; - struct st_renderbuffer *strb; + struct st_renderbuffer *strb = st_renderbuffer(rb); - assert(rb); - - strb = st_renderbuffer(rb); - - if (!strb->surface) + if (!strb || !strb->surface) continue; if (check_clear_color_with_quad( ctx, rb )) diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index d80c068ea81..d128ff98f02 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -34,6 +34,8 @@ #include "main/image.h" #include "main/bufferobj.h" #include "main/macros.h" +#include "main/mfeatures.h" +#include "main/mtypes.h" #include "main/pack.h" #include "main/texformat.h" #include "main/texstore.h" @@ -94,88 +96,61 @@ is_passthrough_program(const struct gl_fragment_program *prog) /** * Make fragment shader for glDraw/CopyPixels. This shader is made * by combining the pixel transfer shader with the user-defined shader. - * \return pointer to Gallium driver fragment shader + * \param fpIn the current/incoming fragment program + * \param fpOut returns the combined fragment program */ -static void * -combined_drawpix_fragment_program(struct gl_context *ctx) +void +st_make_drawpix_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut) { - struct st_context *st = st_context(ctx); - struct st_fragment_program *stfp; + struct gl_program *newProg; - if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn - && st->fp->serialNo == st->pixel_xfer.user_prog_sn) { - /* the pixel tranfer program has not changed and the user-defined - * program has not changed, so re-use the combined program. - */ - stfp = st->pixel_xfer.combined_prog; + if (is_passthrough_program(fpIn)) { + newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx, + &st->pixel_xfer.program->Base); } else { - /* Concatenate the pixel transfer program with the current user- - * defined program. - */ - if (is_passthrough_program(&st->fp->Base)) { - stfp = (struct st_fragment_program *) - _mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base); - } - else { #if 0 - printf("Base program:\n"); - _mesa_print_program(&st->fp->Base.Base); - printf("DrawPix program:\n"); - _mesa_print_program(&st->pixel_xfer.program->Base.Base); + /* debug */ + printf("Base program:\n"); + _mesa_print_program(&fpIn->Base); + printf("DrawPix program:\n"); + _mesa_print_program(&st->pixel_xfer.program->Base.Base); #endif - stfp = (struct st_fragment_program *) - _mesa_combine_programs(ctx, - &st->pixel_xfer.program->Base.Base, - &st->fp->Base.Base); - } + newProg = _mesa_combine_programs(st->ctx, + &st->pixel_xfer.program->Base.Base, + &fpIn->Base); + } #if 0 - { - struct gl_program *p = &stfp->Base.Base; - printf("Combined DrawPixels program:\n"); - _mesa_print_program(p); - printf("InputsRead: 0x%x\n", p->InputsRead); - printf("OutputsWritten: 0x%x\n", p->OutputsWritten); - _mesa_print_parameter_list(p->Parameters); - } + /* debug */ + printf("Combined DrawPixels program:\n"); + _mesa_print_program(newProg); + printf("InputsRead: 0x%x\n", newProg->InputsRead); + printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); + _mesa_print_parameter_list(newProg->Parameters); #endif - /* translate to TGSI tokens */ - st_translate_fragment_program(st, stfp); - - /* save new program, update serial numbers */ - 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; - } - - /* Ideally we'd have updated the pipe constants during the normal - * st/atom mechanism. But we can't since this is specific to glDrawPixels. - */ - st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); - - return stfp->driver_shader; + *fpOut = (struct gl_fragment_program *) newProg; } /** - * Create fragment shader that does a TEX() instruction to get a Z and/or + * Create fragment program that does a TEX() instruction to get a Z and/or * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL. * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX). * Pass fragment color through as-is. - * \return pointer to the Gallium driver fragment shader + * \return pointer to the gl_fragment program */ -static void * -make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, - GLboolean write_stencil) +struct gl_fragment_program * +st_make_drawpix_z_stencil_program(struct st_context *st, + GLboolean write_depth, + GLboolean write_stencil) { struct gl_context *ctx = st->ctx; struct gl_program *p; - struct st_fragment_program *stp; + struct gl_fragment_program *fp; GLuint ic = 0; const GLuint shaderIndex = write_depth * 2 + write_stencil; @@ -183,7 +158,7 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, if (st->drawpix.shaders[shaderIndex]) { /* already have the proper shader */ - return st->drawpix.shaders[shaderIndex]->driver_shader; + return st->drawpix.shaders[shaderIndex]; } /* @@ -245,18 +220,15 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, if (write_stencil) p->SamplersUsed |= 1 << 1; - stp = st_fragment_program((struct gl_fragment_program *) p); + fp = (struct gl_fragment_program *) p; /* save the new shader */ - st->drawpix.shaders[shaderIndex] = stp; + st->drawpix.shaders[shaderIndex] = fp; - st_translate_fragment_program(st, stp); - - return stp->driver_shader; + return fp; } - /** * Create a simple vertex shader that just passes through the * vertex position and texcoord (and optionally, color). @@ -427,9 +399,9 @@ make_texture(struct st_context *st, /* we'll do pixel transfer in a fragment shader */ ctx->_ImageTransferState = 0x0; - transfer = pipe_get_transfer(st->pipe, pt, 0, 0, 0, - PIPE_TRANSFER_WRITE, 0, 0, - width, height); + transfer = pipe_get_transfer(st->pipe, pt, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, + width, height); /* map texture transfer */ dest = pipe_transfer_map(pipe, transfer); @@ -763,9 +735,9 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, else usage = PIPE_TRANSFER_WRITE; - pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0, 0, - usage, x, y, - width, height); + pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0, + usage, x, y, + width, height); stmap = pipe_transfer_map(pipe, pt); @@ -873,6 +845,61 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, /** + * Get fragment program variant for a glDrawPixels or glCopyPixels + * command for RGBA data. + */ +static struct st_fp_variant * +get_color_fp_variant(struct st_context *st) +{ + struct gl_context *ctx = st->ctx; + struct st_fp_variant_key key; + struct st_fp_variant *fpv; + + memset(&key, 0, sizeof(key)); + + key.st = st; + key.drawpixels = 1; + key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 || + ctx->Pixel.RedScale != 1.0 || + ctx->Pixel.GreenBias != 0.0 || + ctx->Pixel.GreenScale != 1.0 || + ctx->Pixel.BlueBias != 0.0 || + ctx->Pixel.BlueScale != 1.0 || + ctx->Pixel.AlphaBias != 0.0 || + ctx->Pixel.AlphaScale != 1.0); + key.pixelMaps = ctx->Pixel.MapColorFlag; + + fpv = st_get_fp_variant(st, st->fp, &key); + + return fpv; +} + + +/** + * Get fragment program variant for a glDrawPixels or glCopyPixels + * command for depth/stencil data. + */ +static struct st_fp_variant * +get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth, + GLboolean write_stencil) +{ + struct st_fp_variant_key key; + struct st_fp_variant *fpv; + + memset(&key, 0, sizeof(key)); + + key.st = st; + key.drawpixels = 1; + key.drawpixels_z = write_depth; + key.drawpixels_stencil = write_stencil; + + fpv = st_get_fp_variant(st, st->fp, &key); + + return fpv; +} + + +/** * Called via ctx->Driver.DrawPixels() */ static void @@ -889,6 +916,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, struct pipe_sampler_view *sv[2]; int num_sampler_view = 1; enum pipe_format stencil_format = PIPE_FORMAT_NONE; + struct st_fp_variant *fpv; if (format == GL_DEPTH_STENCIL) write_stencil = write_depth = GL_TRUE; @@ -921,14 +949,25 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, st_validate_state(st); + /* + * Get vertex/fragment shaders + */ if (write_depth || write_stencil) { - driver_fp = make_fragment_shader_z_stencil(st, write_depth, write_stencil); + fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil); + + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); + color = ctx->Current.RasterColor; } else { - driver_fp = combined_drawpix_fragment_program(ctx); + fpv = get_color_fp_variant(st); + + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); + color = NULL; if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; @@ -936,6 +975,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, } } + /* update fragment program constants */ + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + /* draw with textured quad */ { struct pipe_resource *pt @@ -1025,15 +1067,15 @@ copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy, usage = PIPE_TRANSFER_READ_WRITE; else usage = PIPE_TRANSFER_WRITE; - + if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) { dsty = rbDraw->Base.Height - dsty - height; } ptDraw = pipe_get_transfer(st_context(ctx)->pipe, - rbDraw->texture, 0, 0, 0, - usage, dstx, dsty, - width, height); + rbDraw->texture, 0, 0, + usage, dstx, dsty, + width, height); assert(util_format_get_blockwidth(ptDraw->resource->format) == 1); assert(util_format_get_blockheight(ptDraw->resource->format) == 1); @@ -1116,6 +1158,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLint readX, readY, readW, readH; GLuint sample_count; struct gl_pixelstore_attrib pack = ctx->DefaultPacking; + struct st_fp_variant *fpv; st_validate_state(st); @@ -1125,11 +1168,18 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, return; } + /* + * Get vertex/fragment shaders + */ if (type == GL_COLOR) { rbRead = st_get_color_read_renderbuffer(ctx); color = NULL; - driver_fp = combined_drawpix_fragment_program(ctx); + + fpv = get_color_fp_variant(st); + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); + if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; num_sampler_view++; @@ -1139,10 +1189,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, assert(type == GL_DEPTH); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; - driver_fp = make_fragment_shader_z_stencil(st, GL_TRUE, GL_FALSE); + + fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE); + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); } + /* update fragment program constants */ + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + + if (rbRead->Base.Wrapped) rbRead = st_renderbuffer(rbRead->Base.Wrapped); @@ -1209,27 +1266,24 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, /* Make temporary texture which is a copy of the src region. */ if (srcFormat == texFormat) { - struct pipe_subresource srcsub, dstsub; - srcsub.face = 0; - srcsub.level = 0; - dstsub.face = 0; - dstsub.level = 0; - /* copy source framebuffer surface into mipmap/texture */ + struct pipe_box src_box; + u_box_2d(readX, readY, readW, readH, &src_box); + /* copy source framebuffer surface into mipmap/texture */ pipe->resource_copy_region(pipe, pt, /* dest tex */ - dstsub, + 0, pack.SkipPixels, pack.SkipRows, 0, /* dest pos */ rbRead->texture, /* src tex */ - srcsub, - readX, readY, 0, readW, readH); /* src region */ + 0, + &src_box); } else { /* CPU-based fallback/conversion */ struct pipe_transfer *ptRead = - pipe_get_transfer(st->pipe, rbRead->texture, 0, 0, 0, - PIPE_TRANSFER_READ, - readX, readY, readW, readH); + pipe_get_transfer(st->pipe, rbRead->texture, 0, 0, + PIPE_TRANSFER_READ, + readX, readY, readW, readH); struct pipe_transfer *ptTex; enum pipe_transfer_usage transfer_usage; @@ -1241,8 +1295,8 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, else transfer_usage = PIPE_TRANSFER_WRITE; - ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, 0, transfer_usage, - 0, 0, width, height); + ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage, + 0, 0, width, height); /* copy image from ptRead surface to ptTex surface */ if (type == GL_COLOR) { @@ -1297,7 +1351,7 @@ st_destroy_drawpix(struct st_context *st) for (i = 0; i < Elements(st->drawpix.shaders); i++) { if (st->drawpix.shaders[i]) - st_reference_fragprog(st, &st->drawpix.shaders[i], NULL); + _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL); } st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h index 575f169e08e..44d7f5ed1e7 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.h +++ b/src/mesa/state_tracker/st_cb_drawpixels.h @@ -31,6 +31,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; struct st_context; @@ -42,6 +43,16 @@ extern void st_init_drawpixels_functions(struct dd_function_table *functions); extern void st_destroy_drawpix(struct st_context *st); +extern void +st_make_drawpix_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut); + +extern struct gl_fragment_program * +st_make_drawpix_z_stencil_program(struct st_context *st, + GLboolean write_depth, + GLboolean write_stencil); + #else static INLINE void diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c index 6cad7d3216e..b540a79331b 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.c +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -15,6 +15,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "program/program.h" #include "program/prog_print.h" @@ -220,7 +221,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, } } - pipe_buffer_unmap(pipe, vbuffer, vbuffer_transfer); + pipe_buffer_unmap(pipe, vbuffer_transfer); #undef SET_ATTRIB } diff --git a/src/mesa/state_tracker/st_cb_drawtex.h b/src/mesa/state_tracker/st_cb_drawtex.h index d21262f8977..455da04e674 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.h +++ b/src/mesa/state_tracker/st_cb_drawtex.h @@ -11,6 +11,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; struct st_context; diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c index c4b84de790c..dfde821fc19 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.c +++ b/src/mesa/state_tracker/st_cb_eglimage.c @@ -26,6 +26,7 @@ * Chia-I Wu <[email protected]> */ +#include "main/mfeatures.h" #include "main/texobj.h" #include "main/texfetch.h" #include "main/teximage.h" diff --git a/src/mesa/state_tracker/st_cb_eglimage.h b/src/mesa/state_tracker/st_cb_eglimage.h index b6e44d5aff5..48567ed9da5 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.h +++ b/src/mesa/state_tracker/st_cb_eglimage.h @@ -30,6 +30,7 @@ #define ST_CB_EGLIMAGE_H #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 9425f07aee6..0c7641f8623 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -38,6 +38,7 @@ #include "main/fbobject.h" #include "main/framebuffer.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "main/renderbuffer.h" #include "pipe/p_context.h" @@ -52,6 +53,7 @@ #include "util/u_format.h" #include "util/u_inlines.h" +#include "util/u_surface.h" /** @@ -60,19 +62,23 @@ * during window resize. */ static GLboolean -st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, +st_renderbuffer_alloc_storage(struct gl_context * ctx, + struct gl_renderbuffer *rb, GLenum internalFormat, GLuint width, GLuint height) { struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = st->pipe->screen; struct st_renderbuffer *strb = st_renderbuffer(rb); enum pipe_format format; + struct pipe_surface surf_tmpl; if (strb->format != PIPE_FORMAT_NONE) format = strb->format; else - format = st_choose_renderbuffer_format(screen, internalFormat, rb->NumSamples); + format = st_choose_renderbuffer_format(screen, internalFormat, + rb->NumSamples); /* init renderbuffer fields */ strb->Base.Width = width; @@ -113,6 +119,7 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *r template.width0 = width; template.height0 = height; template.depth0 = 1; + template.array_size = 1; template.last_level = 0; template.nr_samples = rb->NumSamples; if (util_format_is_depth_or_stencil(format)) { @@ -120,7 +127,7 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *r } else { template.bind = (PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_RENDER_TARGET); + PIPE_BIND_RENDER_TARGET); } strb->texture = screen->resource_create(screen, &template); @@ -128,10 +135,11 @@ st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *r if (!strb->texture) return FALSE; - strb->surface = screen->get_tex_surface(screen, - strb->texture, - 0, 0, 0, - template.bind); + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + u_surface_default_template(&surf_tmpl, strb->texture, template.bind); + strb->surface = pipe->create_surface(pipe, + strb->texture, + &surf_tmpl); if (strb->surface) { assert(strb->surface->texture); assert(strb->surface->format); @@ -327,12 +335,12 @@ st_render_texture(struct gl_context *ctx, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *strb; struct gl_renderbuffer *rb; struct pipe_resource *pt = st_get_texobj_resource(att->Texture); struct st_texture_object *stObj; const struct gl_texture_image *texImage; + struct pipe_surface surf_tmpl; /* When would this fail? Perhaps assert? */ if (!pt) @@ -381,12 +389,15 @@ st_render_texture(struct gl_context *ctx, assert(strb->rtt_level <= strb->texture->last_level); /* 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_BIND_RENDER_TARGET); + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = strb->texture->format; + surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; + surf_tmpl.u.tex.level = strb->rtt_level; + surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; + surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; + strb->surface = pipe->create_surface(pipe, + strb->texture, + &surf_tmpl); strb->format = pt->format; diff --git a/src/mesa/state_tracker/st_cb_feedback.c b/src/mesa/state_tracker/st_cb_feedback.c index 5c01856f033..9b85a39bedd 100644 --- a/src/mesa/state_tracker/st_cb_feedback.c +++ b/src/mesa/state_tracker/st_cb_feedback.c @@ -40,6 +40,7 @@ #include "main/imports.h" #include "main/context.h" #include "main/feedback.h" +#include "main/mfeatures.h" #include "vbo/vbo.h" diff --git a/src/mesa/state_tracker/st_cb_feedback.h b/src/mesa/state_tracker/st_cb_feedback.h index f2342f58238..02e34e40271 100644 --- a/src/mesa/state_tracker/st_cb_feedback.h +++ b/src/mesa/state_tracker/st_cb_feedback.h @@ -31,6 +31,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index 4d83fcc6ccb..32694975d17 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -46,16 +46,13 @@ #include "st_cb_program.h" -static GLuint SerialNo = 1; - /** * Called via ctx->Driver.BindProgram() to bind an ARB vertex or * fragment program. */ -static void st_bind_program( struct gl_context *ctx, - GLenum target, - struct gl_program *prog ) +static void +st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog) { struct st_context *st = st_context(ctx); @@ -77,7 +74,8 @@ static void st_bind_program( struct gl_context *ctx, * Called via ctx->Driver.UseProgram() to bind a linked GLSL program * (vertex shader + fragment shader). */ -static void st_use_program( struct gl_context *ctx, struct gl_shader_program *shProg) +static void +st_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) { struct st_context *st = st_context(ctx); @@ -87,48 +85,28 @@ static void st_use_program( struct gl_context *ctx, struct gl_shader_program *sh } - /** * Called via ctx->Driver.NewProgram() to allocate a new vertex or * fragment program. */ -static struct gl_program *st_new_program( struct gl_context *ctx, - GLenum target, - GLuint id ) +static struct gl_program * +st_new_program(struct gl_context *ctx, GLenum target, GLuint id) { switch (target) { case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_vertex_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_vertex_program(ctx, &prog->Base, target, id); } case GL_FRAGMENT_PROGRAM_ARB: case GL_FRAGMENT_PROGRAM_NV: { struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_fragment_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_fragment_program(ctx, &prog->Base, target, id); } case MESA_GEOMETRY_PROGRAM: { struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_geometry_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_geometry_program(ctx, &prog->Base, target, id); } default: @@ -138,7 +116,10 @@ static struct gl_program *st_new_program( struct gl_context *ctx, } -void +/** + * Called via ctx->Driver.DeleteProgram() + */ +static void st_delete_program(struct gl_context *ctx, struct gl_program *prog) { struct st_context *st = st_context(ctx); @@ -147,17 +128,15 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - st_vp_release_varients( st, stvp ); + st_release_vp_variants( st, stvp ); } break; case MESA_GEOMETRY_PROGRAM: { - struct st_geometry_program *stgp = (struct st_geometry_program *) prog; + struct st_geometry_program *stgp = + (struct st_geometry_program *) prog; - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } + st_release_gp_variants(st, stgp); if (stgp->tgsi.tokens) { st_free_tokens((void *) stgp->tgsi.tokens); @@ -167,23 +146,15 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) break; case GL_FRAGMENT_PROGRAM_ARB: { - struct st_fragment_program *stfp = (struct st_fragment_program *) prog; + struct st_fragment_program *stfp = + (struct st_fragment_program *) prog; - if (stfp->driver_shader) { - cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); - stfp->driver_shader = NULL; - } + st_release_fp_variants(st, stfp); if (stfp->tgsi.tokens) { st_free_tokens(stfp->tgsi.tokens); stfp->tgsi.tokens = NULL; } - - if (stfp->bitmap_program) { - struct gl_program *prg = &stfp->bitmap_program->Base.Base; - _mesa_reference_program(ctx, &prg, NULL); - stfp->bitmap_program = NULL; - } } break; default: @@ -195,15 +166,25 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) } -static GLboolean st_is_program_native( struct gl_context *ctx, - GLenum target, - struct gl_program *prog ) +/** + * Called via ctx->Driver.IsProgramNative() + */ +static GLboolean +st_is_program_native(struct gl_context *ctx, + GLenum target, + struct gl_program *prog) { return GL_TRUE; } -static GLboolean st_program_string_notify( struct gl_context *ctx, +/** + * Called via ctx->Driver.ProgramStringNotify() + * Called when the program's text/code is changed. We have to free + * all shader variants and corresponding gallium shaders when this happens. + */ +static GLboolean +st_program_string_notify( struct gl_context *ctx, GLenum target, struct gl_program *prog ) { @@ -212,12 +193,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, if (target == GL_FRAGMENT_PROGRAM_ARB) { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; - stfp->serialNo++; - - if (stfp->driver_shader) { - cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); - stfp->driver_shader = NULL; - } + st_release_fp_variants(st, stfp); if (stfp->tgsi.tokens) { st_free_tokens(stfp->tgsi.tokens); @@ -230,12 +206,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, else if (target == MESA_GEOMETRY_PROGRAM) { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; - stgp->serialNo++; - - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } + st_release_gp_variants(st, stgp); if (stgp->tgsi.tokens) { st_free_tokens((void *) stgp->tgsi.tokens); @@ -248,9 +219,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, else if (target == GL_VERTEX_PROGRAM_ARB) { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - stvp->serialNo++; - - st_vp_release_varients( st, stvp ); + st_release_vp_variants( st, stvp ); if (st->vp == stvp) st->dirty.st |= ST_NEW_VERTEX_PROGRAM; @@ -261,8 +230,11 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, } - -void st_init_program_functions(struct dd_function_table *functions) +/** + * Plug in the program and shader-related device driver functions. + */ +void +st_init_program_functions(struct dd_function_table *functions) { functions->BindProgram = st_bind_program; functions->UseProgram = st_use_program; diff --git a/src/mesa/state_tracker/st_cb_program.h b/src/mesa/state_tracker/st_cb_program.h index 004afb6d812..091a4439c48 100644 --- a/src/mesa/state_tracker/st_cb_program.h +++ b/src/mesa/state_tracker/st_cb_program.h @@ -29,15 +29,10 @@ #define ST_CB_PROGRAM_H -#include "main/mtypes.h" - struct dd_function_table; extern void st_init_program_functions(struct dd_function_table *functions); -extern void -st_delete_program(struct gl_context *ctx, struct gl_program *prog); - #endif diff --git a/src/mesa/state_tracker/st_cb_queryobj.c b/src/mesa/state_tracker/st_cb_queryobj.c index aa31b3710b5..d0ac253bcec 100644 --- a/src/mesa/state_tracker/st_cb_queryobj.c +++ b/src/mesa/state_tracker/st_cb_queryobj.c @@ -35,6 +35,7 @@ #include "main/imports.h" #include "main/context.h" +#include "main/mfeatures.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -84,6 +85,8 @@ st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q) /* convert GL query type to Gallium query type */ switch (q->Target) { + case GL_ANY_SAMPLES_PASSED: + /* fall-through */ case GL_SAMPLES_PASSED_ARB: type = PIPE_QUERY_OCCLUSION_COUNTER; break; diff --git a/src/mesa/state_tracker/st_cb_queryobj.h b/src/mesa/state_tracker/st_cb_queryobj.h index 017471b0b06..03f0be8372b 100644 --- a/src/mesa/state_tracker/st_cb_queryobj.h +++ b/src/mesa/state_tracker/st_cb_queryobj.h @@ -29,6 +29,7 @@ #define ST_CB_QUERYOBJ_H +#include "main/mfeatures.h" #include "main/mtypes.h" /** diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c index 15a4f602d1d..32d465c5cce 100644 --- a/src/mesa/state_tracker/st_cb_rasterpos.c +++ b/src/mesa/state_tracker/st_cb_rasterpos.c @@ -38,6 +38,7 @@ #include "main/imports.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "main/feedback.h" #include "st_context.h" diff --git a/src/mesa/state_tracker/st_cb_rasterpos.h b/src/mesa/state_tracker/st_cb_rasterpos.h index 2dc109bb184..b61411bd20c 100644 --- a/src/mesa/state_tracker/st_cb_rasterpos.h +++ b/src/mesa/state_tracker/st_cb_rasterpos.h @@ -30,6 +30,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index bcd46ac9d54..0507be74578 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -80,7 +80,7 @@ st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, /* Create a read transfer from the renderbuffer's texture */ pt = pipe_get_transfer(pipe, strb->texture, - 0, 0, 0, /* face, level, zslice */ + 0, 0, PIPE_TRANSFER_READ, x, y, width, height); @@ -236,7 +236,7 @@ st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb, } trans = pipe_get_transfer(pipe, strb->texture, - 0, 0, 0, /* face, level, zslice */ + 0, 0, PIPE_TRANSFER_READ, x, y, width, height); if (!trans) { @@ -328,7 +328,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - GLfloat temp[MAX_WIDTH][4]; + GLfloat (*temp)[4]; const GLbitfield transferOps = ctx->_ImageTransferState; GLsizei i, j; GLint yStep, dfStride; @@ -381,6 +381,13 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h return; } + /* allocate temp pixel row buffer */ + temp = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat)); + if (!temp) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); + return; + } + if (format == GL_RGBA && type == GL_FLOAT) { /* write tile(row) directly into user's buffer */ df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width, @@ -400,7 +407,7 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h /* Create a read transfer from the renderbuffer's texture */ trans = pipe_get_transfer(pipe, strb->texture, - 0, 0, 0, /* face, level, zslice */ + 0, 0, PIPE_TRANSFER_READ, x, y, width, height); @@ -533,6 +540,8 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei h } } + free(temp); + pipe->transfer_destroy(pipe, trans); _mesa_unmap_pbo_dest(ctx, &clippedPacking); diff --git a/src/mesa/state_tracker/st_cb_readpixels.h b/src/mesa/state_tracker/st_cb_readpixels.h index 83c9b659e3d..9622ae6feea 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.h +++ b/src/mesa/state_tracker/st_cb_readpixels.h @@ -29,9 +29,11 @@ #ifndef ST_CB_READPIXELS_H #define ST_CB_READPIXELS_H -#include "main/mtypes.h" +#include "main/glheader.h" struct dd_function_table; +struct gl_context; +struct gl_pixelstore_attrib; extern struct st_renderbuffer * st_get_color_read_renderbuffer(struct gl_context *ctx); diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 15e69e1fa07..09a10ba5819 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -63,7 +63,7 @@ #include "util/u_surface.h" #include "util/u_sampler.h" #include "util/u_math.h" - +#include "util/u_box.h" #define DBG if (0) printf @@ -431,7 +431,7 @@ compress_with_blit(struct gl_context * ctx, struct pipe_resource *src_tex; struct pipe_sampler_view view_templ; struct pipe_sampler_view *src_view; - struct pipe_surface *dst_surface; + struct pipe_surface *dst_surface, surf_tmpl; struct pipe_transfer *tex_xfer; void *map; @@ -441,9 +441,13 @@ compress_with_blit(struct gl_context * ctx, } /* get destination surface (in the compressed texture) */ - dst_surface = screen->get_tex_surface(screen, stImage->pt, - stImage->face, stImage->level, 0, - 0 /* flags */); + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = stImage->pt->format; + surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; + surf_tmpl.u.tex.level = stImage->level; + surf_tmpl.u.tex.first_layer = stImage->face; + surf_tmpl.u.tex.last_layer = stImage->face; + dst_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl); if (!dst_surface) { /* can't render into this format (or other problem) */ return GL_FALSE; @@ -464,6 +468,7 @@ compress_with_blit(struct gl_context * ctx, templ.width0 = width; templ.height0 = height; templ.depth0 = 1; + templ.array_size = 1; templ.last_level = 0; templ.usage = PIPE_USAGE_DEFAULT; templ.bind = PIPE_BIND_SAMPLER_VIEW; @@ -475,9 +480,9 @@ compress_with_blit(struct gl_context * ctx, /* Put user's tex data into the temporary texture */ tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex, - 0, 0, 0, /* face, level are zero */ - PIPE_TRANSFER_WRITE, - 0, 0, width, height); /* x, y, w, h */ + 0, 0, /* layer, level are zero */ + PIPE_TRANSFER_WRITE, + 0, 0, width, height); /* x, y, w, h */ map = pipe_transfer_map(pipe, tex_xfer); _mesa_texstore(ctx, 2, GL_RGBA, mesa_format, @@ -857,7 +862,6 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; - struct pipe_screen *screen = pipe->screen; struct st_texture_image *stImage = st_texture_image(texImage); struct st_texture_object *stObj = st_texture_object(texObj); struct pipe_sampler_view *src_view = @@ -871,7 +875,7 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, PIPE_BIND_TRANSFER_READ); /* create temp / dest surface */ - if (!util_create_rgba_surface(screen, width, height, bind, + if (!util_create_rgba_surface(pipe, width, height, bind, &dst_texture, &dst_surface)) { _mesa_problem(ctx, "util_create_rgba_surface() failed " "in decompress_with_blit()"); @@ -891,9 +895,9 @@ decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, /* map the dst_surface so we can read from it */ tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, - dst_texture, 0, 0, 0, - PIPE_TRANSFER_READ, - 0, 0, width, height); + dst_texture, 0, 0, + PIPE_TRANSFER_READ, + 0, 0, width, height); pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); @@ -1310,7 +1314,7 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, struct pipe_transfer *src_trans; GLvoid *texDest; enum pipe_transfer_usage transfer_usage; - + if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -1321,11 +1325,11 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, } src_trans = pipe_get_transfer(st_context(ctx)->pipe, - strb->texture, - 0, 0, 0, - PIPE_TRANSFER_READ, - srcX, srcY, - width, height); + strb->texture, + 0, 0, + PIPE_TRANSFER_READ, + srcX, srcY, + width, height); if ((baseFormat == GL_DEPTH_COMPONENT || baseFormat == GL_DEPTH_STENCIL) && @@ -1334,7 +1338,8 @@ fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, else transfer_usage = PIPE_TRANSFER_WRITE; - texDest = st_texture_image_map(st, stImage, 0, transfer_usage, + /* XXX this used to ignore destZ param */ + texDest = st_texture_image_map(st, stImage, destZ, transfer_usage, destX, destY, width, height); if (baseFormat == GL_DEPTH_COMPONENT || @@ -1523,6 +1528,9 @@ st_copy_texsubimage(struct gl_context *ctx, if (texBaseFormat == GL_DEPTH_COMPONENT || texBaseFormat == GL_DEPTH_STENCIL) { strb = st_renderbuffer(fb->_DepthBuffer); + if (strb->Base.Wrapped) { + strb = st_renderbuffer(strb->Base.Wrapped); + } } else { /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */ @@ -1592,27 +1600,23 @@ st_copy_texsubimage(struct gl_context *ctx, if (matching_base_formats && src_format == dest_format && - !do_flip) + !do_flip) { /* use surface_copy() / blit */ - struct pipe_subresource subdst, subsrc; - subdst.face = stImage->face; - subdst.level = stImage->level; - subsrc.face = strb->surface->face; - subsrc.level = strb->surface->level; + struct pipe_box src_box; + u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer, + width, height, &src_box); /* for resource_copy_region(), y=0=top, always */ pipe->resource_copy_region(pipe, /* dest */ stImage->pt, - subdst, - destX, destY, destZ, + stImage->level, + destX, destY, destZ + stImage->face, /* src */ strb->texture, - subsrc, - srcX, srcY, strb->surface->zslice, - /* size */ - width, height); + strb->surface->u.tex.level, + &src_box); use_fallback = GL_FALSE; } else if (format_writemask && @@ -1628,12 +1632,16 @@ st_copy_texsubimage(struct gl_context *ctx, 0)) { /* draw textured quad to do the copy */ GLint srcY0, srcY1; - struct pipe_subresource subsrc; + struct pipe_surface surf_tmpl; + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = stImage->pt->format; + surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; + surf_tmpl.u.tex.level = stImage->level; + surf_tmpl.u.tex.first_layer = stImage->face + destZ; + surf_tmpl.u.tex.last_layer = stImage->face + destZ; - dest_surface = screen->get_tex_surface(screen, stImage->pt, - stImage->face, stImage->level, - destZ, - PIPE_BIND_RENDER_TARGET); + dest_surface = pipe->create_surface(pipe, stImage->pt, + &surf_tmpl); if (do_flip) { srcY1 = strb->Base.Height - srcY - height; @@ -1643,15 +1651,13 @@ st_copy_texsubimage(struct gl_context *ctx, srcY0 = srcY; srcY1 = srcY0 + height; } - subsrc.face = strb->surface->face; - subsrc.level = strb->surface->level; util_blit_pixels_writemask(st->blit, strb->texture, - subsrc, + strb->surface->u.tex.level, srcX, srcY0, srcX + width, srcY1, - strb->surface->zslice, + strb->surface->u.tex.first_layer, dest_surface, destX, destY, destX + width, destY + height, @@ -1853,7 +1859,7 @@ st_finalize_texture(struct gl_context *ctx, */ if (firstImage->pt && firstImage->pt != stObj->pt && - firstImage->pt->last_level >= stObj->lastLevel) { + (!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) { pipe_resource_reference(&stObj->pt, firstImage->pt); pipe_sampler_view_reference(&stObj->sampler_view, NULL); } diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h index 60987055eb1..f1502bda788 100644 --- a/src/mesa/state_tracker/st_cb_texture.h +++ b/src/mesa/state_tracker/st_cb_texture.h @@ -31,9 +31,10 @@ #include "main/glheader.h" -#include "main/mtypes.h" struct dd_function_table; +struct gl_context; +struct gl_texture_object; struct pipe_context; struct st_context; diff --git a/src/mesa/state_tracker/st_cb_xformfb.c b/src/mesa/state_tracker/st_cb_xformfb.c index 838a0a4a934..e415b186aa7 100644 --- a/src/mesa/state_tracker/st_cb_xformfb.c +++ b/src/mesa/state_tracker/st_cb_xformfb.c @@ -35,6 +35,7 @@ #include "main/imports.h" #include "main/context.h" +#include "main/mfeatures.h" #include "main/transformfeedback.h" #include "st_cb_xformfb.h" diff --git a/src/mesa/state_tracker/st_cb_xformfb.h b/src/mesa/state_tracker/st_cb_xformfb.h index 574cf481e18..1215ebea871 100644 --- a/src/mesa/state_tracker/st_cb_xformfb.h +++ b/src/mesa/state_tracker/st_cb_xformfb.h @@ -30,6 +30,7 @@ #include "main/compiler.h" +#include "main/mfeatures.h" struct dd_function_table; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index d6628b1bff0..c7f3949bf9e 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -207,12 +207,6 @@ static void st_destroy_context_priv( struct st_context *st ) pipe_sampler_view_reference(&st->state.sampler_views[i], NULL); } - for (i = 0; i < Elements(st->state.constants); i++) { - if (st->state.constants[i]) { - pipe_resource_reference(&st->state.constants[i], NULL); - } - } - if (st->default_texture) { st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture); st->default_texture = NULL; @@ -244,14 +238,15 @@ void st_destroy_context( struct st_context *st ) pipe->set_index_buffer(pipe, NULL); for (i = 0; i < PIPE_SHADER_TYPES; i++) { - pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, NULL); - pipe_resource_reference(&st->state.constants[PIPE_SHADER_VERTEX], NULL); + pipe->set_constant_buffer(pipe, i, 0, NULL); } _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache); _vbo_DestroyContext(st->ctx); + st_destroy_program_variants(st); + _mesa_free_context_data(ctx); st_destroy_context_priv(st); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index d342c0cff1e..64a8f790e22 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -1,4 +1,3 @@ -//struct dd_function_table; /************************************************************************** * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. @@ -93,7 +92,10 @@ struct st_context struct pipe_sampler_state samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state *sampler_list[PIPE_MAX_SAMPLERS]; struct pipe_clip_state clip; - struct pipe_resource *constants[PIPE_SHADER_TYPES]; + struct { + void *ptr; + unsigned size; + } constants[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_scissor_state scissor; @@ -106,15 +108,6 @@ struct st_context GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */ } state; - struct { - struct st_tracked_state tracked_state[PIPE_SHADER_TYPES]; - } constants; - - /* XXX unused: */ - struct { - struct gl_fragment_program *fragment_program; - } cb; - char vendor[100]; char renderer[100]; @@ -130,7 +123,9 @@ struct st_context struct st_fragment_program *fp; /**< Currently bound fragment program */ struct st_geometry_program *gp; /**< Currently bound geometry program */ - struct st_vp_varient *vp_varient; + struct st_vp_variant *vp_variant; + struct st_fp_variant *fp_variant; + struct st_gp_variant *gp_variant; struct gl_texture_object *default_texture; @@ -160,7 +155,7 @@ struct st_context /** for glDraw/CopyPixels */ struct { - struct st_fragment_program *shaders[4]; + struct gl_fragment_program *shaders[4]; void *vert_shaders[2]; /**< ureg shaders */ } drawpix; diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c index df32491d044..e1e373d07d4 100644 --- a/src/mesa/state_tracker/st_debug.c +++ b/src/mesa/state_tracker/st_debug.c @@ -89,8 +89,8 @@ st_print_current(void) } #endif - if (st->vp->varients) - tgsi_dump( st->vp->varients[0].tgsi.tokens, 0 ); + if (st->vp->variants) + tgsi_dump( st->vp->variants[0].tgsi.tokens, 0 ); if (st->vp->Base.Base.Parameters) _mesa_print_parameter_list(st->vp->Base.Base.Parameters); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 61a0e1b0877..db70daacc48 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -43,6 +43,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "program/prog_uniform.h" #include "vbo/vbo.h" @@ -241,7 +242,7 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, */ static GLboolean is_interleaved_arrays(const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, GLboolean *userSpace) { @@ -297,7 +298,7 @@ is_interleaved_arrays(const struct st_vertex_program *vp, */ static void get_arrays_bounds(const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, GLuint max_index, const GLubyte **low, const GLubyte **high) @@ -343,7 +344,7 @@ get_arrays_bounds(const struct st_vertex_program *vp, static void setup_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, GLuint max_index, GLboolean userSpace, @@ -409,7 +410,7 @@ setup_interleaved_attribs(struct gl_context *ctx, static void setup_non_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, GLuint max_index, GLboolean *userSpace, @@ -617,7 +618,7 @@ st_draw_vbo(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; const struct st_vertex_program *vp; - const struct st_vp_varient *vpv; + const struct st_vp_variant *vpv; struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; GLuint attr; struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; @@ -650,7 +651,7 @@ st_draw_vbo(struct gl_context *ctx, /* must get these after state validation! */ vp = st->vp; - vpv = st->vp_varient; + vpv = st->vp_variant; #if 0 if (MESA_VERBOSE & VERBOSE_GLSL) { diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h index 2e4c468cff5..5d3c278228f 100644 --- a/src/mesa/state_tracker/st_draw.h +++ b/src/mesa/state_tracker/st_draw.h @@ -36,10 +36,11 @@ #include "main/compiler.h" #include "main/glheader.h" -#include "main/mtypes.h" struct _mesa_index_buffer; struct _mesa_prim; +struct gl_client_array; +struct gl_context; struct st_context; void st_init_draw( struct st_context *st ); diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index 7f392fc4916..4e76a050701 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -28,6 +28,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "vbo/vbo.h" @@ -109,9 +110,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, struct pipe_index_buffer ibuffer; struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; struct pipe_transfer *ib_transfer = NULL; - struct pipe_transfer *cb_transfer; GLuint attr, i; - ubyte *mapped_constants; const void *mapped_indices = NULL; assert(draw); @@ -123,10 +122,10 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* must get these after state validation! */ vp = st->vp; - vs = &st->vp_varient->tgsi; + vs = &st->vp_variant->tgsi; - if (!st->vp_varient->draw_shader) { - st->vp_varient->draw_shader = draw_create_vertex_shader(draw, vs); + if (!st->vp_variant->draw_shader) { + st->vp_variant->draw_shader = draw_create_vertex_shader(draw, vs); } /* @@ -139,7 +138,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, draw_set_viewport_state(draw, &st->state.viewport); draw_set_clip_state(draw, &st->state.clip); draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL); - draw_bind_vertex_shader(draw, st->vp_varient->draw_shader); + draw_bind_vertex_shader(draw, st->vp_variant->draw_shader); set_feedback_vertex_format(ctx); /* loop over TGSI shader inputs to determine vertex buffer @@ -242,14 +241,10 @@ st_feedback_draw_vbo(struct gl_context *ctx, draw_set_mapped_index_buffer(draw, mapped_indices); } - /* map constant buffers */ - mapped_constants = pipe_buffer_map(pipe, - st->state.constants[PIPE_SHADER_VERTEX], - PIPE_TRANSFER_READ, - &cb_transfer); + /* set the constant buffer */ draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0, - mapped_constants, - st->state.constants[PIPE_SHADER_VERTEX]->width0); + st->state.constants[PIPE_SHADER_VERTEX].ptr, + st->state.constants[PIPE_SHADER_VERTEX].size); /* draw here */ @@ -258,17 +253,12 @@ st_feedback_draw_vbo(struct gl_context *ctx, } - /* unmap constant buffers */ - pipe_buffer_unmap(pipe, st->state.constants[PIPE_SHADER_VERTEX], - cb_transfer); - /* * unmap vertex/index buffers */ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (draw->pt.vertex_buffer[i].buffer) { - pipe_buffer_unmap(pipe, draw->pt.vertex_buffer[i].buffer, - vb_transfer[i]); + pipe_buffer_unmap(pipe, vb_transfer[i]); pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL); draw_set_mapped_vertex_buffer(draw, i, NULL); } @@ -279,7 +269,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, draw_set_index_buffer(draw, NULL); if (ib_transfer) - pipe_buffer_unmap(pipe, ibuffer.buffer, ib_transfer); + pipe_buffer_unmap(pipe, ib_transfer); pipe_resource_reference(&ibuffer.buffer, NULL); } } diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 37a0aa2bc9f..df4f5cf8b5c 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -29,6 +29,7 @@ #include "main/imports.h" #include "main/context.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -224,6 +225,7 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE; ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; ctx->Extensions.ARB_fragment_program = GL_TRUE; + ctx->Extensions.ARB_half_float_pixel = GL_TRUE; ctx->Extensions.ARB_map_buffer_range = GL_TRUE; ctx->Extensions.ARB_multisample = GL_TRUE; ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */ @@ -343,6 +345,7 @@ void st_init_extensions(struct st_context *st) if (screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY)) { ctx->Extensions.ARB_occlusion_query = GL_TRUE; + ctx->Extensions.ARB_occlusion_query2 = GL_TRUE; } if (screen->get_param(screen, PIPE_CAP_TIMER_QUERY)) { ctx->Extensions.EXT_timer_query = GL_TRUE; @@ -442,7 +445,9 @@ void st_init_extensions(struct st_context *st) #endif if (screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { +#if 0 /* XXX re-enable when GLSL compiler again supports geometry shaders */ ctx->Extensions.ARB_geometry_shader4 = GL_TRUE; +#endif } if (screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) { diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c index 955d821a657..2e0a664dd01 100644 --- a/src/mesa/state_tracker/st_format.c +++ b/src/mesa/state_tracker/st_format.c @@ -37,6 +37,7 @@ #include "main/texstore.h" #include "main/image.h" #include "main/macros.h" +#include "main/mfeatures.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" @@ -146,14 +147,28 @@ st_mesa_format_to_pipe_format(gl_format mesaFormat) return PIPE_FORMAT_B4G4R4A4_UNORM; case MESA_FORMAT_RGB565: return PIPE_FORMAT_B5G6R5_UNORM; + case MESA_FORMAT_RGB332: + return PIPE_FORMAT_B2G3R3_UNORM; + case MESA_FORMAT_ARGB2101010: + return PIPE_FORMAT_B10G10R10A2_UNORM; + case MESA_FORMAT_AL44: + return PIPE_FORMAT_L4A4_UNORM; case MESA_FORMAT_AL88: return PIPE_FORMAT_L8A8_UNORM; + case MESA_FORMAT_AL1616: + return PIPE_FORMAT_L16A16_UNORM; case MESA_FORMAT_A8: return PIPE_FORMAT_A8_UNORM; + case MESA_FORMAT_A16: + return PIPE_FORMAT_A16_UNORM; case MESA_FORMAT_L8: return PIPE_FORMAT_L8_UNORM; + case MESA_FORMAT_L16: + return PIPE_FORMAT_L16_UNORM; case MESA_FORMAT_I8: return PIPE_FORMAT_I8_UNORM; + case MESA_FORMAT_I16: + return PIPE_FORMAT_I16_UNORM; case MESA_FORMAT_Z16: return PIPE_FORMAT_Z16_UNORM; case MESA_FORMAT_Z32: @@ -261,14 +276,28 @@ st_pipe_format_to_mesa_format(enum pipe_format format) return MESA_FORMAT_ARGB4444; case PIPE_FORMAT_B5G6R5_UNORM: return MESA_FORMAT_RGB565; + case PIPE_FORMAT_B2G3R3_UNORM: + return MESA_FORMAT_RGB332; + case PIPE_FORMAT_B10G10R10A2_UNORM: + return MESA_FORMAT_ARGB2101010; + case PIPE_FORMAT_L4A4_UNORM: + return MESA_FORMAT_AL44; case PIPE_FORMAT_L8A8_UNORM: return MESA_FORMAT_AL88; + case PIPE_FORMAT_L16A16_UNORM: + return MESA_FORMAT_AL1616; case PIPE_FORMAT_A8_UNORM: return MESA_FORMAT_A8; + case PIPE_FORMAT_A16_UNORM: + return MESA_FORMAT_A16; case PIPE_FORMAT_L8_UNORM: return MESA_FORMAT_L8; + case PIPE_FORMAT_L16_UNORM: + return MESA_FORMAT_L16; case PIPE_FORMAT_I8_UNORM: return MESA_FORMAT_I8; + case PIPE_FORMAT_I16_UNORM: + return MESA_FORMAT_I16; case PIPE_FORMAT_S8_USCALED: return MESA_FORMAT_S8; @@ -469,17 +498,27 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, unsigned geom_flags = 0; /* we don't care about POT vs. NPOT here, yet */ switch (internalFormat) { + case GL_RGB10: + case GL_RGB10_A2: + if (screen->is_format_supported( screen, PIPE_FORMAT_B10G10R10A2_UNORM, + target, sample_count, bindings, + geom_flags )) + return PIPE_FORMAT_B10G10R10A2_UNORM; + /* Pass through. */ case 4: case GL_RGBA: case GL_RGBA8: - case GL_RGB10_A2: return default_rgba_format( screen, target, sample_count, bindings, geom_flags ); case 3: case GL_RGB: + case GL_RGB8: return default_rgb_format( screen, target, sample_count, bindings, geom_flags ); + + case GL_RGB12: + case GL_RGB16: case GL_RGBA12: case GL_RGBA16: if (screen->is_format_supported( screen, PIPE_FORMAT_R16G16B16A16_UNORM, @@ -506,16 +545,14 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return default_rgba_format( screen, target, sample_count, bindings, geom_flags ); - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - return default_rgb_format( screen, target, sample_count, bindings, - geom_flags ); - + case GL_R3_G3_B2: + if (screen->is_format_supported( screen, PIPE_FORMAT_B2G3R3_UNORM, + target, sample_count, bindings, + geom_flags )) + return PIPE_FORMAT_B2G3R3_UNORM; + /* Pass through. */ case GL_RGB5: case GL_RGB4: - case GL_R3_G3_B2: if (screen->is_format_supported( screen, PIPE_FORMAT_B5G6R5_UNORM, target, sample_count, bindings, geom_flags )) @@ -527,11 +564,15 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return default_rgba_format( screen, target, sample_count, bindings, geom_flags ); + case GL_ALPHA12: + case GL_ALPHA16: + if (screen->is_format_supported( screen, PIPE_FORMAT_A16_UNORM, target, + sample_count, bindings, geom_flags )) + return PIPE_FORMAT_A16_UNORM; + /* Pass through. */ case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: case GL_COMPRESSED_ALPHA: if (screen->is_format_supported( screen, PIPE_FORMAT_A8_UNORM, target, sample_count, bindings, geom_flags )) @@ -539,12 +580,16 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return default_rgba_format( screen, target, sample_count, bindings, geom_flags ); + case GL_LUMINANCE12: + case GL_LUMINANCE16: + if (screen->is_format_supported( screen, PIPE_FORMAT_L16_UNORM, target, + sample_count, bindings, geom_flags )) + return PIPE_FORMAT_L16_UNORM; + /* Pass through. */ case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: case GL_COMPRESSED_LUMINANCE: if (screen->is_format_supported( screen, PIPE_FORMAT_L8_UNORM, target, sample_count, bindings, geom_flags )) @@ -552,14 +597,17 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return default_rgba_format( screen, target, sample_count, bindings, geom_flags ); + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + if (screen->is_format_supported( screen, PIPE_FORMAT_L16A16_UNORM, target, + sample_count, bindings, geom_flags )) + return PIPE_FORMAT_L16A16_UNORM; + /* Pass through. */ case 2: case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE6_ALPHA2: case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: case GL_COMPRESSED_LUMINANCE_ALPHA: if (screen->is_format_supported( screen, PIPE_FORMAT_L8A8_UNORM, target, sample_count, bindings, geom_flags )) @@ -567,11 +615,25 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, return default_rgba_format( screen, target, sample_count, bindings, geom_flags ); + case GL_LUMINANCE4_ALPHA4: + if (screen->is_format_supported( screen, PIPE_FORMAT_L4A4_UNORM, target, + sample_count, bindings, geom_flags )) + return PIPE_FORMAT_L4A4_UNORM; + if (screen->is_format_supported( screen, PIPE_FORMAT_L8A8_UNORM, target, + sample_count, bindings, geom_flags )) + return PIPE_FORMAT_L8A8_UNORM; + return default_rgba_format( screen, target, sample_count, bindings, + geom_flags ); + + case GL_INTENSITY12: + case GL_INTENSITY16: + if (screen->is_format_supported( screen, PIPE_FORMAT_I16_UNORM, target, + sample_count, bindings, geom_flags )) + return PIPE_FORMAT_I16_UNORM; + /* Pass through. */ case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: case GL_COMPRESSED_INTENSITY: if (screen->is_format_supported( screen, PIPE_FORMAT_I8_UNORM, target, sample_count, bindings, geom_flags )) @@ -680,10 +742,10 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_DEPTH_COMPONENT: { static const enum pipe_format formats[] = { - PIPE_FORMAT_Z16_UNORM, PIPE_FORMAT_Z32_UNORM, PIPE_FORMAT_Z24_UNORM_S8_USCALED, - PIPE_FORMAT_S8_USCALED_Z24_UNORM + PIPE_FORMAT_S8_USCALED_Z24_UNORM, + PIPE_FORMAT_Z16_UNORM }; return find_supported_format(screen, formats, Elements(formats), target, sample_count, bindings, geom_flags); @@ -717,18 +779,30 @@ st_choose_format(struct pipe_screen *screen, GLenum internalFormat, case GL_SRGB_EXT: case GL_SRGB8_EXT: - case GL_COMPRESSED_SRGB_EXT: - case GL_COMPRESSED_SRGB_ALPHA_EXT: case GL_SRGB_ALPHA_EXT: case GL_SRGB8_ALPHA8_EXT: return default_srgba_format( screen, target, sample_count, bindings, geom_flags ); + + case GL_COMPRESSED_SRGB_EXT: case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - return PIPE_FORMAT_DXT1_SRGB; + if (screen->is_format_supported(screen, PIPE_FORMAT_DXT1_SRGB, target, + sample_count, bindings, geom_flags)) + return PIPE_FORMAT_DXT1_SRGB; + return default_srgba_format( screen, target, sample_count, bindings, + geom_flags ); + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return PIPE_FORMAT_DXT1_SRGBA; + + case GL_COMPRESSED_SRGB_ALPHA_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - return PIPE_FORMAT_DXT3_SRGBA; + if (screen->is_format_supported(screen, PIPE_FORMAT_DXT3_SRGBA, target, + sample_count, bindings, geom_flags)) + return PIPE_FORMAT_DXT3_SRGBA; + return default_srgba_format( screen, target, sample_count, bindings, + geom_flags ); + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return PIPE_FORMAT_DXT5_SRGBA; @@ -955,8 +1029,13 @@ gl_format st_ChooseTextureFormat(struct gl_context *ctx, GLint internalFormat, GLenum format, GLenum type) { + boolean want_renderable = + internalFormat == 3 || internalFormat == 4 || + internalFormat == GL_RGB || internalFormat == GL_RGBA || + internalFormat == GL_RGB8 || internalFormat == GL_RGBA8; + return st_ChooseTextureFormat_renderable(ctx, internalFormat, - format, type, GL_TRUE); + format, type, want_renderable); } /** diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h index 43fa59b1006..fe195c1069b 100644 --- a/src/mesa/state_tracker/st_format.h +++ b/src/mesa/state_tracker/st_format.h @@ -31,11 +31,12 @@ #define ST_FORMAT_H #include "main/formats.h" -#include "main/mtypes.h" +#include "main/glheader.h" #include "pipe/p_defines.h" #include "pipe/p_format.h" +struct gl_context; struct pipe_screen; extern GLenum diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 1fc4f40488f..c5f6008a222 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -79,11 +79,15 @@ st_render_mipmap(struct st_context *st, const uint face = _mesa_tex_target_to_face(target); assert(psv->texture == stObj->pt); - assert(target != GL_TEXTURE_3D); /* not done yet */ +#if 0 + assert(target != GL_TEXTURE_3D); /* implemented but untested */ +#endif /* check if we can render in the texture's format */ - if (!screen->is_format_supported(screen, psv->format, psv->texture->target, 0, - PIPE_BIND_RENDER_TARGET, 0)) { + /* XXX should probably kill this and always use util_gen_mipmap + since this implements a sw fallback as well */ + if (!screen->is_format_supported(screen, psv->format, psv->texture->target, + 0, PIPE_BIND_RENDER_TARGET, 0)) { return FALSE; } @@ -161,12 +165,12 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, struct pipe_resource *pt = st_get_texobj_resource(texObj); const uint baseLevel = texObj->BaseLevel; const uint lastLevel = pt->last_level; - const uint face = _mesa_tex_target_to_face(target), zslice = 0; + const uint face = _mesa_tex_target_to_face(target); uint dstLevel; GLenum datatype; GLuint comps; GLboolean compressed; - + if (ST_DEBUG & DEBUG_FALLBACK) debug_printf("%s: fallback processing\n", __FUNCTION__); @@ -198,16 +202,15 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, ubyte *dstData; int srcStride, dstStride; - srcTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, face, - srcLevel, zslice, - PIPE_TRANSFER_READ, 0, 0, - srcWidth, srcHeight); - + srcTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, srcLevel, + face, + PIPE_TRANSFER_READ, 0, 0, + srcWidth, srcHeight); - dstTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, face, - dstLevel, zslice, - PIPE_TRANSFER_WRITE, 0, 0, - dstWidth, dstHeight); + dstTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, dstLevel, + face, + PIPE_TRANSFER_WRITE, 0, 0, + dstWidth, dstHeight); srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans); dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans); @@ -215,6 +218,8 @@ fallback_generate_mipmap(struct gl_context *ctx, GLenum target, srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format); dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format); + /* this cannot work correctly for 3d since it does + not respect layerStride. */ if (compressed) { const enum pipe_format format = pt->format; const uint bw = util_format_get_blockwidth(format); @@ -365,6 +370,12 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, pt = stObj->pt; } + else { + /* Make sure that the base texture image data is present in the + * texture buffer. + */ + st_finalize_texture(ctx, st->pipe, texObj); + } assert(pt->last_level >= lastLevel); @@ -372,6 +383,8 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, * use the software fallback. */ if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) { + /* since the util code actually also has a fallback, should + probably make it never fail and kill this */ fallback_generate_mipmap(ctx, target, texObj); } diff --git a/src/mesa/state_tracker/st_gen_mipmap.h b/src/mesa/state_tracker/st_gen_mipmap.h index 3ba091da151..815c6a51638 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.h +++ b/src/mesa/state_tracker/st_gen_mipmap.h @@ -30,8 +30,10 @@ #define ST_GEN_MIPMAP_H -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; +struct gl_texture_object; struct st_context; extern void diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index 05733e818ea..179e5dc8392 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -34,9 +34,11 @@ #include "util/u_pointer.h" #include "util/u_inlines.h" #include "util/u_atomic.h" +#include "util/u_surface.h" #include "main/mtypes.h" #include "main/context.h" +#include "main/mfeatures.h" #include "main/texobj.h" #include "main/teximage.h" #include "main/texstate.h" @@ -142,7 +144,7 @@ buffer_index_to_attachment(gl_buffer_index index) static void st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) { - struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *pipe = st->pipe; struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; uint width, height; unsigned i; @@ -160,7 +162,7 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) for (i = 0; i < stfb->num_statts; i++) { struct st_renderbuffer *strb; - struct pipe_surface *ps; + struct pipe_surface *ps, surf_tmpl; gl_buffer_index idx; if (!textures[i]) @@ -179,8 +181,10 @@ st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st) continue; } - ps = screen->get_tex_surface(screen, textures[i], 0, 0, 0, - PIPE_BIND_RENDER_TARGET); + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + u_surface_default_template(&surf_tmpl, textures[i], + PIPE_BIND_RENDER_TARGET); + ps = pipe->create_surface(pipe, textures[i], &surf_tmpl); if (ps) { pipe_surface_reference(&strb->surface, ps); pipe_resource_reference(&strb->texture, ps->texture); @@ -510,7 +514,8 @@ st_context_flush(struct st_context_iface *stctxi, unsigned flags, } static boolean -st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target, +st_context_teximage(struct st_context_iface *stctxi, + enum st_texture_type target, int level, enum pipe_format internal_format, struct pipe_resource *tex, boolean mipmap) { @@ -813,6 +818,7 @@ st_manager_flush_frontbuffer(struct st_context *st) /** * Return the surface of an EGLImage. + * FIXME: I think this should operate on resources, not surfaces */ struct pipe_surface * st_manager_get_egl_image_surface(struct st_context *st, @@ -821,7 +827,7 @@ st_manager_get_egl_image_surface(struct st_context *st, struct st_manager *smapi = (struct st_manager *) st->iface.st_context_private; struct st_egl_image stimg; - struct pipe_surface *ps; + struct pipe_surface *ps, surf_tmpl; if (!smapi || !smapi->get_egl_image) return NULL; @@ -830,8 +836,13 @@ st_manager_get_egl_image_surface(struct st_context *st, if (!smapi->get_egl_image(smapi, eglimg, &stimg)) return NULL; - ps = smapi->screen->get_tex_surface(smapi->screen, - stimg.texture, stimg.face, stimg.level, stimg.zslice, usage); + memset(&surf_tmpl, 0, sizeof(surf_tmpl)); + surf_tmpl.format = stimg.texture->format; + surf_tmpl.usage = usage; + surf_tmpl.u.tex.level = stimg.level; + surf_tmpl.u.tex.first_layer = stimg.layer; + surf_tmpl.u.tex.last_layer = stimg.layer; + ps = st->pipe->create_surface(st->pipe, stimg.texture, &surf_tmpl); pipe_resource_reference(&stimg.texture, NULL); return ps; @@ -856,7 +867,8 @@ st_manager_validate_framebuffers(struct st_context *st) * Add a color renderbuffer on demand. */ boolean -st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb, +st_manager_add_color_renderbuffer(struct st_context *st, + struct gl_framebuffer *fb, gl_buffer_index idx) { struct st_framebuffer *stfb = st_ws_framebuffer(fb); diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index 96c8aeb6e8d..42f1c2017f8 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -772,10 +772,13 @@ emit_adjusted_wpos( struct st_translate *t, /** * Emit the TGSI instructions for inverting the WPOS y coordinate. + * This code is unavoidable because it also depends on whether + * a FBO is bound (STATE_FB_WPOS_Y_TRANSFORM). */ static void -emit_inverted_wpos( struct st_translate *t, - const struct gl_program *program ) +emit_wpos_inversion( struct st_translate *t, + const struct gl_program *program, + boolean invert) { struct ureg_program *ureg = t->ureg; @@ -783,17 +786,17 @@ emit_inverted_wpos( struct st_translate *t, * Need to replace instances of INPUT[WPOS] with temp T * where T = INPUT[WPOS] by y is inverted. */ - static const gl_state_index winSizeState[STATE_LENGTH] - = { STATE_INTERNAL, STATE_FB_SIZE, 0, 0, 0 }; + static const gl_state_index wposTransformState[STATE_LENGTH] + = { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM, 0, 0, 0 }; /* XXX: note we are modifying the incoming shader here! Need to * do this before emitting the constant decls below, or this * will be missed: */ - unsigned winHeightConst = _mesa_add_state_reference(program->Parameters, - winSizeState); + unsigned wposTransConst = _mesa_add_state_reference(program->Parameters, + wposTransformState); - struct ureg_src winsize = ureg_DECL_constant( ureg, winHeightConst ); + struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst ); struct ureg_dst wpos_temp; struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]]; @@ -806,12 +809,23 @@ emit_inverted_wpos( struct st_translate *t, ureg_MOV( ureg, wpos_temp, wpos_input ); } - /* SUB wpos_temp.y, winsize_const, wpos_input - */ - ureg_SUB( ureg, - ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ), - winsize, - wpos_input); + if (invert) { + /* MAD wpos_temp.y, wpos_input, wpostrans.xxxx, wpostrans.yyyy + */ + ureg_MAD( ureg, + ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ), + wpos_input, + ureg_scalar(wpostrans, 0), + ureg_scalar(wpostrans, 1)); + } else { + /* MAD wpos_temp.y, wpos_input, wpostrans.zzzz, wpostrans.wwww + */ + ureg_MAD( ureg, + ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ), + wpos_input, + ureg_scalar(wpostrans, 2), + ureg_scalar(wpostrans, 3)); + } /* Use wpos_temp as position input from here on: */ @@ -873,8 +887,7 @@ emit_wpos(struct st_context *st, /* we invert after adjustment so that we avoid the MOV to temporary, * and reuse the adjustment ADD instead */ - if (invert) - emit_inverted_wpos(t, program); + emit_wpos_inversion(t, program, invert); } diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.h b/src/mesa/state_tracker/st_mesa_to_tgsi.h index 9bfd4960b60..0615e52ef62 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.h +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.h @@ -29,18 +29,20 @@ #ifndef ST_MESA_TO_TGSI_H #define ST_MESA_TO_TGSI_H -#include "main/mtypes.h" - -#include "pipe/p_compiler.h" - -struct ureg_program; - #if defined __cplusplus extern "C" { #endif -struct tgsi_token; +#include "main/glheader.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_defines.h" + +struct gl_context; struct gl_program; +struct tgsi_token; +struct ureg_program; + enum pipe_error st_translate_mesa_program( diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 76799287fe1..7b32b46838a 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -32,7 +32,10 @@ #include "main/imports.h" +#include "main/hash.h" +#include "main/mfeatures.h" #include "main/mtypes.h" +#include "program/prog_parameter.h" #include "program/prog_print.h" #include "program/programopt.h" @@ -44,6 +47,8 @@ #include "tgsi/tgsi_ureg.h" #include "st_debug.h" +#include "st_cb_bitmap.h" +#include "st_cb_drawpixels.h" #include "st_context.h" #include "st_program.h" #include "st_mesa_to_tgsi.h" @@ -52,34 +57,109 @@ /** + * Delete a vertex program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv) +{ + if (vpv->driver_shader) + cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); + +#if FEATURE_feedback || FEATURE_rastpos + if (vpv->draw_shader) + draw_delete_vertex_shader( st->draw, vpv->draw_shader ); +#endif + + if (vpv->tgsi.tokens) + st_free_tokens(vpv->tgsi.tokens); + + FREE( vpv ); +} + + + +/** * Clean out any old compilations: */ void -st_vp_release_varients( struct st_context *st, +st_release_vp_variants( struct st_context *st, struct st_vertex_program *stvp ) { - struct st_vp_varient *vpv; + struct st_vp_variant *vpv; - for (vpv = stvp->varients; vpv; ) { - struct st_vp_varient *next = vpv->next; + for (vpv = stvp->variants; vpv; ) { + struct st_vp_variant *next = vpv->next; + delete_vp_variant(st, vpv); + vpv = next; + } - if (vpv->driver_shader) - cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); - -#if FEATURE_feedback || FEATURE_rastpos - if (vpv->draw_shader) - draw_delete_vertex_shader( st->draw, vpv->draw_shader ); -#endif + stvp->variants = NULL; +} + + + +/** + * Delete a fragment program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv) +{ + if (fpv->driver_shader) + cso_delete_fragment_shader(st->cso_context, fpv->driver_shader); - if (vpv->tgsi.tokens) - st_free_tokens(vpv->tgsi.tokens); + FREE(fpv); +} + + +/** + * Free all variants of a fragment program. + */ +void +st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp) +{ + struct st_fp_variant *fpv; + + for (fpv = stfp->variants; fpv; ) { + struct st_fp_variant *next = fpv->next; + delete_fp_variant(st, fpv); + fpv = next; + } + + stfp->variants = NULL; +} + + +/** + * Delete a geometry program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_gp_variant(struct st_context *st, struct st_gp_variant *gpv) +{ + if (gpv->driver_shader) + cso_delete_geometry_shader(st->cso_context, gpv->driver_shader); - FREE( vpv ); + FREE(gpv); +} - vpv = next; + +/** + * Free all variants of a geometry program. + */ +void +st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp) +{ + struct st_gp_variant *gpv; + + for (gpv = stgp->variants; gpv; ) { + struct st_gp_variant *next = gpv->next; + delete_gp_variant(st, gpv); + gpv = next; } - stvp->varients = NULL; + stgp->variants = NULL; } @@ -92,7 +172,7 @@ st_vp_release_varients( struct st_context *st, * \param tokensOut destination for TGSI tokens * \return pointer to cached pipe_shader object. */ -void +static void st_prepare_vertex_program(struct st_context *st, struct st_vertex_program *stvp) { @@ -196,17 +276,22 @@ st_prepare_vertex_program(struct st_context *st, } -struct st_vp_varient * +/** + * Translate a vertex program to create a new variant. + */ +static struct st_vp_variant * st_translate_vertex_program(struct st_context *st, struct st_vertex_program *stvp, - const struct st_vp_varient_key *key) + const struct st_vp_variant_key *key) { - struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient); + struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant); struct pipe_context *pipe = st->pipe; struct ureg_program *ureg; enum pipe_error error; unsigned num_outputs; + st_prepare_vertex_program( st, stvp ); + _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING); @@ -216,6 +301,8 @@ st_translate_vertex_program(struct st_context *st, return NULL; } + vpv->key = *key; + vpv->num_inputs = stvp->num_inputs; num_outputs = stvp->num_outputs; if (key->passthrough_edgeflags) { @@ -229,23 +316,22 @@ st_translate_vertex_program(struct st_context *st, debug_printf("\n"); } - error = - st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_VERTEX, - ureg, - &stvp->Base.Base, - /* inputs */ - vpv->num_inputs, - stvp->input_to_index, - NULL, /* input semantic name */ - NULL, /* input semantic index */ - NULL, - /* outputs */ - num_outputs, - stvp->result_to_output, - stvp->output_semantic_name, - stvp->output_semantic_index, - key->passthrough_edgeflags ); + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_VERTEX, + ureg, + &stvp->Base.Base, + /* inputs */ + vpv->num_inputs, + stvp->input_to_index, + NULL, /* input semantic name */ + NULL, /* input semantic index */ + NULL, + /* outputs */ + num_outputs, + stvp->result_to_output, + stvp->output_semantic_name, + stvp->output_semantic_index, + key->passthrough_edgeflags ); if (error) goto fail; @@ -275,201 +361,317 @@ fail: } +/** + * Find/create a vertex program variant. + */ +struct st_vp_variant * +st_get_vp_variant(struct st_context *st, + struct st_vertex_program *stvp, + const struct st_vp_variant_key *key) +{ + struct st_vp_variant *vpv; + + /* Search for existing variant */ + for (vpv = stvp->variants; vpv; vpv = vpv->next) { + if (memcmp(&vpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!vpv) { + /* create now */ + vpv = st_translate_vertex_program(st, stvp, key); + if (vpv) { + /* insert into list */ + vpv->next = stvp->variants; + stvp->variants = vpv; + } + } + + return vpv; +} + /** - * Translate a Mesa fragment shader into a TGSI shader. - * \return pointer to cached pipe_shader object. + * Translate a Mesa fragment shader into a TGSI shader using extra info in + * the key. + * \return new fragment program variant */ -void +static struct st_fp_variant * st_translate_fragment_program(struct st_context *st, - struct st_fragment_program *stfp ) + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key) { struct pipe_context *pipe = st->pipe; - GLuint outputMapping[FRAG_RESULT_MAX]; - GLuint inputMapping[FRAG_ATTRIB_MAX]; - GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ - GLuint attr; - enum pipe_error error; - const GLbitfield inputsRead = stfp->Base.Base.InputsRead; - struct ureg_program *ureg; + struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant); - ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; - ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; - uint fs_num_inputs = 0; + if (!variant) + return NULL; - ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; - ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; - uint fs_num_outputs = 0; + assert(!(key->bitmap && key->drawpixels)); - _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); +#if FEATURE_drawpix + if (key->bitmap) { + /* glBitmap drawing */ + struct gl_fragment_program *fp; - /* - * Convert Mesa program inputs to TGSI input register semantics. - */ - for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { - if (inputsRead & (1 << attr)) { - const GLuint slot = fs_num_inputs++; + st_make_bitmap_fragment_program(st, &stfp->Base, + &fp, &variant->bitmap_sampler); - inputMapping[attr] = slot; + variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); + stfp = st_fragment_program(fp); + } + else if (key->drawpixels) { + /* glDrawPixels drawing */ + struct gl_fragment_program *fp; - switch (attr) { - case FRAG_ATTRIB_WPOS: - input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_COL0: - input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_COL1: - input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - input_semantic_index[slot] = 1; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_FOGC: - input_semantic_name[slot] = TGSI_SEMANTIC_FOG; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; - case FRAG_ATTRIB_FACE: - input_semantic_name[slot] = TGSI_SEMANTIC_FACE; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; - break; - /* In most cases, there is nothing special about these - * inputs, so adopt a convention to use the generic - * semantic name and the mesa FRAG_ATTRIB_ number as the - * index. - * - * All that is required is that the vertex shader labels - * its own outputs similarly, and that the vertex shader - * generates at least every output required by the - * fragment shader plus fixed-function hardware (such as - * BFC). - * - * There is no requirement that semantic indexes start at - * zero or be restricted to a particular range -- nobody - * should be building tables based on semantic index. - */ - case FRAG_ATTRIB_PNTC: - case FRAG_ATTRIB_TEX0: - case FRAG_ATTRIB_TEX1: - case FRAG_ATTRIB_TEX2: - case FRAG_ATTRIB_TEX3: - case FRAG_ATTRIB_TEX4: - case FRAG_ATTRIB_TEX5: - case FRAG_ATTRIB_TEX6: - case FRAG_ATTRIB_TEX7: - case FRAG_ATTRIB_VAR0: - default: - /* Actually, let's try and zero-base this just for - * readability of the generated TGSI. - */ - assert(attr >= FRAG_ATTRIB_TEX0); - input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); - input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - if (attr == FRAG_ATTRIB_PNTC) - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - else - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; - } + if (key->drawpixels_z || key->drawpixels_stencil) { + fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z, + key->drawpixels_stencil); } else { - inputMapping[attr] = -1; + /* RGBA */ + st_make_drawpix_fragment_program(st, &stfp->Base, &fp); + variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); } + stfp = st_fragment_program(fp); } +#endif - /* - * Semantics and mapping for outputs - */ - { - uint numColors = 0; - GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; - - /* if z is written, emit that first */ - if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; - fs_output_semantic_index[fs_num_outputs] = 0; - outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; - fs_num_outputs++; - outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); - } + if (!stfp->tgsi.tokens) { + /* need to translate Mesa instructions to TGSI now */ + GLuint outputMapping[FRAG_RESULT_MAX]; + GLuint inputMapping[FRAG_ATTRIB_MAX]; + GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ + GLuint attr; + enum pipe_error error; + const GLbitfield inputsRead = stfp->Base.Base.InputsRead; + struct ureg_program *ureg; + GLboolean write_all = GL_FALSE; - if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; - fs_output_semantic_index[fs_num_outputs] = 0; - outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; - fs_num_outputs++; - outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); - } + ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; + ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; + uint fs_num_inputs = 0; + + ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; + ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; + uint fs_num_outputs = 0; + + + _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); + + /* + * Convert Mesa program inputs to TGSI input register semantics. + */ + for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { + if (inputsRead & (1 << attr)) { + const GLuint slot = fs_num_inputs++; + + inputMapping[attr] = slot; - /* handle remaning outputs (color) */ - for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { - if (outputsWritten & BITFIELD64_BIT(attr)) { switch (attr) { - case FRAG_RESULT_DEPTH: - case FRAG_RESULT_STENCIL: - /* handled above */ - assert(0); + case FRAG_ATTRIB_WPOS: + input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_COL0: + input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_COL1: + input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + input_semantic_index[slot] = 1; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_FOGC: + input_semantic_name[slot] = TGSI_SEMANTIC_FOG; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; + case FRAG_ATTRIB_FACE: + input_semantic_name[slot] = TGSI_SEMANTIC_FACE; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; + /* In most cases, there is nothing special about these + * inputs, so adopt a convention to use the generic + * semantic name and the mesa FRAG_ATTRIB_ number as the + * index. + * + * All that is required is that the vertex shader labels + * its own outputs similarly, and that the vertex shader + * generates at least every output required by the + * fragment shader plus fixed-function hardware (such as + * BFC). + * + * There is no requirement that semantic indexes start at + * zero or be restricted to a particular range -- nobody + * should be building tables based on semantic index. + */ + case FRAG_ATTRIB_PNTC: + case FRAG_ATTRIB_TEX0: + case FRAG_ATTRIB_TEX1: + case FRAG_ATTRIB_TEX2: + case FRAG_ATTRIB_TEX3: + case FRAG_ATTRIB_TEX4: + case FRAG_ATTRIB_TEX5: + case FRAG_ATTRIB_TEX6: + case FRAG_ATTRIB_TEX7: + case FRAG_ATTRIB_VAR0: 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++; + /* Actually, let's try and zero-base this just for + * readability of the generated TGSI. + */ + assert(attr >= FRAG_ATTRIB_TEX0); + input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); + input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + if (attr == FRAG_ATTRIB_PNTC) + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + else + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; } + } + else { + inputMapping[attr] = -1; + } + } + + /* + * Semantics and mapping for outputs + */ + { + uint numColors = 0; + GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; + + /* if z is written, emit that first */ + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; + fs_output_semantic_index[fs_num_outputs] = 0; + outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; + fs_num_outputs++; + outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); + } + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; + fs_output_semantic_index[fs_num_outputs] = 0; + outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; fs_num_outputs++; + outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); + } + + /* handle remaning outputs (color) */ + for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { + if (outputsWritten & BITFIELD64_BIT(attr)) { + switch (attr) { + case FRAG_RESULT_DEPTH: + case FRAG_RESULT_STENCIL: + /* handled above */ + assert(0); + break; + case FRAG_RESULT_COLOR: + write_all = GL_TRUE; /* fallthrough */ + 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; + } + + fs_num_outputs++; + } } } - } - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); - if (ureg == NULL) - return; + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; - if (ST_DEBUG & DEBUG_MESA) { - _mesa_print_program(&stfp->Base.Base); - _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); - debug_printf("\n"); + if (ST_DEBUG & DEBUG_MESA) { + _mesa_print_program(&stfp->Base.Base); + _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); + debug_printf("\n"); + } + if (write_all == GL_TRUE) + ureg_property_fs_color0_writes_all_cbufs(ureg, 1); + + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_FRAGMENT, + ureg, + &stfp->Base.Base, + /* inputs */ + fs_num_inputs, + inputMapping, + input_semantic_name, + input_semantic_index, + interpMode, + /* outputs */ + fs_num_outputs, + outputMapping, + fs_output_semantic_name, + fs_output_semantic_index, FALSE ); + + stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); + ureg_destroy( ureg ); } - error = - st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_FRAGMENT, - ureg, - &stfp->Base.Base, - /* inputs */ - fs_num_inputs, - inputMapping, - input_semantic_name, - input_semantic_index, - interpMode, - /* outputs */ - fs_num_outputs, - outputMapping, - fs_output_semantic_name, - fs_output_semantic_index, FALSE ); - - stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); - ureg_destroy( ureg ); - stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); + /* fill in variant */ + variant->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); + variant->key = *key; if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); debug_printf("\n"); } + + return variant; } -void + +/** + * Translate fragment program if needed. + */ +struct st_fp_variant * +st_get_fp_variant(struct st_context *st, + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key) +{ + struct st_fp_variant *fpv; + + /* Search for existing variant */ + for (fpv = stfp->variants; fpv; fpv = fpv->next) { + if (memcmp(&fpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!fpv) { + /* create new */ + fpv = st_translate_fragment_program(st, stfp, key); + if (fpv) { + /* insert into list */ + fpv->next = stfp->variants; + stfp->variants = fpv; + } + } + + return fpv; +} + + +/** + * Translate a geometry program to create a new variant. + */ +static struct st_gp_variant * st_translate_geometry_program(struct st_context *st, - struct st_geometry_program *stgp) + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key) { GLuint inputMapping[GEOM_ATTRIB_MAX]; GLuint outputMapping[GEOM_RESULT_MAX]; @@ -492,12 +694,19 @@ st_translate_geometry_program(struct st_context *st, GLuint maxSlot = 0; struct ureg_program *ureg; + struct st_gp_variant *gpv; + + gpv = CALLOC_STRUCT(st_gp_variant); + if (!gpv) + return NULL; + _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING); ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); if (ureg == NULL) { - return; + FREE(gpv); + return NULL; } /* which vertex output goes to the first geometry input */ @@ -527,7 +736,7 @@ st_translate_geometry_program(struct st_context *st, } else ++gs_builtin_inputs; -#if 1 +#if 0 debug_printf("input map at %d = %d\n", slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); #endif @@ -669,37 +878,35 @@ st_translate_geometry_program(struct st_context *st, st_free_tokens(stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); - error = st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_GEOMETRY, - ureg, - &stgp->Base.Base, - /* inputs */ - gs_num_inputs, - inputMapping, - stgp->input_semantic_name, - stgp->input_semantic_index, - NULL, - /* outputs */ - gs_num_outputs, - outputMapping, - gs_output_semantic_name, - gs_output_semantic_index, - FALSE); - + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_GEOMETRY, + ureg, + &stgp->Base.Base, + /* inputs */ + gs_num_inputs, + inputMapping, + stgp->input_semantic_name, + stgp->input_semantic_index, + NULL, + /* outputs */ + gs_num_outputs, + outputMapping, + gs_output_semantic_name, + gs_output_semantic_index, + FALSE); stgp->num_inputs = gs_num_inputs; stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); - stgp->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); + + /* fill in new variant */ + gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); + gpv->key = *key; if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); @@ -710,8 +917,44 @@ st_translate_geometry_program(struct st_context *st, tgsi_dump(stgp->tgsi.tokens, 0); debug_printf("\n"); } + + return gpv; } + +/** + * Get/create geometry program variant. + */ +struct st_gp_variant * +st_get_gp_variant(struct st_context *st, + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key) +{ + struct st_gp_variant *gpv; + + /* Search for existing variant */ + for (gpv = stgp->variants; gpv; gpv = gpv->next) { + if (memcmp(&gpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!gpv) { + /* create new */ + gpv = st_translate_geometry_program(st, stgp, key); + if (gpv) { + /* insert into list */ + gpv->next = stgp->variants; + stgp->variants = gpv; + } + } + + return gpv; +} + + + + /** * Debug- print current shader text */ @@ -757,3 +1000,155 @@ st_print_shaders(struct gl_context *ctx) } } } + + +/** + * Vert/Geom/Frag programs have per-context variants. Free all the + * variants attached to the given program which match the given context. + */ +static void +destroy_program_variants(struct st_context *st, struct gl_program *program) +{ + if (!program) + return; + + switch (program->Target) { + case GL_VERTEX_PROGRAM_ARB: + { + struct st_vertex_program *stvp = (struct st_vertex_program *) program; + struct st_vp_variant *vpv, **prevPtr = &stvp->variants; + + for (vpv = stvp->variants; vpv; ) { + struct st_vp_variant *next = vpv->next; + if (vpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_vp_variant(st, vpv); + } + else { + prevPtr = &vpv->next; + } + vpv = next; + } + } + break; + case GL_FRAGMENT_PROGRAM_ARB: + { + struct st_fragment_program *stfp = + (struct st_fragment_program *) program; + struct st_fp_variant *fpv, **prevPtr = &stfp->variants; + + for (fpv = stfp->variants; fpv; ) { + struct st_fp_variant *next = fpv->next; + if (fpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_fp_variant(st, fpv); + } + else { + prevPtr = &fpv->next; + } + fpv = next; + } + } + break; + case MESA_GEOMETRY_PROGRAM: + { + struct st_geometry_program *stgp = + (struct st_geometry_program *) program; + struct st_gp_variant *gpv, **prevPtr = &stgp->variants; + + for (gpv = stgp->variants; gpv; ) { + struct st_gp_variant *next = gpv->next; + if (gpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_gp_variant(st, gpv); + } + else { + prevPtr = &gpv->next; + } + gpv = next; + } + } + break; + default: + _mesa_problem(NULL, "Unexpected program target in " + "destroy_program_variants_cb()"); + } +} + + +/** + * Callback for _mesa_HashWalk. Free all the shader's program variants + * which match the given context. + */ +static void +destroy_shader_program_variants_cb(GLuint key, void *data, void *userData) +{ + struct st_context *st = (struct st_context *) userData; + struct gl_shader *shader = (struct gl_shader *) data; + + switch (shader->Type) { + case GL_SHADER_PROGRAM_MESA: + { + struct gl_shader_program *shProg = (struct gl_shader_program *) data; + GLuint i; + + for (i = 0; i < shProg->NumShaders; i++) { + destroy_program_variants(st, shProg->Shaders[i]->Program); + } + + destroy_program_variants(st, (struct gl_program *) + shProg->VertexProgram); + destroy_program_variants(st, (struct gl_program *) + shProg->FragmentProgram); + destroy_program_variants(st, (struct gl_program *) + shProg->GeometryProgram); + } + break; + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + case GL_GEOMETRY_SHADER: + { + destroy_program_variants(st, shader->Program); + } + break; + default: + assert(0); + } +} + + +/** + * Callback for _mesa_HashWalk. Free all the program variants which match + * the given context. + */ +static void +destroy_program_variants_cb(GLuint key, void *data, void *userData) +{ + struct st_context *st = (struct st_context *) userData; + struct gl_program *program = (struct gl_program *) data; + destroy_program_variants(st, program); +} + + +/** + * Walk over all shaders and programs to delete any variants which + * belong to the given context. + * This is called during context tear-down. + */ +void +st_destroy_program_variants(struct st_context *st) +{ + /* ARB vert/frag program */ + _mesa_HashWalk(st->ctx->Shared->Programs, + destroy_program_variants_cb, st); + + /* GLSL vert/frag/geom shaders */ + _mesa_HashWalk(st->ctx->Shared->ShaderObjects, + destroy_shader_program_variants_cb, st); +} diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 72dbc715fe1..c4244df939e 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -40,26 +40,61 @@ #include "st_context.h" +/** Fragment program variant key */ +struct st_fp_variant_key +{ + struct st_context *st; /**< variants are per-context */ + + /** for glBitmap */ + GLuint bitmap:1; /**< glBitmap variant? */ + + /** for glDrawPixels */ + GLuint drawpixels:1; /**< glDrawPixels variant */ + GLuint scaleAndBias:1; /**< glDrawPixels w/ scale and/or bias? */ + GLuint pixelMaps:1; /**< glDrawPixels w/ pixel lookup map? */ + GLuint drawpixels_z:1; /**< glDrawPixels(GL_DEPTH) */ + GLuint drawpixels_stencil:1; /**< glDrawPixels(GL_STENCIL) */ +}; + + +/** + * Variant of a fragment program. + */ +struct st_fp_variant +{ + /** Parameters which generated this version of fragment program */ + struct st_fp_variant_key key; + + /** Driver's compiled shader */ + void *driver_shader; + + /** For glBitmap variants */ + struct gl_program_parameter_list *parameters; + uint bitmap_sampler; + + /** next in linked list */ + struct st_fp_variant *next; +}; + + /** * Derived from Mesa gl_fragment_program: */ struct st_fragment_program { struct gl_fragment_program Base; - GLuint serialNo; struct pipe_shader_state tgsi; - void *driver_shader; - /** Program prefixed with glBitmap prologue */ - struct st_fragment_program *bitmap_program; - uint bitmap_sampler; + struct st_fp_variant *variants; }; -struct st_vp_varient_key +/** Vertex program variant key */ +struct st_vp_variant_key { + struct st_context *st; /**< variants are per-context */ boolean passthrough_edgeflags; }; @@ -68,12 +103,12 @@ struct st_vp_varient_key * This represents a vertex program, especially translated to match * the inputs of a particular fragment shader. */ -struct st_vp_varient +struct st_vp_variant { /* Parameters which generated this translated version of a vertex * shader: */ - struct st_vp_varient_key key; + struct st_vp_variant_key key; /** * TGSI tokens (to later generate a 'draw' module shader for @@ -88,9 +123,9 @@ struct st_vp_varient struct draw_vertex_shader *draw_shader; /** Next in linked list */ - struct st_vp_varient *next; + struct st_vp_variant *next; - /** similar to that in st_vertex_program, but with information about edgeflags too */ + /** similar to that in st_vertex_program, but with edgeflags info too */ GLuint num_inputs; }; @@ -101,7 +136,6 @@ struct st_vp_varient struct st_vertex_program { struct gl_vertex_program Base; /**< The Mesa vertex program */ - GLuint serialNo, lastSerialNo; /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */ GLuint input_to_index[VERT_ATTRIB_MAX]; @@ -115,18 +149,41 @@ struct st_vertex_program ubyte output_semantic_index[VERT_RESULT_MAX]; GLuint num_outputs; - /** List of translated varients of this vertex program. + /** List of translated variants of this vertex program. */ - struct st_vp_varient *varients; + struct st_vp_variant *variants; +}; + + + +/** Geometry program variant key */ +struct st_gp_variant_key +{ + struct st_context *st; /**< variants are per-context */ + /* no other fields yet */ +}; + + +/** + * Geometry program variant. + */ +struct st_gp_variant +{ + /* Parameters which generated this translated version of a vertex */ + struct st_gp_variant_key key; + + void *driver_shader; + + struct st_gp_variant *next; }; + /** * Derived from Mesa gl_geometry_program: */ struct st_geometry_program { struct gl_geometry_program Base; /**< The Mesa geometry program */ - GLuint serialNo; /** map GP input back to VP output */ GLuint input_map[PIPE_MAX_SHADER_INPUTS]; @@ -145,9 +202,12 @@ struct st_geometry_program ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; struct pipe_shader_state tgsi; - void *driver_shader; + + struct st_gp_variant *variants; }; + + static INLINE struct st_fragment_program * st_fragment_program( struct gl_fragment_program *fp ) { @@ -162,9 +222,9 @@ st_vertex_program( struct gl_vertex_program *vp ) } static INLINE struct st_geometry_program * -st_geometry_program( struct gl_geometry_program *vp ) +st_geometry_program( struct gl_geometry_program *gp ) { - return (struct st_geometry_program *)vp; + return (struct st_geometry_program *)gp; } static INLINE void @@ -198,32 +258,43 @@ st_reference_fragprog(struct st_context *st, } -extern void -st_translate_fragment_program(struct st_context *st, - struct st_fragment_program *fp); +extern struct st_vp_variant * +st_get_vp_variant(struct st_context *st, + struct st_vertex_program *stvp, + const struct st_vp_variant_key *key); + + +extern struct st_fp_variant * +st_get_fp_variant(struct st_context *st, + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key); + + +extern struct st_gp_variant * +st_get_gp_variant(struct st_context *st, + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key); + + extern void -st_translate_geometry_program(struct st_context *st, - struct st_geometry_program *stgp); +st_release_vp_variants( struct st_context *st, + struct st_vertex_program *stvp ); -/* Called after program string change, discard all previous - * compilation results. - */ extern void -st_prepare_vertex_program(struct st_context *st, - struct st_vertex_program *stvp); +st_release_fp_variants( struct st_context *st, + struct st_fragment_program *stfp ); -extern struct st_vp_varient * -st_translate_vertex_program(struct st_context *st, - struct st_vertex_program *stvp, - const struct st_vp_varient_key *key); +extern void +st_release_gp_variants(struct st_context *st, + struct st_geometry_program *stgp); -void -st_vp_release_varients( struct st_context *st, - struct st_vertex_program *stvp ); extern void st_print_shaders(struct gl_context *ctx); +extern void +st_destroy_program_variants(struct st_context *st); + #endif diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index c6cf2ba061b..155ea39f18c 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -84,6 +84,7 @@ st_texture_create(struct st_context *st, pt.width0 = width0; pt.height0 = height0; pt.depth0 = depth0; + pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : 1); pt.usage = PIPE_USAGE_DEFAULT; pt.bind = bind; pt.flags = 0; @@ -136,7 +137,7 @@ st_texture_match_image(const struct pipe_resource *pt, */ GLubyte * st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, - GLuint zoffset, enum pipe_transfer_usage usage, + GLuint zoffset, enum pipe_transfer_usage usage, GLuint x, GLuint y, GLuint w, GLuint h) { struct pipe_context *pipe = st->pipe; @@ -144,9 +145,9 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage, DBG("%s \n", __FUNCTION__); - stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->face, - stImage->level, zoffset, - usage, x, y, w, h); + stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->level, + stImage->face + zoffset, + usage, x, y, w, h); if (stImage->transfer) return pipe_transfer_map(pipe, stImage->transfer); @@ -219,10 +220,10 @@ st_texture_image_data(struct st_context *st, DBG("%s\n", __FUNCTION__); for (i = 0; i < depth; i++) { - dst_transfer = pipe_get_transfer(st->pipe, dst, face, level, i, - PIPE_TRANSFER_WRITE, 0, 0, - u_minify(dst->width0, level), - u_minify(dst->height0, level)); + dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i, + PIPE_TRANSFER_WRITE, 0, 0, + u_minify(dst->width0, level), + u_minify(dst->height0, level)); st_surface_data(pipe, dst_transfer, 0, 0, /* dstx, dsty */ @@ -230,7 +231,7 @@ st_texture_image_data(struct st_context *st, src_row_stride, 0, 0, /* source x, y */ u_minify(dst->width0, level), - u_minify(dst->height0, level)); /* width, height */ + u_minify(dst->height0, level)); /* width, height */ pipe->transfer_destroy(pipe, dst_transfer); @@ -245,14 +246,10 @@ st_texture_image_data(struct st_context *st, static void print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src) { - struct pipe_subresource rect; struct pipe_transfer *xfer; struct pipe_box region; ubyte *map; - rect.face = 0; - rect.level = 0; - region.x = src->width0 / 2; region.y = src->height0 / 2; region.z = 0; @@ -260,7 +257,7 @@ print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src) region.height = 1; region.depth = 1; - xfer = pipe->get_transfer(pipe, src, rect, PIPE_TRANSFER_READ, ®ion); + xfer = pipe->get_transfer(pipe, src, 0, PIPE_TRANSFER_READ, ®ion); map = pipe->transfer_map(pipe, xfer); printf("center pixel: %d %d %d %d\n", map[0], map[1], map[2], map[3]); @@ -282,22 +279,26 @@ st_texture_image_copy(struct pipe_context *pipe, struct pipe_resource *src, GLuint srcLevel, GLuint face) { - GLuint width = u_minify(dst->width0, dstLevel); - GLuint height = u_minify(dst->height0, dstLevel); - GLuint depth = u_minify(dst->depth0, dstLevel); - struct pipe_subresource dstsub, srcsub; + GLuint width = u_minify(dst->width0, dstLevel); + GLuint height = u_minify(dst->height0, dstLevel); + GLuint depth = u_minify(dst->depth0, dstLevel); + struct pipe_box src_box; GLuint i; assert(u_minify(src->width0, srcLevel) == width); assert(u_minify(src->height0, srcLevel) == height); assert(u_minify(src->depth0, srcLevel) == depth); - dstsub.face = face; - dstsub.level = dstLevel; - srcsub.face = face; - srcsub.level = srcLevel; + src_box.x = 0; + src_box.y = 0; + src_box.width = width; + src_box.height = height; + src_box.depth = 1; /* Loop over 3D image slices */ - for (i = 0; i < depth; i++) { + /* could (and probably should) use "true" 3d box here - + but drivers can't quite handle it yet */ + for (i = face; i < face + depth; i++) { + src_box.z = i; if (0) { print_center_pixel(pipe, src); @@ -305,12 +306,11 @@ st_texture_image_copy(struct pipe_context *pipe, pipe->resource_copy_region(pipe, dst, - dstsub, + dstLevel, 0, 0, i,/* destX, Y, Z */ src, - srcsub, - 0, 0, i,/* srcX, Y, Z */ - width, height); + srcLevel, + &src_box); } } |