st/mesa: fix glDrawPixels with a texture

The samplers for DrawPixels data and the pixel map are assigned to slots
which don't overlap with the existing sampler slots.

The texture coordinates for the user texture are uploaded as a constant.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Tested-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
Marek Olšák
2015-10-05 01:22:20 +02:00
parent f15bb3e633
commit de6a004035
5 changed files with 111 additions and 29 deletions

View File

@@ -525,6 +525,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
int num_sampler_view,
void *driver_vp,
void *driver_fp,
struct st_fp_variant *fpv,
const GLfloat *color,
GLboolean invertTex,
GLboolean write_depth, GLboolean write_stencil)
@@ -612,10 +613,9 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
cso_set_tesseval_shader_handle(cso, NULL);
cso_set_geometry_shader_handle(cso, NULL);
/* texture sampling state: */
/* user samplers, plus the drawpix samplers */
{
struct pipe_sampler_state sampler;
const struct pipe_sampler_state *states[2] = {&sampler, &sampler};
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
@@ -626,8 +626,25 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.normalized_coords = normalized;
cso_set_samplers(cso, PIPE_SHADER_FRAGMENT,
num_sampler_view > 1 ? 2 : 1, states);
if (fpv) {
const struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
uint num = MAX2(MAX2(fpv->drawpix_sampler, fpv->pixelmap_sampler) + 1,
st->state.num_samplers[PIPE_SHADER_FRAGMENT]);
uint i;
for (i = 0; i < st->state.num_samplers[PIPE_SHADER_FRAGMENT]; i++)
samplers[i] = &st->state.samplers[PIPE_SHADER_FRAGMENT][i];
samplers[fpv->drawpix_sampler] = &sampler;
if (sv[1])
samplers[fpv->pixelmap_sampler] = &sampler;
cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num, samplers);
} else {
const struct pipe_sampler_state *samplers[2] = {&sampler, &sampler};
cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, samplers);
}
}
/* viewport state: viewport matching window dims */
@@ -647,7 +664,20 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
cso_set_vertex_elements(cso, 3, st->velems_util_draw);
cso_set_stream_outputs(st->cso_context, 0, NULL, NULL);
/* texture state: */
/* user textures, plus the drawpix textures */
if (fpv) {
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
uint num = MAX2(MAX2(fpv->drawpix_sampler, fpv->pixelmap_sampler) + 1,
st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
memcpy(sampler_views, st->state.sampler_views[PIPE_SHADER_FRAGMENT],
sizeof(sampler_views));
sampler_views[fpv->drawpix_sampler] = sv[0];
if (sv[1])
sampler_views[fpv->pixelmap_sampler] = sv[1];
cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num, sampler_views);
} else
cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, sv);
/* Compute Gallium window coords (y=0=top) with pixel zoom.
@@ -943,6 +973,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
struct pipe_sampler_view *sv[2] = { NULL };
int num_sampler_view = 1;
struct gl_pixelstore_attrib clippedUnpack;
struct st_fp_variant *fpv = NULL;
/* Mesa state should be up to date by now */
assert(ctx->NewState == 0x0);
@@ -982,7 +1013,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
color = ctx->Current.RasterColor;
}
else {
struct st_fp_variant *fpv = get_color_fp_variant(st);
fpv = get_color_fp_variant(st);
driver_fp = fpv->driver_shader;
driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
@@ -1025,7 +1056,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
sv,
num_sampler_view,
driver_vp,
driver_fp,
driver_fp, fpv,
color, GL_FALSE, write_depth, write_stencil);
pipe_sampler_view_reference(&sv[0], NULL);
if (num_sampler_view > 1)
@@ -1280,6 +1311,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
void *driver_vp, *driver_fp;
struct pipe_resource *pt;
struct pipe_sampler_view *sv[2] = { NULL };
struct st_fp_variant *fpv = NULL;
int num_sampler_view = 1;
GLfloat *color;
enum pipe_format srcFormat;
@@ -1318,7 +1350,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
* Get vertex/fragment shaders
*/
if (type == GL_COLOR) {
struct st_fp_variant *fpv = get_color_fp_variant(st);
fpv = get_color_fp_variant(st);
rbRead = st_get_color_read_renderbuffer(ctx);
color = NULL;
@@ -1470,7 +1502,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
sv,
num_sampler_view,
driver_vp,
driver_fp,
driver_fp, fpv,
color, invertTex, GL_FALSE, GL_FALSE);
pipe_resource_reference(&pt, NULL);

View File

