d3dx9: D3DXAssembleShaderFromResource implementation.
[wine] / dlls / d3dx9_36 / shader.c
1 /*
2  * Copyright 2008 Luis Busquets
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21 #include "wine/debug.h"
22 #include "wine/unicode.h"
23 #include "windef.h"
24 #include "wingdi.h"
25 #include "d3dx9.h"
26 #include "d3dx9_36_private.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
29
30 LPCSTR WINAPI D3DXGetPixelShaderProfile(LPDIRECT3DDEVICE9 device)
31 {
32     D3DCAPS9 caps;
33
34     TRACE("device %p\n", device);
35
36     if (!device) return NULL;
37
38     IDirect3DDevice9_GetDeviceCaps(device,&caps);
39
40     switch (caps.PixelShaderVersion)
41     {
42     case D3DPS_VERSION(1, 1):
43         return "ps_1_1";
44
45     case D3DPS_VERSION(1, 2):
46         return "ps_1_2";
47
48     case D3DPS_VERSION(1, 3):
49         return "ps_1_3";
50
51     case D3DPS_VERSION(1, 4):
52         return "ps_1_4";
53
54     case D3DPS_VERSION(2, 0):
55         if ((caps.PS20Caps.NumTemps>=22)                          &&
56             (caps.PS20Caps.Caps&D3DPS20CAPS_ARBITRARYSWIZZLE)     &&
57             (caps.PS20Caps.Caps&D3DPS20CAPS_GRADIENTINSTRUCTIONS) &&
58             (caps.PS20Caps.Caps&D3DPS20CAPS_PREDICATION)          &&
59             (caps.PS20Caps.Caps&D3DPS20CAPS_NODEPENDENTREADLIMIT) &&
60             (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
61         {
62             return "ps_2_a";
63         }
64         if ((caps.PS20Caps.NumTemps>=32)                          &&
65             (caps.PS20Caps.Caps&D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT))
66         {
67             return "ps_2_b";
68         }
69         return "ps_2_0";
70
71     case D3DPS_VERSION(3, 0):
72         return "ps_3_0";
73     }
74
75     return NULL;
76 }
77
78 UINT WINAPI D3DXGetShaderSize(const DWORD *byte_code)
79 {
80     const DWORD *ptr = byte_code;
81
82     TRACE("byte_code %p\n", byte_code);
83
84     if (!ptr) return 0;
85
86     /* Look for the END token, skipping the VERSION token */
87     while (*++ptr != D3DSIO_END)
88     {
89         /* Skip comments */
90         if ((*ptr & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT)
91         {
92             ptr += ((*ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
93         }
94     }
95     ++ptr;
96
97     /* Return the shader size in bytes */
98     return (ptr - byte_code) * sizeof(*ptr);
99 }
100
101 DWORD WINAPI D3DXGetShaderVersion(const DWORD *byte_code)
102 {
103     TRACE("byte_code %p\n", byte_code);
104
105     return byte_code ? *byte_code : 0;
106 }
107
108 LPCSTR WINAPI D3DXGetVertexShaderProfile(LPDIRECT3DDEVICE9 device)
109 {
110     D3DCAPS9 caps;
111
112     TRACE("device %p\n", device);
113
114     if (!device) return NULL;
115
116     IDirect3DDevice9_GetDeviceCaps(device,&caps);
117
118     switch (caps.VertexShaderVersion)
119     {
120     case D3DVS_VERSION(1, 1):
121         return "vs_1_1";
122     case D3DVS_VERSION(2, 0):
123         if ((caps.VS20Caps.NumTemps>=13) &&
124             (caps.VS20Caps.DynamicFlowControlDepth==24) &&
125             (caps.VS20Caps.Caps&D3DPS20CAPS_PREDICATION))
126         {
127             return "vs_2_a";
128         }
129         return "vs_2_0";
130     case D3DVS_VERSION(3, 0):
131         return "vs_3_0";
132     }
133
134     return NULL;
135 }
136
137 HRESULT WINAPI D3DXAssembleShader(LPCSTR data,
138                                   UINT data_len,
139                                   CONST D3DXMACRO* defines,
140                                   LPD3DXINCLUDE include,
141                                   DWORD flags,
142                                   LPD3DXBUFFER* shader,
143                                   LPD3DXBUFFER* error_messages)
144 {
145     FIXME("stub\n");
146     return D3DERR_INVALIDCALL;
147 }
148
149 HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
150                                            CONST D3DXMACRO* defines,
151                                            LPD3DXINCLUDE include,
152                                            DWORD flags,
153                                            LPD3DXBUFFER* shader,
154                                            LPD3DXBUFFER* error_messages)
155 {
156     LPWSTR filename_w = NULL;
157     DWORD len;
158     HRESULT ret;
159
160     if (!filename) return D3DXERR_INVALIDDATA;
161
162     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
163     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
164     if (!filename_w) return E_OUTOFMEMORY;
165     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
166
167     ret = D3DXAssembleShaderFromFileW(filename_w, defines, include, flags, shader, error_messages);
168
169     HeapFree(GetProcessHeap(), 0, filename_w);
170     return ret;
171 }
172
173 HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
174                                            CONST D3DXMACRO* defines,
175                                            LPD3DXINCLUDE include,
176                                            DWORD flags,
177                                            LPD3DXBUFFER* shader,
178                                            LPD3DXBUFFER* error_messages)
179 {
180     FIXME("stub\n");
181     return D3DERR_INVALIDCALL;
182 }
183
184 HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module,
185                                                LPCSTR resource,
186                                                CONST D3DXMACRO* defines,
187                                                LPD3DXINCLUDE include,
188                                                DWORD flags,
189                                                LPD3DXBUFFER* shader,
190                                                LPD3DXBUFFER* error_messages)
191 {
192     HRSRC res;
193     LPCSTR buffer;
194     DWORD len;
195
196     if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
197         return D3DXERR_INVALIDDATA;
198     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
199         return D3DXERR_INVALIDDATA;
200     return D3DXAssembleShader(buffer, len, defines, include, flags,
201                               shader, error_messages);
202 }
203
204 HRESULT WINAPI D3DXAssembleShaderFromResourceW(HMODULE module,
205                                                LPCWSTR resource,
206                                                CONST D3DXMACRO* defines,
207                                                LPD3DXINCLUDE include,
208                                                DWORD flags,
209                                                LPD3DXBUFFER* shader,
210                                                LPD3DXBUFFER* error_messages)
211 {
212     HRSRC res;
213     LPCSTR buffer;
214     DWORD len;
215
216     if (!(res = FindResourceW(module, resource, (LPCWSTR)RT_RCDATA)))
217         return D3DXERR_INVALIDDATA;
218     if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
219         return D3DXERR_INVALIDDATA;
220     return D3DXAssembleShader(buffer, len, defines, include, flags,
221                               shader, error_messages);
222 }