st/mesa: implement DrawPixels shader transformation using tgsi_transform_shader

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-04 02:38:55 +02:00
parent b55b986dc9
commit f15bb3e633
10 changed files with 303 additions and 504 deletions

View File

@@ -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 \

View File

@@ -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 */

View File

@@ -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])

View File

@@ -31,6 +31,7 @@
#include "main/compiler.h"
#include <stdbool.h>
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 */

View File

@@ -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 = &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 &&
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;
}

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}