wined3d: Move program_dump_decl_usage into baseshader.
[wine] / dlls / wined3d / baseshader.c
1 /*
2  * shaders implementation
3  *
4  * Copyright 2002-2003 Jason Edmeades
5  * Copyright 2002-2003 Raphael Junqueira
6  * Copyright 2005 Oliver Stieber
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include <string.h>
25 #include <stdio.h>
26 #include "wined3d_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
29
30 inline static BOOL shader_is_version_token(DWORD token) {
31     return 0xFFFF0000 == (token & 0xFFFF0000) || 
32            0xFFFE0000 == (token & 0xFFFF0000);
33 }
34
35 inline static BOOL shader_is_comment_token(DWORD token) {
36     return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
37 }
38
39 int shader_addline(
40     SHADER_BUFFER* buffer,  
41     const char *format, ...) {
42
43     char* base = buffer->buffer + buffer->bsize;
44     int rc;
45
46     va_list args;
47     va_start(args, format);
48     rc = vsnprintf(base, SHADER_PGMSIZE - 1 - buffer->bsize, format, args);
49     va_end(args);
50
51     if (rc < 0 ||                                   /* C89 */ 
52         rc > SHADER_PGMSIZE - 1 - buffer->bsize) {  /* C99 */
53
54         ERR("The buffer allocated for the shader program string "
55             "is too small at %d bytes.\n", SHADER_PGMSIZE);
56         buffer->bsize = SHADER_PGMSIZE - 1;
57         return -1;
58     }
59
60     buffer->bsize += rc;
61     buffer->lineNo++;
62     TRACE("GL HW (%u, %u) : %s", buffer->lineNo, buffer->bsize, base); 
63     return 0;
64 }
65
66 const SHADER_OPCODE* shader_get_opcode(
67     IWineD3DBaseShader *iface, const DWORD code) {
68
69     IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl*) iface;
70
71     DWORD i = 0;
72     DWORD version = This->baseShader.version;
73     DWORD hex_version = This->baseShader.hex_version;
74     const SHADER_OPCODE *shader_ins = This->baseShader.shader_ins;
75
76     /** TODO: use dichotomic search */
77     while (NULL != shader_ins[i].name) {
78         if (((code & D3DSI_OPCODE_MASK) == shader_ins[i].opcode) &&
79             (((hex_version >= shader_ins[i].min_version) && (hex_version <= shader_ins[i].max_version)) ||
80             ((shader_ins[i].min_version == 0) && (shader_ins[i].max_version == 0)))) {
81             return &shader_ins[i];
82         }
83         ++i;
84     }
85     FIXME("Unsupported opcode %lx(%ld) masked %lx version %ld\n", 
86        code, code, code & D3DSI_OPCODE_MASK, version);
87     return NULL;
88 }
89
90 /* Note: For vertex shaders,
91  * texUsed = addrUsed, and 
92  * D3DSPR_TEXTURE = D3DSPR_ADDR. 
93  *
94  * Also note that this does not count the loop register
95  * as an address register. */   
96
97 void shader_get_registers_used(
98     IWineD3DBaseShader *iface,
99     CONST DWORD* pToken, 
100     DWORD* tempsUsed, 
101     DWORD* texUsed) {
102
103     if (pToken == NULL)
104         return;
105
106     *tempsUsed = 0;
107     *texUsed = 0;
108
109     while (D3DVS_END() != *pToken) {
110         CONST SHADER_OPCODE* curOpcode;
111
112         /* Skip version */
113         if (shader_is_version_token(*pToken)) {
114              ++pToken;
115              continue;
116
117         /* Skip comments */
118         } else if (shader_is_comment_token(*pToken)) {
119              DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
120              ++pToken;
121              pToken += comment_len;
122              continue;
123         }
124
125         /* Fetch opcode */
126         curOpcode = shader_get_opcode(iface, *pToken);
127         ++pToken;
128
129         /* Unhandled opcode, and its parameters */
130         if (NULL == curOpcode) {
131            while (*pToken & 0x80000000)
132                ++pToken;
133            continue;
134
135         /* Skip declarations (for now) */
136         } else if (D3DSIO_DCL == curOpcode->opcode) {
137             pToken += curOpcode->num_params;
138             continue;
139
140         /* Skip definitions (for now) */
141         } else if (D3DSIO_DEF == curOpcode->opcode) {
142             pToken += curOpcode->num_params;
143             continue;
144
145         /* Set texture registers, and temporary registers */
146         } else {
147             int i;
148
149             for (i = 0; i < curOpcode->num_params; ++i) {
150                 DWORD regtype = (((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
151                 DWORD reg = (*pToken) & D3DSP_REGNUM_MASK;
152                 if (D3DSPR_TEXTURE == regtype)
153                     *texUsed |= (1 << reg);
154                 if (D3DSPR_TEMP == regtype)
155                     *tempsUsed |= (1 << reg);
156                 ++pToken;
157              }
158         }
159     }
160 }
161
162 void shader_program_dump_decl_usage(
163     DWORD decl, 
164     DWORD param) {
165
166     DWORD regtype = shader_get_regtype(param);
167     TRACE("dcl_");
168
169     if (regtype == D3DSPR_SAMPLER) {
170         DWORD ttype = decl & D3DSP_TEXTURETYPE_MASK;
171
172         switch (ttype) {
173             case D3DSTT_2D: TRACE("2d"); break;
174             case D3DSTT_CUBE: TRACE("cube"); break;
175             case D3DSTT_VOLUME: TRACE("volume"); break;
176             default: TRACE("unknown_ttype(%08lx)", ttype); 
177        }
178
179     } else { 
180
181         DWORD usage = decl & D3DSP_DCL_USAGE_MASK;
182         DWORD idx = (decl & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
183
184         switch(usage) {
185         case D3DDECLUSAGE_POSITION:
186             TRACE("%s%ld", "position", idx);
187             break;
188         case D3DDECLUSAGE_BLENDINDICES:
189             TRACE("%s", "blend");
190             break;
191         case D3DDECLUSAGE_BLENDWEIGHT:
192             TRACE("%s", "weight");
193             break;
194         case D3DDECLUSAGE_NORMAL:
195             TRACE("%s%ld", "normal", idx);
196             break;
197         case D3DDECLUSAGE_PSIZE:
198             TRACE("%s", "psize");
199             break;
200         case D3DDECLUSAGE_COLOR:
201             if(idx == 0)  {
202                 TRACE("%s", "color");
203             } else {
204                 TRACE("%s%ld", "specular", (idx - 1));
205             }
206             break;
207         case D3DDECLUSAGE_TEXCOORD:
208             TRACE("%s%ld", "texture", idx);
209             break;
210         case D3DDECLUSAGE_TANGENT:
211             TRACE("%s", "tangent");
212             break;
213         case D3DDECLUSAGE_BINORMAL:
214             TRACE("%s", "binormal");
215             break;
216         case D3DDECLUSAGE_TESSFACTOR:
217             TRACE("%s", "tessfactor");
218             break;
219         case D3DDECLUSAGE_POSITIONT:
220             TRACE("%s%ld", "positionT", idx);
221             break;
222         case D3DDECLUSAGE_FOG:
223             TRACE("%s", "fog");
224             break;
225         case D3DDECLUSAGE_DEPTH:
226             TRACE("%s", "depth");
227             break;
228         case D3DDECLUSAGE_SAMPLE:
229             TRACE("%s", "sample");
230             break;
231         default:
232             FIXME("unknown_semantics(%08lx)", usage);
233         }
234     }
235 }
236
237 /* TODO: Move other shared code here */