aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/r300/radeon_mesa_to_rc.c
blob: 9f9dec840b41cb18e2caa5843fb8f5035ac4012a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
 * Copyright (C) 2009 Nicolai Haehnle.
 *
 * 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, sublicense, 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 NONINFRINGEMENT.
 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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 "radeon_mesa_to_rc.h"

#include "main/mtypes.h"
#include "shader/prog_instruction.h"
#include "shader/prog_parameter.h"

#include "compiler/radeon_compiler.h"
#include "compiler/radeon_program.h"


static rc_opcode translate_opcode(gl_inst_opcode opcode)
{
	switch(opcode) {
	case OPCODE_NOP: return RC_OPCODE_NOP;
	case OPCODE_ABS: return RC_OPCODE_ABS;
	case OPCODE_ADD: return RC_OPCODE_ADD;
	case OPCODE_ARL: return RC_OPCODE_ARL;
	case OPCODE_CMP: return RC_OPCODE_CMP;
	case OPCODE_COS: return RC_OPCODE_COS;
	case OPCODE_DDX: return RC_OPCODE_DDX;
	case OPCODE_DDY: return RC_OPCODE_DDY;
	case OPCODE_DP3: return RC_OPCODE_DP3;
	case OPCODE_DP4: return RC_OPCODE_DP4;
	case OPCODE_DPH: return RC_OPCODE_DPH;
	case OPCODE_DST: return RC_OPCODE_DST;
	case OPCODE_EX2: return RC_OPCODE_EX2;
	case OPCODE_EXP: return RC_OPCODE_EXP;
	case OPCODE_FLR: return RC_OPCODE_FLR;
	case OPCODE_FRC: return RC_OPCODE_FRC;
	case OPCODE_KIL: return RC_OPCODE_KIL;
	case OPCODE_LG2: return RC_OPCODE_LG2;
	case OPCODE_LIT: return RC_OPCODE_LIT;
	case OPCODE_LOG: return RC_OPCODE_LOG;
	case OPCODE_LRP: return RC_OPCODE_LRP;
	case OPCODE_MAD: return RC_OPCODE_MAD;
	case OPCODE_MAX: return RC_OPCODE_MAX;
	case OPCODE_MIN: return RC_OPCODE_MIN;
	case OPCODE_MOV: return RC_OPCODE_MOV;
	case OPCODE_MUL: return RC_OPCODE_MUL;
	case OPCODE_POW: return RC_OPCODE_POW;
	case OPCODE_RCP: return RC_OPCODE_RCP;
	case OPCODE_RSQ: return RC_OPCODE_RSQ;
	case OPCODE_SCS: return RC_OPCODE_SCS;
	case OPCODE_SEQ: return RC_OPCODE_SEQ;
	case OPCODE_SFL: return RC_OPCODE_SFL;
	case OPCODE_SGE: return RC_OPCODE_SGE;
	case OPCODE_SGT: return RC_OPCODE_SGT;
	case OPCODE_SIN: return RC_OPCODE_SIN;
	case OPCODE_SLE: return RC_OPCODE_SLE;
	case OPCODE_SLT: return RC_OPCODE_SLT;
	case OPCODE_SNE: return RC_OPCODE_SNE;
	case OPCODE_SUB: return RC_OPCODE_SUB;
	case OPCODE_SWZ: return RC_OPCODE_SWZ;
	case OPCODE_TEX: return RC_OPCODE_TEX;
	case OPCODE_TXB: return RC_OPCODE_TXB;
	case OPCODE_TXD: return RC_OPCODE_TXD;
	case OPCODE_TXL: return RC_OPCODE_TXL;
	case OPCODE_TXP: return RC_OPCODE_TXP;
	case OPCODE_XPD: return RC_OPCODE_XPD;
	default: return RC_OPCODE_ILLEGAL_OPCODE;
	}
}

static rc_saturate_mode translate_saturate(unsigned int saturate)
{
	switch(saturate) {
	default:
	case SATURATE_OFF: return RC_SATURATE_NONE;
	case SATURATE_ZERO_ONE: return RC_SATURATE_ZERO_ONE;
	}
}

