From de6a004035f3de5879648f8afb4670ae82f4ad02 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 5 Oct 2015 01:22:20 +0200 Subject: [PATCH] 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 Reviewed-by: Brian Paul Tested-by: Brian Paul --- src/mesa/state_tracker/st_cb_drawpixels.c | 52 ++++++++++++++---- src/mesa/state_tracker/st_cb_drawpixels.h | 4 +- .../state_tracker/st_cb_drawpixels_shader.c | 55 +++++++++++++------ src/mesa/state_tracker/st_program.c | 25 ++++++++- src/mesa/state_tracker/st_program.h | 4 ++ 5 files changed, 111 insertions(+), 29 deletions(-) diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 34163ede4a2..7e8633edc1a 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -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,8 +664,21 @@ 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: */ - cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, num_sampler_view, sv); + /* 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. * Recall that these coords are transformed by the current @@ -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); diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h index b8a34952141..f1fb32dd6cf 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.h +++ b/src/mesa/state_tracker/st_cb_drawpixels.h @@ -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 */ diff --git a/src/mesa/state_tracker/st_cb_drawpixels_shader.c b/src/mesa/state_tracker/st_cb_drawpixels_shader.c index 01db0b6d73e..749b46cfbf7 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels_shader.c +++ b/src/mesa/state_tracker/st_cb_drawpixels_shader.c @@ -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 = ¤t_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; diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 01e33d04f74..95ad2f46827 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -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); diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 2927d542dfc..33d39f005b9 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -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; }; -- 2.30.2