@@ -44,6 +44,8 @@ st_destroy_drawpix(struct st_context *st);
extern const struct tgsi_token *
st_get_drawpix_shader(const struct tgsi_token *tokens, bool use_texcoord,
bool scale_and_bias, unsigned scale_const,
unsigned bias_const, bool pixel_maps);
unsigned bias_const, bool pixel_maps,
unsigned drawpix_sampler, unsigned pixelmap_sampler,
unsigned texcoord_const);
#endif /* ST_CB_DRAWPIXELS_H */

View File

@@ -40,6 +40,9 @@ struct tgsi_drawpix_transform {
unsigned scale_const;
unsigned bias_const;
unsigned color_temp;
unsigned drawpix_sampler;
unsigned pixelmap_sampler;
unsigned texcoord_const;
};
static inline struct tgsi_drawpix_transform *
@@ -71,7 +74,8 @@ transform_instr(struct tgsi_transform_context *tctx,
struct tgsi_drawpix_transform *ctx = tgsi_drawpix_transform(tctx);
struct tgsi_full_declaration decl;
struct tgsi_full_instruction inst;
unsigned i, semantic;
unsigned i, sem_texcoord = ctx->use_texcoord ? TGSI_SEMANTIC_TEXCOORD :
TGSI_SEMANTIC_GENERIC;
int texcoord_index = -1;
if (ctx->first_instruction_emitted)
@@ -96,6 +100,13 @@ transform_instr(struct tgsi_transform_context *tctx,
}
}
if (ctx->info.const_file_max[0] < (int)ctx->texcoord_const) {
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_CONSTANT;
decl.Range.First = decl.Range.Last = ctx->texcoord_const;
tctx->emit_declaration(tctx, &decl);
}
/* Add a new temp. */
ctx->color_temp = ctx->info.file_max[TGSI_FILE_TEMPORARY] + 1;
decl = tgsi_default_full_declaration();
@@ -103,11 +114,9 @@ transform_instr(struct tgsi_transform_context *tctx,
decl.Range.First = decl.Range.Last = ctx->color_temp;
tctx->emit_declaration(tctx, &decl);
/* Add TEXCOORD[0] if it's missing. */
semantic = ctx->use_texcoord ? TGSI_SEMANTIC_TEXCOORD :
TGSI_SEMANTIC_GENERIC;
/* Add TEXCOORD[texcoord_slot] if it's missing. */
for (i = 0; i < ctx->info.num_inputs; i++) {
if (ctx->info.input_semantic_name[i] == semantic &&
if (ctx->info.input_semantic_name[i] == sem_texcoord &&
ctx->info.input_semantic_index[i] == 0) {
texcoord_index = i;
break;
@@ -118,7 +127,7 @@ transform_instr(struct tgsi_transform_context *tctx,
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
decl.Declaration.Semantic = 1;
decl.Semantic.Name = semantic;
decl.Semantic.Name = sem_texcoord;
decl.Declaration.Interpolate = 1;
decl.Interp.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
decl.Range.First = decl.Range.Last = ctx->info.num_inputs;
@@ -127,17 +136,19 @@ transform_instr(struct tgsi_transform_context *tctx,
}
/* Declare the drawpix sampler if it's missing. */
if (ctx->info.file_max[TGSI_FILE_SAMPLER] == -1) {
if (!(ctx->info.samplers_declared & (1 << ctx->drawpix_sampler))) {
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
decl.Range.First = decl.Range.Last = ctx->drawpix_sampler;
tctx->emit_declaration(tctx, &decl);
}
/* Declare the pixel map sampler if it's missing. */
if (ctx->info.file_max[TGSI_FILE_SAMPLER] <= 0) {
if (ctx->pixel_maps &&
!(ctx->info.samplers_declared & (1 << ctx->pixelmap_sampler))) {
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
decl.Range.First = decl.Range.Last = 1;
decl.Range.First = decl.Range.Last = ctx->pixelmap_sampler;
tctx->emit_declaration(tctx, &decl);
}
@@ -157,7 +168,7 @@ transform_instr(struct tgsi_transform_context *tctx,
inst.Instruction.NumSrcRegs = 2;
SET_SRC(&inst, 0, TGSI_FILE_INPUT, texcoord_index, X, Y, Z, W);
inst.Src[1].Register.File = TGSI_FILE_SAMPLER;
inst.Src[1].Register.Index = 0;
inst.Src[1].Register.Index = ctx->drawpix_sampler;
tctx->emit_instruction(tctx, &inst);
@@ -197,7 +208,7 @@ transform_instr(struct tgsi_transform_context *tctx,
inst.Instruction.NumSrcRegs = 2;
SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->color_temp, X, Y, Y, Y);
inst.Src[1].Register.File = TGSI_FILE_SAMPLER;
inst.Src[1].Register.Index = 1;
inst.Src[1].Register.Index = ctx->pixelmap_sampler;
tctx->emit_instruction(tctx, &inst);
@@ -207,7 +218,9 @@ transform_instr(struct tgsi_transform_context *tctx,
tctx->emit_instruction(tctx, &inst);
}
/* Now, "color_temp" should be used in place of IN:COLOR0 */
/* Now, "color_temp" should be used in place of IN:COLOR0,
* and CONST[texcoord_slot] should be used in place of IN:TEXCOORD0.
*/
transform_inst:
@@ -215,12 +228,17 @@ transform_inst:
struct tgsi_full_src_register *src = &current_inst->Src[i];
unsigned reg = src->Register.Index;
if (src->Register.File == TGSI_FILE_INPUT &&
!src->Register.Indirect &&
ctx->info.input_semantic_name[reg] == TGSI_SEMANTIC_COLOR &&
if (src->Register.File != TGSI_FILE_INPUT || src->Register.Indirect)
continue;
if (ctx->info.input_semantic_name[reg] == TGSI_SEMANTIC_COLOR &&
ctx->info.input_semantic_index[reg] == 0) {
src->Register.File = TGSI_FILE_TEMPORARY;
src->Register.Index = ctx->color_temp;
} else if (ctx->info.input_semantic_name[reg] == sem_texcoord &&
ctx->info.input_semantic_index[reg] == 0) {
src->Register.File = TGSI_FILE_CONSTANT;
src->Register.Index = ctx->texcoord_const;
}
}
@@ -230,7 +248,9 @@ transform_inst:
const struct tgsi_token *
st_get_drawpix_shader(const struct tgsi_token *tokens, bool use_texcoord,
bool scale_and_bias, unsigned scale_const,
unsigned bias_const, bool pixel_maps)
unsigned bias_const, bool pixel_maps,
unsigned drawpix_sampler, unsigned pixelmap_sampler,
unsigned texcoord_const)
{
struct tgsi_drawpix_transform ctx;
struct tgsi_token *newtoks;
@@ -243,6 +263,9 @@ st_get_drawpix_shader(const struct tgsi_token *tokens, bool use_texcoord,
ctx.scale_const = scale_const;
ctx.bias_const = bias_const;
ctx.pixel_maps = pixel_maps;
ctx.drawpix_sampler = drawpix_sampler;
ctx.pixelmap_sampler = pixelmap_sampler;
ctx.texcoord_const = texcoord_const;
tgsi_scan_shader(tokens, &ctx.info);
newlen = tgsi_num_tokens(tokens) + 30;

View File

@@ -886,7 +886,17 @@ st_translate_fragment_program(struct st_context *st,
/* glDrawPixels (color only) */
if (key->drawpixels) {
const struct tgsi_token *tokens;
unsigned scale_const = 0, bias_const = 0;
unsigned scale_const = 0, bias_const = 0, texcoord_const = 0;
/* Find the first unused slot. */
variant->drawpix_sampler = ffs(~stfp->Base.Base.SamplersUsed) - 1;
if (key->pixelMaps) {
unsigned samplers_used = stfp->Base.Base.SamplersUsed |
(1 << variant->drawpix_sampler);
variant->pixelmap_sampler = ffs(~samplers_used) - 1;
}
variant->parameters =
_mesa_clone_parameter_list(stfp->Base.Base.Parameters);
@@ -903,10 +913,21 @@ st_translate_fragment_program(struct st_context *st,
bias_state);
}
{
static const gl_state_index state[STATE_LENGTH] =
{ STATE_INTERNAL, STATE_CURRENT_ATTRIB, VERT_ATTRIB_TEX0 };
texcoord_const = _mesa_add_state_reference(variant->parameters,
state);
}
tokens = st_get_drawpix_shader(variant->tgsi.tokens,
st->needs_texcoord_semantic,
key->scaleAndBias, scale_const,
bias_const, key->pixelMaps);
bias_const, key->pixelMaps,
variant->drawpix_sampler,
variant->pixelmap_sampler,
texcoord_const);
if (tokens) {
tgsi_free_tokens(variant->tgsi.tokens);

View File

@@ -85,6 +85,10 @@ struct st_fp_variant
struct gl_program_parameter_list *parameters;
uint bitmap_sampler;
/** For glDrawPixels variants */
unsigned drawpix_sampler;
unsigned pixelmap_sampler;
/** next in linked list */
struct st_fp_variant *next;
};