From: Marek Olšák Date: Sun, 4 Oct 2015 00:38:55 +0000 (+0200) Subject: st/mesa: implement DrawPixels shader transformation using tgsi_transform_shader X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f15bb3e633d577fe6d8d7bc2c64497c6ac4c2021;p=mesa.git st/mesa: implement DrawPixels shader transformation using tgsi_transform_shader Reviewed-by: Dave Airlie Reviewed-by: Brian Paul Tested-by: Brian Paul --- diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources index 2dabea83075..13208b5e421 100644 --- a/src/mesa/Makefile.sources +++ b/src/mesa/Makefile.sources @@ -426,6 +426,7 @@ STATETRACKER_FILES = \ state_tracker/st_cb_condrender.h \ state_tracker/st_cb_drawpixels.c \ state_tracker/st_cb_drawpixels.h \ + state_tracker/st_cb_drawpixels_shader.c \ state_tracker/st_cb_drawtex.c \ state_tracker/st_cb_drawtex.h \ state_tracker/st_cb_eglimage.c \ diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index a04163cc137..f94c358afba 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -25,65 +25,17 @@ * **************************************************************************/ -/* - * Generate fragment programs to implement pixel transfer ops, such as - * scale/bias, colortable, convolution... - * - * Authors: +/* Authors: * Brian Paul */ -#include "main/imports.h" -#include "main/image.h" -#include "main/macros.h" -#include "program/program.h" -#include "program/prog_cache.h" -#include "program/prog_instruction.h" -#include "program/prog_parameter.h" -#include "program/prog_print.h" - #include "st_context.h" -#include "st_format.h" #include "st_texture.h" -#include "pipe/p_screen.h" -#include "pipe/p_context.h" #include "util/u_inlines.h" #include "util/u_pack_color.h" -struct state_key -{ - GLuint scaleAndBias:1; - GLuint pixelMaps:1; - -#if 0 - GLfloat Maps[3][256][4]; - int NumMaps; - GLint NumStages; - pipeline_stage Stages[STAGE_MAX]; - GLboolean StagesUsed[STAGE_MAX]; - GLfloat Scale1[4], Bias1[4]; - GLfloat Scale2[4], Bias2[4]; -#endif -}; - -static void -make_state_key(struct gl_context *ctx, struct state_key *key) -{ - memset(key, 0, sizeof(*key)); - - if (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->scaleAndBias = 1; - } - - key->pixelMaps = ctx->Pixel.MapColorFlag; -} - - /** * Update the pixelmap texture with the contents of the R/G/B/A pixel maps. */ @@ -128,74 +80,15 @@ load_color_map_texture(struct gl_context *ctx, struct pipe_resource *pt) pipe_transfer_unmap(pipe, transfer); } - - -#define MAX_INST 100 - /** - * Returns a fragment program which implements the current pixel transfer ops. + * Upload the pixel transfer color map texture. */ -static struct gl_fragment_program * -get_pixel_transfer_program(struct gl_context *ctx, const struct state_key *key) +static void +update_pixel_transfer(struct st_context *st) { - struct st_context *st = st_context(ctx); - struct prog_instruction inst[MAX_INST]; - struct gl_program_parameter_list *params; - struct gl_fragment_program *fp; - GLuint ic = 0; - const GLuint colorTemp = 0; - - fp = (struct gl_fragment_program *) - ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); - if (!fp) - return NULL; - - params = _mesa_new_parameter_list(); - - /* - * Get initial pixel color from the texture. - * TEX colorTemp, fragment.texcoord[0], texture[0], 2D; - */ - _mesa_init_instructions(inst + ic, 1); - inst[ic].Opcode = OPCODE_TEX; - inst[ic].DstReg.File = PROGRAM_TEMPORARY; - inst[ic].DstReg.Index = colorTemp; - inst[ic].SrcReg[0].File = PROGRAM_INPUT; - inst[ic].SrcReg[0].Index = VARYING_SLOT_TEX0; - inst[ic].TexSrcUnit = 0; - inst[ic].TexSrcTarget = TEXTURE_2D_INDEX; - ic++; - fp->Base.InputsRead = BITFIELD64_BIT(VARYING_SLOT_TEX0); - fp->Base.OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR); - fp->Base.SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */ - - if (key->scaleAndBias) { - static const gl_state_index scale_state[STATE_LENGTH] = - { STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 }; - static const gl_state_index bias_state[STATE_LENGTH] = - { STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 }; - GLint scale_p, bias_p; - - scale_p = _mesa_add_state_reference(params, scale_state); - bias_p = _mesa_add_state_reference(params, bias_state); - - /* MAD colorTemp, colorTemp, scale, bias; */ - _mesa_init_instructions(inst + ic, 1); - inst[ic].Opcode = OPCODE_MAD; - inst[ic].DstReg.File = PROGRAM_TEMPORARY; - inst[ic].DstReg.Index = colorTemp; - inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY; - inst[ic].SrcReg[0].Index = colorTemp; - inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR; - inst[ic].SrcReg[1].Index = scale_p; - inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR; - inst[ic].SrcReg[2].Index = bias_p; - ic++; - } - - if (key->pixelMaps) { - const GLuint temp = 1; + struct gl_context *ctx = st->ctx; + if (ctx->Pixel.MapColorFlag) { /* create the colormap/texture now if not already done */ if (!st->pixel_xfer.pixelmap_texture) { st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx); @@ -203,117 +96,11 @@ get_pixel_transfer_program(struct gl_context *ctx, const struct state_key *key) st_create_texture_sampler_view(st->pipe, st->pixel_xfer.pixelmap_texture); } - - /* with a little effort, we can do four pixel map look-ups with - * two TEX instructions: - */ - - /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */ - _mesa_init_instructions(inst + ic, 1); - inst[ic].Opcode = OPCODE_TEX; - inst[ic].DstReg.File = PROGRAM_TEMPORARY; - inst[ic].DstReg.Index = temp; - inst[ic].DstReg.WriteMask = WRITEMASK_XY; /* write R,G */ - inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY; - inst[ic].SrcReg[0].Index = colorTemp; - inst[ic].TexSrcUnit = 1; - inst[ic].TexSrcTarget = TEXTURE_2D_INDEX; - ic++; - - /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */ - _mesa_init_instructions(inst + ic, 1); - inst[ic].Opcode = OPCODE_TEX; - inst[ic].DstReg.File = PROGRAM_TEMPORARY; - inst[ic].DstReg.Index = temp; - inst[ic].DstReg.WriteMask = WRITEMASK_ZW; /* write B,A */ - inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY; - inst[ic].SrcReg[0].Index = colorTemp; - inst[ic].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, - SWIZZLE_Z, SWIZZLE_W); - inst[ic].TexSrcUnit = 1; - inst[ic].TexSrcTarget = TEXTURE_2D_INDEX; - ic++; - - /* MOV colorTemp, temp; */ - _mesa_init_instructions(inst + ic, 1); - inst[ic].Opcode = OPCODE_MOV; - inst[ic].DstReg.File = PROGRAM_TEMPORARY; - inst[ic].DstReg.Index = colorTemp; - inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY; - inst[ic].SrcReg[0].Index = temp; - ic++; - - fp->Base.SamplersUsed |= (1 << 1); /* sampler 1 is used */ - } - - /* Modify last instruction's dst reg to write to result.color */ - { - struct prog_instruction *last = &inst[ic - 1]; - last->DstReg.File = PROGRAM_OUTPUT; - last->DstReg.Index = FRAG_RESULT_COLOR; - } - - /* END; */ - _mesa_init_instructions(inst + ic, 1); - inst[ic].Opcode = OPCODE_END; - ic++; - - assert(ic <= MAX_INST); - - - fp->Base.Instructions = _mesa_alloc_instructions(ic); - if (!fp->Base.Instructions) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, - "generating pixel transfer program"); - _mesa_free_parameter_list(params); - return NULL; - } - - _mesa_copy_instructions(fp->Base.Instructions, inst, ic); - fp->Base.NumInstructions = ic; - fp->Base.Parameters = params; - -#if 0 - printf("========= pixel transfer prog\n"); - _mesa_print_program(&fp->Base); - _mesa_print_parameter_list(fp->Base.Parameters); -#endif - - return fp; -} - - - -/** - * Update st->pixel_xfer.program in response to new pixel-transfer state. - */ -static void -update_pixel_transfer(struct st_context *st) -{ - struct gl_context *ctx = st->ctx; - struct state_key key; - struct gl_fragment_program *fp; - - make_state_key(st->ctx, &key); - - fp = (struct gl_fragment_program *) - _mesa_search_program_cache(st->pixel_xfer.cache, &key, sizeof(key)); - if (!fp) { - fp = get_pixel_transfer_program(st->ctx, &key); - _mesa_program_cache_insert(st->ctx, st->pixel_xfer.cache, - &key, sizeof(key), &fp->Base); - } - - if (ctx->Pixel.MapColorFlag) { load_color_map_texture(ctx, st->pixel_xfer.pixelmap_texture); } - st->pixel_xfer.pixelmap_enabled = ctx->Pixel.MapColorFlag; - - st->pixel_xfer.program = (struct st_fragment_program *) fp; } - const struct st_tracked_state st_update_pixel_transfer = { "st_update_pixel_transfer", /* name */ { /* dirty */ diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index f77d3049ae6..34163ede4a2 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -71,119 +71,6 @@ #include "cso_cache/cso_context.h" -/** - * Check if the given program is: - * 0: MOVE result.color, fragment.color; - * 1: END; - */ -static GLboolean -is_passthrough_program(const struct gl_fragment_program *prog) -{ - if (prog->Base.NumInstructions == 2) { - const struct prog_instruction *inst = prog->Base.Instructions; - if (inst[0].Opcode == OPCODE_MOV && - inst[1].Opcode == OPCODE_END && - inst[0].DstReg.File == PROGRAM_OUTPUT && - inst[0].DstReg.Index == FRAG_RESULT_COLOR && - inst[0].DstReg.WriteMask == WRITEMASK_XYZW && - inst[0].SrcReg[0].File == PROGRAM_INPUT && - inst[0].SrcReg[0].Index == VARYING_SLOT_COL0 && - inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) { - return GL_TRUE; - } - } - return GL_FALSE; -} - - -/** - * Returns a fragment program which implements the current pixel transfer ops. - */ -static struct gl_fragment_program * -get_glsl_pixel_transfer_program(struct st_context *st, - struct st_fragment_program *orig) -{ - int pixelMaps = 0, scaleAndBias = 0; - struct gl_context *ctx = st->ctx; - struct st_fragment_program *fp = (struct st_fragment_program *) - ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0); - - if (!fp) - return NULL; - - if (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) { - scaleAndBias = 1; - } - - pixelMaps = ctx->Pixel.MapColorFlag; - - if (pixelMaps) { - /* create the colormap/texture now if not already done */ - if (!st->pixel_xfer.pixelmap_texture) { - st->pixel_xfer.pixelmap_texture = st_create_color_map_texture(ctx); - st->pixel_xfer.pixelmap_sampler_view = - st_create_texture_sampler_view(st->pipe, - st->pixel_xfer.pixelmap_texture); - } - } - - get_pixel_transfer_visitor(fp, orig->glsl_to_tgsi, - scaleAndBias, pixelMaps); - - return &fp->Base; -} - - -/** - * Make fragment shader for glDraw/CopyPixels. This shader is made - * by combining the pixel transfer shader with the user-defined shader. - * \param fpIn the current/incoming fragment program - * \param fpOut returns the combined fragment program - */ -void -st_make_drawpix_fragment_program(struct st_context *st, - struct gl_fragment_program *fpIn, - struct gl_fragment_program **fpOut) -{ - struct gl_program *newProg; - struct st_fragment_program *stfp = (struct st_fragment_program *) fpIn; - - if (is_passthrough_program(fpIn)) { - newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx, - &st->pixel_xfer.program->Base); - } - else if (stfp->glsl_to_tgsi != NULL) { - newProg = (struct gl_program *) get_glsl_pixel_transfer_program(st, stfp); - } - else { -#if 0 - /* debug */ - printf("Base program:\n"); - _mesa_print_program(&fpIn->Base); - printf("DrawPix program:\n"); - _mesa_print_program(&st->pixel_xfer.program->Base.Base); -#endif - newProg = _mesa_combine_programs(st->ctx, - &st->pixel_xfer.program->Base.Base, - &fpIn->Base); - } - -#if 0 - /* 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 - - *fpOut = (struct gl_fragment_program *) newProg; -} - - /** * 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. @@ -1101,7 +988,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); color = NULL; - if (st->pixel_xfer.pixelmap_enabled) { + if (ctx->Pixel.MapColorFlag) { pipe_sampler_view_reference(&sv[1], st->pixel_xfer.pixelmap_sampler_view); num_sampler_view++; @@ -1439,7 +1326,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, driver_fp = fpv->driver_shader; driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); - if (st->pixel_xfer.pixelmap_enabled) { + if (ctx->Pixel.MapColorFlag) { pipe_sampler_view_reference(&sv[1], st->pixel_xfer.pixelmap_sampler_view); num_sampler_view++; @@ -1610,7 +1497,6 @@ st_destroy_drawpix(struct st_context *st) st->drawpix.zs_shaders[i]); } - st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); if (st->drawpix.vert_shaders[0]) cso_delete_vertex_shader(st->cso_context, st->drawpix.vert_shaders[0]); if (st->drawpix.vert_shaders[1]) diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h index c6649cbd51c..b8a34952141 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 struct dd_function_table; struct st_context; @@ -40,9 +41,9 @@ 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 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); #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 new file mode 100644 index 00000000000..01db0b6d73e --- /dev/null +++ b/src/mesa/state_tracker/st_cb_drawpixels_shader.c @@ -0,0 +1,255 @@ +/************************************************************************** + * + * Copyright (C) 2015 Advanced Micro Devices, Inc. + * Copyright 2007 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "st_cb_drawpixels.h" +#include "tgsi/tgsi_transform.h" +#include "tgsi/tgsi_scan.h" + +struct tgsi_drawpix_transform { + struct tgsi_transform_context base; + struct tgsi_shader_info info; + bool use_texcoord; + bool scale_and_bias; + bool pixel_maps; + bool first_instruction_emitted; + unsigned scale_const; + unsigned bias_const; + unsigned color_temp; +}; + +static inline struct tgsi_drawpix_transform * +tgsi_drawpix_transform(struct tgsi_transform_context *tctx) +{ + return (struct tgsi_drawpix_transform *)tctx; +} + +static void +set_src(struct tgsi_full_instruction *inst, unsigned i, unsigned file, unsigned index, + unsigned x, unsigned y, unsigned z, unsigned w) +{ + inst->Src[i].Register.File = file; + inst->Src[i].Register.Index = index; + inst->Src[i].Register.SwizzleX = x; + inst->Src[i].Register.SwizzleY = y; + inst->Src[i].Register.SwizzleZ = z; + inst->Src[i].Register.SwizzleW = w; +} + +#define SET_SRC(inst, i, file, index, x, y, z, w) \ + set_src(inst, i, file, index, TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, \ + TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w) + +static void +transform_instr(struct tgsi_transform_context *tctx, + struct tgsi_full_instruction *current_inst) +{ + struct tgsi_drawpix_transform *ctx = tgsi_drawpix_transform(tctx); + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + unsigned i, semantic; + int texcoord_index = -1; + + if (ctx->first_instruction_emitted) + goto transform_inst; + + ctx->first_instruction_emitted = true; + + /* Add scale and bias constants. */ + if (ctx->scale_and_bias) { + if (ctx->info.const_file_max[0] < (int)ctx->scale_const) { + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_CONSTANT; + decl.Range.First = decl.Range.Last = ctx->scale_const; + tctx->emit_declaration(tctx, &decl); + } + + if (ctx->info.const_file_max[0] < (int)ctx->bias_const) { + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_CONSTANT; + decl.Range.First = decl.Range.Last = ctx->bias_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(); + decl.Declaration.File = TGSI_FILE_TEMPORARY; + 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; + for (i = 0; i < ctx->info.num_inputs; i++) { + if (ctx->info.input_semantic_name[i] == semantic && + ctx->info.input_semantic_index[i] == 0) { + texcoord_index = i; + break; + } + } + + if (texcoord_index == -1) { + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_INPUT; + decl.Declaration.Semantic = 1; + decl.Semantic.Name = semantic; + decl.Declaration.Interpolate = 1; + decl.Interp.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; + decl.Range.First = decl.Range.Last = ctx->info.num_inputs; + texcoord_index = ctx->info.num_inputs; + tctx->emit_declaration(tctx, &decl); + } + + /* Declare the drawpix sampler if it's missing. */ + if (ctx->info.file_max[TGSI_FILE_SAMPLER] == -1) { + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_SAMPLER; + tctx->emit_declaration(tctx, &decl); + } + + /* Declare the pixel map sampler if it's missing. */ + if (ctx->info.file_max[TGSI_FILE_SAMPLER] <= 0) { + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_SAMPLER; + decl.Range.First = decl.Range.Last = 1; + tctx->emit_declaration(tctx, &decl); + } + + /* Get initial pixel color from the texture. + * TEX temp, fragment.texcoord[0], texture[0], 2D; + */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_TEX; + inst.Instruction.Texture = 1; + inst.Texture.Texture = TGSI_TEXTURE_2D; + + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->color_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + + 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; + + tctx->emit_instruction(tctx, &inst); + + /* Apply the scale and bias. */ + if (ctx->scale_and_bias) { + /* MAD temp, temp, scale, bias; */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_MAD; + + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->color_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; + + inst.Instruction.NumSrcRegs = 3; + SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->color_temp, X, Y, Z, W); + SET_SRC(&inst, 1, TGSI_FILE_CONSTANT, ctx->scale_const, X, Y, Z, W); + SET_SRC(&inst, 2, TGSI_FILE_CONSTANT, ctx->bias_const, X, Y, Z, W); + + tctx->emit_instruction(tctx, &inst); + } + + if (ctx->pixel_maps) { + /* do four pixel map look-ups with two TEX instructions: */ + + /* TEX temp.xy, temp.xyyy, texture[1], 2D; */ + inst = tgsi_default_full_instruction(); + inst.Instruction.Opcode = TGSI_OPCODE_TEX; + inst.Instruction.Texture = 1; + inst.Texture.Texture = TGSI_TEXTURE_2D; + + inst.Instruction.NumDstRegs = 1; + inst.Dst[0].Register.File = TGSI_FILE_TEMPORARY; + inst.Dst[0].Register.Index = ctx->color_temp; + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XY; + + 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; + + tctx->emit_instruction(tctx, &inst); + + /* TEX temp.zw, temp.zwww, texture[1], 2D; */ + inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_ZW; + SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->color_temp, Z, W, W, W); + tctx->emit_instruction(tctx, &inst); + } + + /* Now, "color_temp" should be used in place of IN:COLOR0 */ + +transform_inst: + + for (i = 0; i < current_inst->Instruction.NumSrcRegs; i++) { + 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 && + ctx->info.input_semantic_index[reg] == 0) { + src->Register.File = TGSI_FILE_TEMPORARY; + src->Register.Index = ctx->color_temp; + } + } + + tctx->emit_instruction(tctx, current_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) +{ + struct tgsi_drawpix_transform ctx; + struct tgsi_token *newtoks; + int newlen; + + memset(&ctx, 0, sizeof(ctx)); + ctx.base.transform_instruction = transform_instr; + ctx.use_texcoord = use_texcoord; + ctx.scale_and_bias = scale_and_bias; + ctx.scale_const = scale_const; + ctx.bias_const = bias_const; + ctx.pixel_maps = pixel_maps; + tgsi_scan_shader(tokens, &ctx.info); + + newlen = tgsi_num_tokens(tokens) + 30; + newtoks = tgsi_alloc_tokens(newlen); + if (!newtoks) + return NULL; + + tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base); + return newtoks; +} diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index a9ab5edcf49..bef7307bb27 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -224,8 +224,6 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE; - st->pixel_xfer.cache = _mesa_new_program_cache(); - st->has_stencil_export = screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT); st->has_shader_model3 = screen->get_param(screen, PIPE_CAP_SM3); @@ -386,8 +384,8 @@ void st_destroy_context( struct st_context *st ) pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL); } pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL); - - _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache); + pipe_sampler_view_reference(&st->pixel_xfer.pixelmap_sampler_view, NULL); + pipe_resource_reference(&st->pixel_xfer.pixelmap_texture, NULL); _vbo_DestroyContext(st->ctx); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 262581eceeb..f187d82449b 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -162,15 +162,8 @@ struct st_context struct gl_texture_object *default_texture; struct { - struct gl_program_cache *cache; - struct st_fragment_program *program; /**< cur pixel transfer prog */ - GLuint xfer_prog_sn; /**< pixel xfer program serial no. */ - GLuint user_prog_sn; /**< user fragment program serial no. */ - struct st_fragment_program *combined_prog; - GLuint combined_prog_sn; struct pipe_resource *pixelmap_texture; struct pipe_sampler_view *pixelmap_sampler_view; - boolean pixelmap_enabled; /**< use the pixelmap texture? */ } pixel_xfer; /** for glBitmap */ diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index a54ee17173a..cdd80f167d0 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -4334,138 +4334,6 @@ glsl_to_tgsi_visitor::renumber_registers(void) ralloc_free(first_reads); } -/** - * Returns a fragment program which implements the current pixel transfer ops. - * Based on get_pixel_transfer_program in st_atom_pixeltransfer.c. - */ -extern "C" void -get_pixel_transfer_visitor(struct st_fragment_program *fp, - glsl_to_tgsi_visitor *original, - int scale_and_bias, int pixel_maps) -{ - glsl_to_tgsi_visitor *v = new glsl_to_tgsi_visitor(); - struct st_context *st = st_context(original->ctx); - struct gl_program *prog = &fp->Base.Base; - struct gl_program_parameter_list *params = _mesa_new_parameter_list(); - st_src_reg coord, src0; - st_dst_reg dst0; - glsl_to_tgsi_instruction *inst; - - /* Copy attributes of the glsl_to_tgsi_visitor in the original shader. */ - v->ctx = original->ctx; - v->prog = prog; - v->shader_program = NULL; - v->shader = NULL; - v->glsl_version = original->glsl_version; - v->native_integers = original->native_integers; - v->options = original->options; - v->next_temp = original->next_temp; - v->num_address_regs = original->num_address_regs; - v->samplers_used = prog->SamplersUsed = original->samplers_used; - v->indirect_addr_consts = original->indirect_addr_consts; - memcpy(&v->immediates, &original->immediates, sizeof(v->immediates)); - v->num_immediates = original->num_immediates; - - /* - * Get initial pixel color from the texture. - * TEX colorTemp, fragment.texcoord[0], texture[0], 2D; - */ - coord = st_src_reg(PROGRAM_INPUT, VARYING_SLOT_TEX0, glsl_type::vec2_type); - src0 = v->get_temp(glsl_type::vec4_type); - dst0 = st_dst_reg(src0); - inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, dst0, coord); - inst->sampler_array_size = 1; - inst->tex_target = TEXTURE_2D_INDEX; - - prog->InputsRead |= VARYING_BIT_TEX0; - prog->SamplersUsed |= (1 << 0); /* mark sampler 0 as used */ - v->samplers_used |= (1 << 0); - - if (scale_and_bias) { - static const gl_state_index scale_state[STATE_LENGTH] = - { STATE_INTERNAL, STATE_PT_SCALE, - (gl_state_index) 0, (gl_state_index) 0, (gl_state_index) 0 }; - static const gl_state_index bias_state[STATE_LENGTH] = - { STATE_INTERNAL, STATE_PT_BIAS, - (gl_state_index) 0, (gl_state_index) 0, (gl_state_index) 0 }; - GLint scale_p, bias_p; - st_src_reg scale, bias; - - scale_p = _mesa_add_state_reference(params, scale_state); - bias_p = _mesa_add_state_reference(params, bias_state); - - /* MAD colorTemp, colorTemp, scale, bias; */ - scale = st_src_reg(PROGRAM_STATE_VAR, scale_p, GLSL_TYPE_FLOAT); - bias = st_src_reg(PROGRAM_STATE_VAR, bias_p, GLSL_TYPE_FLOAT); - inst = v->emit_asm(NULL, TGSI_OPCODE_MAD, dst0, src0, scale, bias); - } - - if (pixel_maps) { - st_src_reg temp = v->get_temp(glsl_type::vec4_type); - st_dst_reg temp_dst = st_dst_reg(temp); - - assert(st->pixel_xfer.pixelmap_texture); - (void) st; - - /* With a little effort, we can do four pixel map look-ups with - * two TEX instructions: - */ - - /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */ - temp_dst.writemask = WRITEMASK_XY; /* write R,G */ - inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, temp_dst, src0); - inst->sampler.index = 1; - inst->sampler_array_size = 1; - inst->tex_target = TEXTURE_2D_INDEX; - - /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */ - src0.swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W); - temp_dst.writemask = WRITEMASK_ZW; /* write B,A */ - inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, temp_dst, src0); - inst->sampler.index = 1; - inst->sampler_array_size = 1; - inst->tex_target = TEXTURE_2D_INDEX; - - prog->SamplersUsed |= (1 << 1); /* mark sampler 1 as used */ - v->samplers_used |= (1 << 1); - - /* MOV colorTemp, temp; */ - inst = v->emit_asm(NULL, TGSI_OPCODE_MOV, dst0, temp); - } - - /* Now copy the instructions from the original glsl_to_tgsi_visitor into the - * new visitor. */ - foreach_in_list(glsl_to_tgsi_instruction, inst, &original->instructions) { - glsl_to_tgsi_instruction *newinst; - st_src_reg src_regs[4]; - - if (inst->dst[0].file == PROGRAM_OUTPUT) - prog->OutputsWritten |= BITFIELD64_BIT(inst->dst[0].index); - - for (int i = 0; i < 4; i++) { - src_regs[i] = inst->src[i]; - if (src_regs[i].file == PROGRAM_INPUT && - src_regs[i].index == VARYING_SLOT_COL0) { - src_regs[i].file = PROGRAM_TEMPORARY; - src_regs[i].index = src0.index; - } - else if (src_regs[i].file == PROGRAM_INPUT) - prog->InputsRead |= BITFIELD64_BIT(src_regs[i].index); - } - - newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2], src_regs[3]); - newinst->tex_target = inst->tex_target; - newinst->sampler_array_size = inst->sampler_array_size; - } - - /* Make modifications to fragment program info. */ - prog->Parameters = _mesa_combine_parameter_lists(params, - original->prog->Parameters); - _mesa_free_parameter_list(params); - count_resources(v, prog); - fp->glsl_to_tgsi = v; -} - /* ------------------------- TGSI conversion stuff -------------------------- */ struct label { unsigned branch_target; diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.h b/src/mesa/state_tracker/st_glsl_to_tgsi.h index dcdfbebcbdc..729295bcb52 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.h +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.h @@ -55,9 +55,6 @@ enum pipe_error st_translate_program( const ubyte outputSemanticIndex[]); void free_glsl_to_tgsi_visitor(struct glsl_to_tgsi_visitor *v); -void get_pixel_transfer_visitor(struct st_fragment_program *fp, - struct glsl_to_tgsi_visitor *original, - int scale_and_bias, int pixel_maps); GLboolean st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index d900ede7265..01e33d04f74 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -540,8 +540,6 @@ st_translate_fragment_program(struct st_context *st, { struct pipe_context *pipe = st->pipe; struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant); - GLboolean deleteFP = GL_FALSE; - GLuint outputMapping[FRAG_RESULT_MAX]; GLuint inputMapping[VARYING_SLOT_MAX]; GLuint inputSlotToAttr[VARYING_SLOT_MAX]; @@ -567,16 +565,6 @@ st_translate_fragment_program(struct st_context *st, assert(!(key->bitmap && key->drawpixels)); memset(inputSlotToAttr, ~0, sizeof(inputSlotToAttr)); - if (key->drawpixels) { - /* glDrawPixels color drawing */ - struct gl_fragment_program *fp; /* we free this temp program below */ - - st_make_drawpix_fragment_program(st, &stfp->Base, &fp); - variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); - deleteFP = GL_TRUE; - stfp = st_fragment_program(fp); - } - if (!stfp->glsl_to_tgsi) _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); @@ -895,6 +883,38 @@ st_translate_fragment_program(struct st_context *st, fprintf(stderr, "mesa: cannot create a shader for glBitmap\n"); } + /* glDrawPixels (color only) */ + if (key->drawpixels) { + const struct tgsi_token *tokens; + unsigned scale_const = 0, bias_const = 0; + + variant->parameters = + _mesa_clone_parameter_list(stfp->Base.Base.Parameters); + + if (key->scaleAndBias) { + static const gl_state_index scale_state[STATE_LENGTH] = + { STATE_INTERNAL, STATE_PT_SCALE }; + static const gl_state_index bias_state[STATE_LENGTH] = + { STATE_INTERNAL, STATE_PT_BIAS }; + + scale_const = _mesa_add_state_reference(variant->parameters, + scale_state); + bias_const = _mesa_add_state_reference(variant->parameters, + bias_state); + } + + tokens = st_get_drawpix_shader(variant->tgsi.tokens, + st->needs_texcoord_semantic, + key->scaleAndBias, scale_const, + bias_const, key->pixelMaps); + + if (tokens) { + tgsi_free_tokens(variant->tgsi.tokens); + variant->tgsi.tokens = tokens; + } else + fprintf(stderr, "mesa: cannot create a shader for glDrawPixels\n"); + } + if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump(variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/); debug_printf("\n"); @@ -903,13 +923,6 @@ st_translate_fragment_program(struct st_context *st, /* fill in variant */ variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi); variant->key = *key; - - if (deleteFP) { - /* Free the temporary program made above */ - struct gl_fragment_program *fp = &stfp->Base; - _mesa_reference_fragprog(st->ctx, &fp, NULL); - } - return variant; }