static rc_register_file translate_register_file(unsigned int file)
{
	switch(file) {
	case PROGRAM_TEMPORARY: return RC_FILE_TEMPORARY;
	case PROGRAM_INPUT: return RC_FILE_INPUT;
	case PROGRAM_OUTPUT: return RC_FILE_OUTPUT;
	case PROGRAM_LOCAL_PARAM:
	case PROGRAM_ENV_PARAM:
	case PROGRAM_STATE_VAR:
	case PROGRAM_NAMED_PARAM:
	case PROGRAM_CONSTANT:
	case PROGRAM_UNIFORM: return RC_FILE_CONSTANT;
	case PROGRAM_ADDRESS: return RC_FILE_ADDRESS;
	default: return RC_FILE_NONE;
	}
}

static void translate_srcreg(struct rc_src_register * dest, struct prog_src_register * src)
{
	dest->File = translate_register_file(src->File);
	dest->Index = src->Index;
	dest->RelAddr = src->RelAddr;
	dest->Swizzle = src->Swizzle;
	dest->Abs = src->Abs;
	dest->Negate = src->Negate;
}

static void translate_dstreg(struct rc_dst_register * dest, struct prog_dst_register * src)
{
	dest->File = translate_register_file(src->File);
	dest->Index = src->Index;
	dest->RelAddr = src->RelAddr;
	dest->WriteMask = src->WriteMask;
}

static rc_texture_target translate_tex_target(gl_texture_index target)
{
	switch(target) {
	case TEXTURE_2D_ARRAY_INDEX: return RC_TEXTURE_2D_ARRAY;
	case TEXTURE_1D_ARRAY_INDEX: return RC_TEXTURE_1D_ARRAY;
	case TEXTURE_CUBE_INDEX: return RC_TEXTURE_CUBE;
	case TEXTURE_3D_INDEX: return RC_TEXTURE_3D;
	case TEXTURE_RECT_INDEX: return RC_TEXTURE_RECT;
	default:
	case TEXTURE_2D_INDEX: return RC_TEXTURE_2D;
	case TEXTURE_1D_INDEX: return RC_TEXTURE_1D;
	}
}

static void translate_instruction(struct radeon_compiler * c,
		struct rc_instruction * dest, struct prog_instruction * src)
{
	const struct rc_opcode_info * opcode;
	unsigned int i;

	dest->U.I.Opcode = translate_opcode(src->Opcode);
	if (dest->U.I.Opcode == RC_OPCODE_ILLEGAL_OPCODE) {
		rc_error(c, "Unsupported opcode %i\n", src->Opcode);
		return;
	}
	dest->U.I.SaturateMode = translate_saturate(src->SaturateMode);

	opcode = rc_get_opcode_info(dest->U.I.Opcode);

	for(i = 0; i < opcode->NumSrcRegs; ++i)
		translate_srcreg(&dest->U.I.SrcReg[i], &src->SrcReg[i]);

	if (opcode->HasDstReg)
		translate_dstreg(&dest->U.I.DstReg, &src->DstReg);

	if (opcode->HasTexture) {
		dest->U.I.TexSrcUnit = src->TexSrcUnit;
		dest->U.I.TexSrcTarget = translate_tex_target(src->TexSrcTarget);
		dest->U.I.TexShadow = src->TexShadow;
	}
}

void radeon_mesa_to_rc_program(struct radeon_compiler * c, struct gl_program * program)
{
	struct prog_instruction *source;
	unsigned int i;

	for(source = program->Instructions; source->Opcode != OPCODE_END; ++source) {
		struct rc_instruction * dest = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
		translate_instruction(c, dest, source);
	}

	c->Program.ShadowSamplers = program->ShadowSamplers;
	c->Program.InputsRead = program->InputsRead;
	c->Program.OutputsWritten = program->OutputsWritten;

	int isNVProgram = 0;

	if (program->Target == GL_VERTEX_PROGRAM_ARB) {
		struct gl_vertex_program * vp = (struct gl_vertex_program *) program;
		isNVProgram = vp->IsNVProgram;
	}

	if (isNVProgram) {
		/* NV_vertex_program has a fixed-sized constant environment.
		 * This could be handled more efficiently for programs that
		 * do not use relative addressing.
		 */
		for(i = 0; i < 96; ++i) {
			struct rc_constant constant;

			constant.Type = RC_CONSTANT_EXTERNAL;
			constant.Size = 4;
			constant.u.External = i;

			rc_constants_add(&c->Program.Constants, &constant);
		}
	} else {
		for(i = 0; i < program->Parameters->NumParameters; ++i) {
			struct rc_constant constant;

			constant.Type = RC_CONSTANT_EXTERNAL;
			constant.Size = 4;
			constant.u.External = i;

			rc_constants_add(&c->Program.Constants, &constant);
		}
	}
}