Add Clear, Present and EndScene support and fix a bug in the drawing
[wine] / dlls / d3d9 / pixelshader.c
1 /*
2  * IDirect3DPixelShader9 implementation
3  *
4  * Copyright 2002-2003 Jason Edmeades
5  *                     Raphael Junqueira
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "d3d9_private.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
26
27 /* IDirect3DPixelShader9 IUnknown parts follow: */
28 HRESULT WINAPI IDirect3DPixelShader9Impl_QueryInterface(LPDIRECT3DPIXELSHADER9 iface, REFIID riid, LPVOID* ppobj) {
29     IDirect3DPixelShader9Impl *This = (IDirect3DPixelShader9Impl *)iface;
30
31     if (IsEqualGUID(riid, &IID_IUnknown)
32         || IsEqualGUID(riid, &IID_IDirect3DPixelShader9)) {
33         IDirect3DPixelShader9Impl_AddRef(iface);
34         *ppobj = This;
35         return D3D_OK;
36     }
37
38     WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
39     return E_NOINTERFACE;
40 }
41
42 ULONG WINAPI IDirect3DPixelShader9Impl_AddRef(LPDIRECT3DPIXELSHADER9 iface) {
43     IDirect3DPixelShader9Impl *This = (IDirect3DPixelShader9Impl *)iface;
44     TRACE("(%p) : AddRef from %ld\n", This, This->ref);
45     return ++(This->ref);
46 }
47
48 ULONG WINAPI IDirect3DPixelShader9Impl_Release(LPDIRECT3DPIXELSHADER9 iface) {
49     IDirect3DPixelShader9Impl *This = (IDirect3DPixelShader9Impl *)iface;
50     ULONG ref = --This->ref;
51
52     TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
53     if (ref == 0) {
54         HeapFree(GetProcessHeap(), 0, This);
55     }
56     return ref;
57 }
58
59 /* IDirect3DPixelShader9 Interface follow: */
60 HRESULT WINAPI IDirect3DPixelShader9Impl_GetDevice(LPDIRECT3DPIXELSHADER9 iface, IDirect3DDevice9** ppDevice) {
61     IDirect3DPixelShader9Impl *This = (IDirect3DPixelShader9Impl *)iface;
62     TRACE("(%p) : returning %p\n", This, This->Device);
63     *ppDevice = (LPDIRECT3DDEVICE9) This->Device;
64     IDirect3DDevice9Impl_AddRef(*ppDevice);
65     return D3D_OK;
66 }
67
68 HRESULT WINAPI IDirect3DPixelShader9Impl_GetFunction(LPDIRECT3DPIXELSHADER9 iface, VOID* pData, UINT* pSizeOfData) {
69     IDirect3DPixelShader9Impl *This = (IDirect3DPixelShader9Impl *)iface;
70     FIXME("(%p): stub\n", This);
71     return D3D_OK;
72 }
73
74
75 IDirect3DPixelShader9Vtbl Direct3DPixelShader9_Vtbl =
76 {
77     IDirect3DPixelShader9Impl_QueryInterface,
78     IDirect3DPixelShader9Impl_AddRef,
79     IDirect3DPixelShader9Impl_Release,
80     IDirect3DPixelShader9Impl_GetDevice,
81     IDirect3DPixelShader9Impl_GetFunction
82 };
83
84
85 /* IDirect3DDevice9 IDirect3DPixelShader9 Methods follow:  */
86 HRESULT WINAPI IDirect3DDevice9Impl_CreatePixelShader(LPDIRECT3DDEVICE9 iface, CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) {
87     IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
88     FIXME("(%p) : stub\n", This);
89     return D3D_OK;
90 }
91
92 HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShader(LPDIRECT3DDEVICE9 iface, IDirect3DPixelShader9* pShader) {
93     IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
94
95     This->UpdateStateBlock->PixelShader = pShader;
96     This->UpdateStateBlock->Changed.pixelShader = TRUE;
97     This->UpdateStateBlock->Set.pixelShader = TRUE;
98     
99     /* Handle recording of state blocks */
100     if (This->isRecordingState) {
101       TRACE("Recording... not performing anything\n");
102       return D3D_OK;
103     }
104     /**
105      * TODO: merge HAL shaders context switching from prototype
106      */
107     return D3D_OK;
108 }
109
110 HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShader(LPDIRECT3DDEVICE9 iface, IDirect3DPixelShader9** ppShader) {
111     IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
112     TRACE("(%p) : GetPixelShader returning %p\n", This, This->StateBlock->PixelShader);
113     *ppShader = This->StateBlock->PixelShader;
114     IDirect3DPixelShader9Impl_AddRef(*ppShader);
115     return D3D_OK;
116 }
117
118 HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT Register, CONST float* pConstantData, UINT Vector4fCount) {
119   IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
120
121   if (Register + Vector4fCount > D3D_VSHADER_MAX_CONSTANTS) {
122     ERR("(%p) : SetPixelShaderConstant C[%u] invalid\n", This, Register);
123     return D3DERR_INVALIDCALL;
124   }
125   if (NULL == pConstantData) {
126     return D3DERR_INVALIDCALL;
127   }
128   if (Vector4fCount > 1) {
129     CONST FLOAT* f = pConstantData;
130     UINT i;
131     TRACE("(%p) : SetPixelShaderConstant C[%u..%u]=\n", This, Register, Register + Vector4fCount - 1);
132     for (i = 0; i < Vector4fCount; ++i) {
133       TRACE("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
134       f += 4;
135     }
136   } else { 
137     const FLOAT* f = (const FLOAT*) pConstantData;
138     TRACE("(%p) : SetPixelShaderConstant, C[%u]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
139   }
140   This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
141   memcpy(&This->UpdateStateBlock->pixelShaderConstantF[Register], pConstantData, Vector4fCount * 4 * sizeof(FLOAT));
142   return D3D_OK;
143 }
144
145 HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantF(LPDIRECT3DDEVICE9 iface, UINT Register, float* pConstantData, UINT Vector4fCount) {
146   IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
147
148   TRACE("(%p) : C[%u] count=%u\n", This, Register, Vector4fCount);
149   if (Register + Vector4fCount > D3D_VSHADER_MAX_CONSTANTS) {
150     return D3DERR_INVALIDCALL;
151   }
152   if (NULL == pConstantData) {
153     return D3DERR_INVALIDCALL;
154   }
155   memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstantF[Register], Vector4fCount * 4 * sizeof(FLOAT));
156   return D3D_OK;
157 }
158
159 HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT Register, CONST int* pConstantData, UINT Vector4iCount) {
160   IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
161
162   if (Register + Vector4iCount > D3D_VSHADER_MAX_CONSTANTS) {
163     ERR("(%p) : SetPixelShaderConstantI C[%u] invalid\n", This, Register);
164     return D3DERR_INVALIDCALL;
165   }
166   if (NULL == pConstantData) {
167     return D3DERR_INVALIDCALL;
168   }
169   if (Vector4iCount > 1) {
170     CONST int* f = pConstantData;
171     UINT i;
172     TRACE("(%p) : SetPixelShaderConstantI C[%u..%u]=\n", This, Register, Register + Vector4iCount - 1);
173     for (i = 0; i < Vector4iCount; ++i) {
174       TRACE("{%d, %d, %d, %d}\n", f[0], f[1], f[2], f[3]);
175       f += 4;
176     }
177   } else { 
178     CONST int* f = pConstantData;
179     TRACE("(%p) : SetPixelShaderConstantI, C[%u]={%i, %i, %i, %i}\n", This, Register, f[0], f[1], f[2], f[3]);
180   }
181   This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
182   memcpy(&This->UpdateStateBlock->pixelShaderConstantI[Register], pConstantData, Vector4iCount * 4 * sizeof(int));
183   return D3D_OK;
184 }
185
186 HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantI(LPDIRECT3DDEVICE9 iface, UINT Register, int* pConstantData, UINT Vector4iCount) {
187   IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
188
189   TRACE("(%p) : C[%u] count=%u\n", This, Register, Vector4iCount);
190   if (Register + Vector4iCount > D3D_VSHADER_MAX_CONSTANTS) {
191     return D3DERR_INVALIDCALL;
192   }
193   if (NULL == pConstantData) {
194     return D3DERR_INVALIDCALL;
195   }
196   memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstantI[Register], Vector4iCount * 4 * sizeof(FLOAT));
197   return D3D_OK;
198 }
199
200 HRESULT WINAPI IDirect3DDevice9Impl_SetPixelShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT Register, CONST BOOL* pConstantData, UINT BoolCount) {
201   IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
202   UINT i;
203
204   if (Register + BoolCount > D3D_VSHADER_MAX_CONSTANTS) {
205     ERR("(%p) : SetPixelShaderConstantB C[%u] invalid\n", This, Register);
206     return D3DERR_INVALIDCALL;
207   }
208   if (NULL == pConstantData) {
209     return D3DERR_INVALIDCALL;
210   }
211   if (BoolCount > 1) {
212     CONST BOOL* f = pConstantData;
213     TRACE("(%p) : SetPixelShaderConstantB C[%u..%u]=\n", This, Register, Register + BoolCount - 1);
214     for (i = 0; i < BoolCount; ++i) {
215       TRACE("{%u}\n", f[i]);
216     }
217   } else { 
218     CONST BOOL* f = pConstantData;
219     TRACE("(%p) : SetPixelShaderConstantB, C[%u]={%u}\n", This, Register, f[0]);
220   }
221   This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
222   for (i = 0; i < BoolCount; ++i) {
223     This->UpdateStateBlock->pixelShaderConstantB[Register] = pConstantData[i];
224   }
225   return D3D_OK;
226 }
227
228 HRESULT WINAPI IDirect3DDevice9Impl_GetPixelShaderConstantB(LPDIRECT3DDEVICE9 iface, UINT Register, BOOL* pConstantData, UINT BoolCount) {
229     IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface;
230     FIXME("(%p) : stub\n", This);
231     return D3D_OK;
232 }