2 * IWineD3DDevice implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
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.
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.
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
24 #include "wined3d_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
31 /**********************************************************
32 * Global variable / Constants follow
33 **********************************************************/
34 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
36 /**********************************************************
37 * Utility functions follow
38 **********************************************************/
39 /* Convert the D3DLIGHT properties into equivalent gl lights */
40 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
43 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
44 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
46 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
47 glMatrixMode(GL_MODELVIEW);
49 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
52 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
53 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
54 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
55 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
56 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
57 checkGLcall("glLightfv");
60 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
61 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
62 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
63 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
64 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
65 checkGLcall("glLightfv");
68 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
69 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
70 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
71 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
72 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
73 checkGLcall("glLightfv");
75 /* Attenuation - Are these right? guessing... */
76 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
77 checkGLcall("glLightf");
78 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
79 checkGLcall("glLightf");
81 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
82 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
83 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
84 checkGLcall("glLightf");
86 switch (lightInfo->OriginalParms.Type) {
89 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
90 checkGLcall("glLightfv");
91 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
92 checkGLcall("glLightf");
98 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
99 checkGLcall("glLightfv");
101 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
102 checkGLcall("glLightfv");
103 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
104 checkGLcall("glLightf");
105 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
106 checkGLcall("glLightf");
110 case D3DLIGHT_DIRECTIONAL:
112 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
113 checkGLcall("glLightfv");
114 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
115 checkGLcall("glLightf");
116 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
117 checkGLcall("glLightf");
121 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
124 /* Restore the modelview matrix */
128 /* Apply the current values to the specified texture stage */
129 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
130 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
133 BOOL changeTexture = TRUE;
135 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
136 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
141 /* Performance: For texture states where multiples effect the outcome, only bother
142 applying the last one as it will pick up all the other values */
143 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
144 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
145 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
146 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
147 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
148 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
152 /* Performance: If the texture states only impact settings for the texture unit
153 (compared to the texture object) then there is no need to reapply them. The
154 only time they need applying is the first time, since we cheat and put the
155 values into the stateblock without applying.
156 Per-texture unit: texture function (eg. combine), ops and args
158 texture generation settings
159 Note: Due to some special conditions there may be a need to do particular ones
160 of these, which is what the Flags allows */
162 case D3DTSS_TEXCOORDINDEX:
163 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
167 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
175 /* Performance: Only change to this texture if we have to */
177 /* Make appropriate texture active */
178 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
179 GLACTIVETEXTURE(Stage);
180 } else if (Stage > 0) {
181 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
183 changeTexture = FALSE;
186 /* Now apply the change */
187 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
191 /* Note the D3DRS value applies to all textures, but GL has one
192 * per texture, so apply it now ready to be used!
194 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[D3DRS_TEXTUREFACTOR], col);
195 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
196 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
198 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
201 /**********************************************************
202 * IWineD3DDevice implementation follows
203 **********************************************************/
204 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
205 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
206 *pParent = This->parent;
207 IUnknown_AddRef(This->parent);
211 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
212 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
215 IWineD3DVertexBufferImpl *object;
216 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
218 /* Allocate the storage for the device */
219 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DVertexBufferImpl));
220 object->lpVtbl = &IWineD3DVertexBuffer_Vtbl;
221 object->resource.wineD3DDevice= iface;
222 IWineD3DDevice_AddRef(iface);
223 object->resource.parent = parent;
224 object->resource.resourceType = D3DRTYPE_VERTEXBUFFER;
225 object->resource.ref = 1;
226 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
227 object->currentDesc.Usage = Usage;
228 object->currentDesc.Pool = Pool;
229 object->currentDesc.FVF = FVF;
230 object->currentDesc.Size = Size;
232 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
233 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
238 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
239 D3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
240 HANDLE *sharedHandle, IUnknown *parent) {
241 IWineD3DIndexBufferImpl *object;
242 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
244 /* Allocate the storage for the device */
245 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DIndexBufferImpl));
246 object->lpVtbl = &IWineD3DIndexBuffer_Vtbl;
247 object->resource.wineD3DDevice = iface;
248 object->resource.resourceType = D3DRTYPE_INDEXBUFFER;
249 object->resource.parent = parent;
250 IWineD3DDevice_AddRef(iface);
251 object->resource.ref = 1;
252 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
253 object->currentDesc.Usage = Usage;
254 object->currentDesc.Pool = Pool;
255 object->currentDesc.Format= Format;
256 object->currentDesc.Size = Length;
258 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
259 debug_d3dformat(Format), Pool, object, object->allocatedMemory);
260 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
265 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
268 IWineD3DStateBlockImpl *object;
270 /* Allocate Storage for the state block */
271 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
272 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
273 object->wineD3DDevice = iface;
274 IWineD3DDevice_AddRef(iface);
275 object->parent = parent;
277 object->blockType = Type;
278 *ppStateBlock = (IWineD3DStateBlock *)object;
280 /* Special case - Used during initialization to produce a placeholder stateblock
281 so other functions called can update a state block */
282 if (Type == (D3DSTATEBLOCKTYPE) 0) {
283 /* Don't bother increasing the reference count otherwise a device will never
284 be freed due to circular dependencies */
288 /* Otherwise, might as well set the whole state block to the appropriate values */
289 IWineD3DDevice_AddRef(iface);
290 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
291 FIXME("unfinished - needs to set up changed and set attributes\n");
298 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
299 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
301 /* Update the current statte block */
302 This->updateStateBlock->fvf = fvf;
303 This->updateStateBlock->changed.fvf = TRUE;
304 This->updateStateBlock->set.fvf = TRUE;
306 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
308 /* No difference if recording or not */
311 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
312 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
313 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
314 *pfvf = This->stateBlock->fvf;
319 * Get / Set Stream Source
321 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
323 IWineD3DVertexBuffer *oldSrc;
325 oldSrc = This->stateBlock->stream_source[StreamNumber];
326 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
328 This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
329 This->updateStateBlock->set.stream_source[StreamNumber] = TRUE;
330 This->updateStateBlock->stream_stride[StreamNumber] = Stride;
331 This->updateStateBlock->stream_source[StreamNumber] = pStreamData;
332 This->updateStateBlock->stream_offset[StreamNumber] = OffsetInBytes;
334 /* Handle recording of state blocks */
335 if (This->isRecordingState) {
336 TRACE("Recording... not performing anything\n");
340 /* Not recording... */
341 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
342 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
347 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
348 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
350 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
351 *pStream = This->stateBlock->stream_source[StreamNumber];
352 *pStride = This->stateBlock->stream_stride[StreamNumber];
353 *pOffset = This->stateBlock->stream_offset[StreamNumber];
354 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
359 * Get / Set & Multipy Transform
361 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
364 /* Most of this routine, comments included copied from ddraw tree initially: */
365 TRACE("(%p) : Transform State=%d\n", This, d3dts);
367 /* Handle recording of state blocks */
368 if (This->isRecordingState) {
369 TRACE("Recording... not performing anything\n");
370 This->updateStateBlock->changed.transform[d3dts] = TRUE;
371 This->updateStateBlock->set.transform[d3dts] = TRUE;
372 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
377 * If the new matrix is the same as the current one,
378 * we cut off any further processing. this seems to be a reasonable
379 * optimization because as was noticed, some apps (warcraft3 for example)
380 * tend towards setting the same matrix repeatedly for some reason.
382 * From here on we assume that the new matrix is different, wherever it matters.
384 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
385 TRACE("The app is setting the same matrix over again\n");
388 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
392 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
393 where ViewMat = Camera space, WorldMat = world space.
395 In OpenGL, camera and world space is combined into GL_MODELVIEW
396 matrix. The Projection matrix stay projection matrix.
399 /* Capture the times we can just ignore the change for now */
400 if (d3dts == D3DTS_WORLDMATRIX(0)) {
401 This->modelview_valid = FALSE;
404 } else if (d3dts == D3DTS_PROJECTION) {
405 This->proj_valid = FALSE;
408 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
409 /* Indexed Vertex Blending Matrices 256 -> 511 */
410 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
411 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
415 /* Now we really are going to have to change a matrix */
418 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
419 if (d3dts < GL_LIMITS(textures)) {
420 int tex = d3dts - D3DTS_TEXTURE0;
421 GLACTIVETEXTURE(tex);
422 set_texture_matrix((float *)lpmatrix,
423 This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
426 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
429 /* If we are changing the View matrix, reset the light and clipping planes to the new view
430 * NOTE: We have to reset the positions even if the light/plane is not currently
431 * enabled, since the call to enable it will not reset the position.
432 * NOTE2: Apparently texture transforms do NOT need reapplying
435 PLIGHTINFOEL *lightChain = NULL;
436 This->modelview_valid = FALSE;
437 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
439 glMatrixMode(GL_MODELVIEW);
440 checkGLcall("glMatrixMode(GL_MODELVIEW)");
442 glLoadMatrixf((float *)lpmatrix);
443 checkGLcall("glLoadMatrixf(...)");
446 lightChain = This->stateBlock->lights;
447 while (lightChain && lightChain->glIndex != -1) {
448 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
449 checkGLcall("glLightfv posn");
450 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
451 checkGLcall("glLightfv dirn");
452 lightChain = lightChain->next;
455 /* Reset Clipping Planes if clipping is enabled */
456 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
457 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
458 checkGLcall("glClipPlane");
462 } else { /* What was requested!?? */
463 WARN("invalid matrix specified: %i\n", d3dts);
466 /* Release lock, all done */
471 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
472 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
473 TRACE("(%p) : for Transform State %d\n", This, State);
474 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
478 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
479 D3DMATRIX *mat = NULL;
482 /* Note: Using 'updateStateBlock' rather then 'stateblock' in the code below
483 means it will be recorded in a state block change, but iworks regardless of recording being on.
484 If this is found to be wrong, change to StateBlock. */
485 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
486 TRACE("(%p) : For state %u\n", This, State);
488 if (State < HIGHEST_TRANSFORMSTATE)
490 mat = &This->updateStateBlock->transforms[State];
492 FIXME("Unhandled transform state!!\n");
495 /* Copied from ddraw code: */
496 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
497 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
498 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
499 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
501 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
502 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
503 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
504 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
506 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
507 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
508 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
509 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
511 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
512 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
513 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
514 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
516 /* Apply change via set transform - will reapply to eg. lights this way */
517 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
523 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
525 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
526 you can reference any indexes you want as long as that number max are enabled are any
527 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
528 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
529 but when recording, just build a chain pretty much of commands to be replayed. */
531 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
533 PLIGHTINFOEL *object, *temp;
535 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
536 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
538 /* If recording state block, just add to end of lights chain */
539 if (This->isRecordingState) {
540 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
541 if (NULL == object) {
542 return D3DERR_OUTOFVIDEOMEMORY;
544 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
545 object->OriginalIndex = Index;
546 object->glIndex = -1;
547 object->changed = TRUE;
549 /* Add to the END of the chain of lights changes to be replayed */
550 if (This->updateStateBlock->lights == NULL) {
551 This->updateStateBlock->lights = object;
553 temp = This->updateStateBlock->lights;
554 while (temp->next != NULL) temp=temp->next;
557 TRACE("Recording... not performing anything more\n");
561 /* Ok, not recording any longer so do real work */
562 object = This->stateBlock->lights;
563 while (object != NULL && object->OriginalIndex != Index) object = object->next;
565 /* If we didn't find it in the list of lights, time to add it */
566 if (object == NULL) {
567 PLIGHTINFOEL *insertAt,*prevPos;
569 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
570 if (NULL == object) {
571 return D3DERR_OUTOFVIDEOMEMORY;
573 object->OriginalIndex = Index;
574 object->glIndex = -1;
576 /* Add it to the front of list with the idea that lights will be changed as needed
577 BUT after any lights currently assigned GL indexes */
578 insertAt = This->stateBlock->lights;
580 while (insertAt != NULL && insertAt->glIndex != -1) {
582 insertAt = insertAt->next;
585 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
586 This->stateBlock->lights = object;
587 } else if (insertAt == NULL) { /* End of list */
588 prevPos->next = object;
589 object->prev = prevPos;
590 } else { /* Middle of chain */
591 if (prevPos == NULL) {
592 This->stateBlock->lights = object;
594 prevPos->next = object;
596 object->prev = prevPos;
597 object->next = insertAt;
598 insertAt->prev = object;
602 /* Initialze the object */
603 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
604 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
605 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
606 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
607 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
608 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
609 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
611 /* Save away the information */
612 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
614 switch (pLight->Type) {
617 object->lightPosn[0] = pLight->Position.x;
618 object->lightPosn[1] = pLight->Position.y;
619 object->lightPosn[2] = pLight->Position.z;
620 object->lightPosn[3] = 1.0f;
621 object->cutoff = 180.0f;
625 case D3DLIGHT_DIRECTIONAL:
627 object->lightPosn[0] = -pLight->Direction.x;
628 object->lightPosn[1] = -pLight->Direction.y;
629 object->lightPosn[2] = -pLight->Direction.z;
630 object->lightPosn[3] = 0.0;
631 object->exponent = 0.0f;
632 object->cutoff = 180.0f;
637 object->lightPosn[0] = pLight->Position.x;
638 object->lightPosn[1] = pLight->Position.y;
639 object->lightPosn[2] = pLight->Position.z;
640 object->lightPosn[3] = 1.0;
643 object->lightDirn[0] = pLight->Direction.x;
644 object->lightDirn[1] = pLight->Direction.y;
645 object->lightDirn[2] = pLight->Direction.z;
646 object->lightDirn[3] = 1.0;
649 * opengl-ish and d3d-ish spot lights use too different models for the
650 * light "intensity" as a function of the angle towards the main light direction,
651 * so we only can approximate very roughly.
652 * however spot lights are rather rarely used in games (if ever used at all).
653 * furthermore if still used, probably nobody pays attention to such details.
655 if (pLight->Falloff == 0) {
658 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
660 if (rho < 0.0001) rho = 0.0001f;
661 object->exponent = -0.3/log(cos(rho/2));
662 object->cutoff = pLight->Phi*90/M_PI;
668 FIXME("Unrecognized light type %d\n", pLight->Type);
671 /* Update the live definitions if the light is currently assigned a glIndex */
672 if (object->glIndex != -1) {
673 setup_light(iface, object->glIndex, object);
678 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
679 PLIGHTINFOEL *lightInfo = NULL;
680 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
681 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
683 /* Locate the light in the live lights */
684 lightInfo = This->stateBlock->lights;
685 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
687 if (lightInfo == NULL) {
688 TRACE("Light information requested but light not defined\n");
689 return D3DERR_INVALIDCALL;
692 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
697 * Get / Set Light Enable
698 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
700 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
701 PLIGHTINFOEL *lightInfo = NULL;
702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
703 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
705 /* If recording state block, just add to end of lights chain with changedEnable set to true */
706 if (This->isRecordingState) {
707 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
708 if (NULL == lightInfo) {
709 return D3DERR_OUTOFVIDEOMEMORY;
711 lightInfo->OriginalIndex = Index;
712 lightInfo->glIndex = -1;
713 lightInfo->enabledChanged = TRUE;
715 /* Add to the END of the chain of lights changes to be replayed */
716 if (This->updateStateBlock->lights == NULL) {
717 This->updateStateBlock->lights = lightInfo;
719 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
720 while (temp->next != NULL) temp=temp->next;
721 temp->next = lightInfo;
723 TRACE("Recording... not performing anything more\n");
727 /* Not recording... So, locate the light in the live lights */
728 lightInfo = This->stateBlock->lights;
729 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
731 /* Special case - enabling an undefined light creates one with a strict set of parms! */
732 if (lightInfo == NULL) {
733 D3DLIGHT9 lightParms;
734 /* Warning - untested code :-) Prob safe to change fixme to a trace but
735 wait until someone confirms it seems to work! */
736 TRACE("Light enabled requested but light not defined, so defining one!\n");
737 lightParms.Type = D3DLIGHT_DIRECTIONAL;
738 lightParms.Diffuse.r = 1.0;
739 lightParms.Diffuse.g = 1.0;
740 lightParms.Diffuse.b = 1.0;
741 lightParms.Diffuse.a = 0.0;
742 lightParms.Specular.r = 0.0;
743 lightParms.Specular.g = 0.0;
744 lightParms.Specular.b = 0.0;
745 lightParms.Specular.a = 0.0;
746 lightParms.Ambient.r = 0.0;
747 lightParms.Ambient.g = 0.0;
748 lightParms.Ambient.b = 0.0;
749 lightParms.Ambient.a = 0.0;
750 lightParms.Position.x = 0.0;
751 lightParms.Position.y = 0.0;
752 lightParms.Position.z = 0.0;
753 lightParms.Direction.x = 0.0;
754 lightParms.Direction.y = 0.0;
755 lightParms.Direction.z = 1.0;
756 lightParms.Range = 0.0;
757 lightParms.Falloff = 0.0;
758 lightParms.Attenuation0 = 0.0;
759 lightParms.Attenuation1 = 0.0;
760 lightParms.Attenuation2 = 0.0;
761 lightParms.Theta = 0.0;
762 lightParms.Phi = 0.0;
763 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
765 /* Search for it again! Should be fairly quick as near head of list */
766 lightInfo = This->stateBlock->lights;
767 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
768 if (lightInfo == NULL) {
769 FIXME("Adding default lights has failed dismally\n");
770 return D3DERR_INVALIDCALL;
774 /* OK, we now have a light... */
775 if (Enable == FALSE) {
777 /* If we are disabling it, check it was enabled, and
778 still only do something if it has assigned a glIndex (which it should have!) */
779 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
780 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
782 glDisable(GL_LIGHT0 + lightInfo->glIndex);
783 checkGLcall("glDisable GL_LIGHT0+Index");
786 TRACE("Nothing to do as light was not enabled\n");
788 lightInfo->lightEnabled = FALSE;
791 /* We are enabling it. If it is enabled, its really simple */
792 if (lightInfo->lightEnabled) {
794 TRACE("Nothing to do as light was enabled\n");
796 /* If it already has a glIndex, its still simple */
797 } else if (lightInfo->glIndex != -1) {
798 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
799 lightInfo->lightEnabled = TRUE;
801 glEnable(GL_LIGHT0 + lightInfo->glIndex);
802 checkGLcall("glEnable GL_LIGHT0+Index already setup");
805 /* Otherwise got to find space - lights are ordered gl indexes first */
807 PLIGHTINFOEL *bsf = NULL;
808 PLIGHTINFOEL *pos = This->stateBlock->lights;
809 PLIGHTINFOEL *prev = NULL;
813 /* Try to minimize changes as much as possible */
814 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
816 /* Try to remember which index can be replaced if necessary */
817 if (bsf==NULL && pos->lightEnabled == FALSE) {
818 /* Found a light we can replace, save as best replacement */
822 /* Step to next space */
828 /* If we have too many active lights, fail the call */
829 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
830 FIXME("Program requests too many concurrent lights\n");
831 return D3DERR_INVALIDCALL;
833 /* If we have allocated all lights, but not all are enabled,
834 reuse one which is not enabled */
835 } else if (Index == This->maxConcurrentLights) {
836 /* use bsf - Simply swap the new light and the BSF one */
837 PLIGHTINFOEL *bsfNext = bsf->next;
838 PLIGHTINFOEL *bsfPrev = bsf->prev;
841 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
842 if (bsf->prev != NULL) {
843 bsf->prev->next = lightInfo;
845 This->stateBlock->lights = lightInfo;
848 /* If not side by side, lots of chains to update */
849 if (bsf->next != lightInfo) {
850 lightInfo->prev->next = bsf;
851 bsf->next->prev = lightInfo;
852 bsf->next = lightInfo->next;
853 bsf->prev = lightInfo->prev;
854 lightInfo->next = bsfNext;
855 lightInfo->prev = bsfPrev;
859 bsf->prev = lightInfo;
860 bsf->next = lightInfo->next;
861 lightInfo->next = bsf;
862 lightInfo->prev = bsfPrev;
867 glIndex = bsf->glIndex;
869 lightInfo->glIndex = glIndex;
870 lightInfo->lightEnabled = TRUE;
872 /* Finally set up the light in gl itself */
873 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
875 setup_light(iface, glIndex, lightInfo);
876 glEnable(GL_LIGHT0 + glIndex);
877 checkGLcall("glEnable GL_LIGHT0 new setup");
880 /* If we reached the end of the allocated lights, with space in the
881 gl lights, setup a new light */
882 } else if (pos->glIndex == -1) {
884 /* We reached the end of the allocated gl lights, so already
885 know the index of the next one! */
887 lightInfo->glIndex = glIndex;
888 lightInfo->lightEnabled = TRUE;
890 /* In an ideal world, its already in the right place */
891 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
892 /* No need to move it */
894 /* Remove this light from the list */
895 lightInfo->prev->next = lightInfo->next;
896 if (lightInfo->next != NULL) {
897 lightInfo->next->prev = lightInfo->prev;
900 /* Add in at appropriate place (inbetween prev and pos) */
901 lightInfo->prev = prev;
902 lightInfo->next = pos;
904 This->stateBlock->lights = lightInfo;
906 prev->next = lightInfo;
909 pos->prev = lightInfo;
913 /* Finally set up the light in gl itself */
914 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
916 setup_light(iface, glIndex, lightInfo);
917 glEnable(GL_LIGHT0 + glIndex);
918 checkGLcall("glEnable GL_LIGHT0 new setup");
927 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
929 PLIGHTINFOEL *lightInfo = NULL;
930 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
931 TRACE("(%p) : for idx(%ld)\n", This, Index);
933 /* Locate the light in the live lights */
934 lightInfo = This->stateBlock->lights;
935 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
937 if (lightInfo == NULL) {
938 TRACE("Light enabled state requested but light not defined\n");
939 return D3DERR_INVALIDCALL;
941 *pEnable = lightInfo->lightEnabled;
946 * Get / Set Clip Planes
948 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
949 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
950 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
953 if (Index >= GL_LIMITS(clipplanes)) {
954 TRACE("Application has requested clipplane this device doesn't support\n");
955 return D3DERR_INVALIDCALL;
958 This->updateStateBlock->changed.clipplane[Index] = TRUE;
959 This->updateStateBlock->set.clipplane[Index] = TRUE;
960 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
961 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
962 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
963 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
965 /* Handle recording of state blocks */
966 if (This->isRecordingState) {
967 TRACE("Recording... not performing anything\n");
975 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
976 glMatrixMode(GL_MODELVIEW);
978 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
980 TRACE("Clipplane [%f,%f,%f,%f]\n",
981 This->updateStateBlock->clipplane[Index][0],
982 This->updateStateBlock->clipplane[Index][1],
983 This->updateStateBlock->clipplane[Index][2],
984 This->updateStateBlock->clipplane[Index][3]);
985 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
986 checkGLcall("glClipPlane");
994 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
996 TRACE("(%p) : for idx %ld\n", This, Index);
999 if (Index >= GL_LIMITS(clipplanes)) {
1000 TRACE("Application has requested clipplane this device doesn't support\n");
1001 return D3DERR_INVALIDCALL;
1004 pPlane[0] = This->stateBlock->clipplane[Index][0];
1005 pPlane[1] = This->stateBlock->clipplane[Index][1];
1006 pPlane[2] = This->stateBlock->clipplane[Index][2];
1007 pPlane[3] = This->stateBlock->clipplane[Index][3];
1012 * Get / Set Clip Plane Status
1013 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
1015 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
1016 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1017 FIXME("(%p) : stub\n", This);
1018 if (NULL == pClipStatus) {
1019 return D3DERR_INVALIDCALL;
1021 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
1022 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
1026 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
1027 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1028 FIXME("(%p) : stub\n", This);
1029 if (NULL == pClipStatus) {
1030 return D3DERR_INVALIDCALL;
1032 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
1033 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
1038 * Get / Set Material
1039 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
1041 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
1042 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1044 This->updateStateBlock->changed.material = TRUE;
1045 This->updateStateBlock->set.material = TRUE;
1046 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
1048 /* Handle recording of state blocks */
1049 if (This->isRecordingState) {
1050 TRACE("Recording... not performing anything\n");
1055 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1056 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1057 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1058 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1059 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1061 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
1062 checkGLcall("glMaterialfv");
1063 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
1064 checkGLcall("glMaterialfv");
1066 /* Only change material color if specular is enabled, otherwise it is set to black */
1067 if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
1068 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1069 checkGLcall("glMaterialfv");
1071 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1072 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1073 checkGLcall("glMaterialfv");
1075 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
1076 checkGLcall("glMaterialfv");
1077 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
1078 checkGLcall("glMaterialf");
1084 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
1085 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1086 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
1087 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1088 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1089 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1090 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1091 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1098 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
1099 UINT BaseVertexIndex) {
1100 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1101 IWineD3DIndexBuffer *oldIdxs;
1103 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
1104 oldIdxs = This->updateStateBlock->pIndexData;
1106 This->updateStateBlock->changed.indices = TRUE;
1107 This->updateStateBlock->set.indices = TRUE;
1108 This->updateStateBlock->pIndexData = pIndexData;
1109 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
1111 /* Handle recording of state blocks */
1112 if (This->isRecordingState) {
1113 TRACE("Recording... not performing anything\n");
1117 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
1118 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
1122 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
1123 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1125 *ppIndexData = This->stateBlock->pIndexData;
1127 /* up ref count on ppindexdata */
1128 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
1129 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
1135 * Get / Set Viewports
1137 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
1138 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1140 TRACE("(%p)\n", This);
1141 This->updateStateBlock->changed.viewport = TRUE;
1142 This->updateStateBlock->set.viewport = TRUE;
1143 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
1145 /* Handle recording of state blocks */
1146 if (This->isRecordingState) {
1147 TRACE("Recording... not performing anything\n");
1153 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1154 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1156 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1157 checkGLcall("glDepthRange");
1160 /* Note: GL requires lower left, DirectX supplies upper left */
1161 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1162 pViewport->Width, pViewport->Height);
1163 checkGLcall("glViewport");
1172 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
1173 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1174 TRACE("(%p)\n", This);
1175 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
1180 * Get / Set Render States
1181 * TODO: Verify against dx9 definitions
1183 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
1185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1186 DWORD OldValue = This->stateBlock->renderState[State];
1188 /* Simple way of refering to either a DWORD or a 4 byte float */
1194 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1195 This->updateStateBlock->changed.renderState[State] = TRUE;
1196 This->updateStateBlock->set.renderState[State] = TRUE;
1197 This->updateStateBlock->renderState[State] = Value;
1199 /* Handle recording of state blocks */
1200 if (This->isRecordingState) {
1201 TRACE("Recording... not performing anything\n");
1208 case D3DRS_FILLMODE :
1209 switch ((D3DFILLMODE) Value) {
1210 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1211 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1212 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1214 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
1216 checkGLcall("glPolygonMode (fillmode)");
1219 case D3DRS_LIGHTING :
1221 glEnable(GL_LIGHTING);
1222 checkGLcall("glEnable GL_LIGHTING");
1224 glDisable(GL_LIGHTING);
1225 checkGLcall("glDisable GL_LIGHTING");
1229 case D3DRS_ZENABLE :
1230 switch ((D3DZBUFFERTYPE) Value) {
1232 glDisable(GL_DEPTH_TEST);
1233 checkGLcall("glDisable GL_DEPTH_TEST");
1236 glEnable(GL_DEPTH_TEST);
1237 checkGLcall("glEnable GL_DEPTH_TEST");
1240 glEnable(GL_DEPTH_TEST);
1241 checkGLcall("glEnable GL_DEPTH_TEST");
1242 FIXME("W buffer is not well handled\n");
1245 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1249 case D3DRS_CULLMODE :
1251 /* If we are culling "back faces with clockwise vertices" then
1252 set front faces to be counter clockwise and enable culling
1254 switch ((D3DCULL) Value) {
1256 glDisable(GL_CULL_FACE);
1257 checkGLcall("glDisable GL_CULL_FACE");
1260 glEnable(GL_CULL_FACE);
1261 checkGLcall("glEnable GL_CULL_FACE");
1262 if (This->renderUpsideDown) {
1264 checkGLcall("glFrontFace GL_CW");
1266 glFrontFace(GL_CCW);
1267 checkGLcall("glFrontFace GL_CCW");
1269 glCullFace(GL_BACK);
1272 glEnable(GL_CULL_FACE);
1273 checkGLcall("glEnable GL_CULL_FACE");
1274 if (This->renderUpsideDown) {
1275 glFrontFace(GL_CCW);
1276 checkGLcall("glFrontFace GL_CCW");
1279 checkGLcall("glFrontFace GL_CW");
1281 glCullFace(GL_BACK);
1284 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1288 case D3DRS_SHADEMODE :
1289 switch ((D3DSHADEMODE) Value) {
1291 glShadeModel(GL_FLAT);
1292 checkGLcall("glShadeModel");
1294 case D3DSHADE_GOURAUD:
1295 glShadeModel(GL_SMOOTH);
1296 checkGLcall("glShadeModel");
1298 case D3DSHADE_PHONG:
1299 FIXME("D3DSHADE_PHONG isn't supported?\n");
1302 return D3DERR_INVALIDCALL;
1304 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1308 case D3DRS_DITHERENABLE :
1310 glEnable(GL_DITHER);
1311 checkGLcall("glEnable GL_DITHER");
1313 glDisable(GL_DITHER);
1314 checkGLcall("glDisable GL_DITHER");
1318 case D3DRS_ZWRITEENABLE :
1321 checkGLcall("glDepthMask");
1324 checkGLcall("glDepthMask");
1330 int glParm = GL_LESS;
1332 switch ((D3DCMPFUNC) Value) {
1333 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1334 case D3DCMP_LESS: glParm=GL_LESS; break;
1335 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1336 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1337 case D3DCMP_GREATER: glParm=GL_GREATER; break;
1338 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
1339 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
1340 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
1342 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1344 glDepthFunc(glParm);
1345 checkGLcall("glDepthFunc");
1349 case D3DRS_AMBIENT :
1352 D3DCOLORTOGLFLOAT4(Value, col);
1353 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1354 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1355 checkGLcall("glLightModel for MODEL_AMBIENT");
1360 case D3DRS_ALPHABLENDENABLE :
1363 checkGLcall("glEnable GL_BLEND");
1365 glDisable(GL_BLEND);
1366 checkGLcall("glDisable GL_BLEND");
1370 case D3DRS_SRCBLEND :
1371 case D3DRS_DESTBLEND :
1373 int newVal = GL_ZERO;
1375 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
1376 case D3DBLEND_ONE : newVal = GL_ONE; break;
1377 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
1378 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
1379 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
1380 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
1381 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
1382 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
1383 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
1384 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
1385 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
1387 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
1388 This->srcBlend = newVal;
1389 This->dstBlend = newVal;
1392 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
1393 This->srcBlend = newVal;
1394 This->dstBlend = newVal;
1397 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
1400 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
1401 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
1402 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
1403 glBlendFunc(This->srcBlend, This->dstBlend);
1405 checkGLcall("glBlendFunc");
1409 case D3DRS_ALPHATESTENABLE :
1411 glEnable(GL_ALPHA_TEST);
1412 checkGLcall("glEnable GL_ALPHA_TEST");
1414 glDisable(GL_ALPHA_TEST);
1415 checkGLcall("glDisable GL_ALPHA_TEST");
1419 case D3DRS_ALPHAFUNC :
1421 int glParm = GL_LESS;
1422 float ref = ((float) This->stateBlock->renderState[D3DRS_ALPHAREF]) / 255.0f;
1424 switch ((D3DCMPFUNC) Value) {
1425 case D3DCMP_NEVER: glParm = GL_NEVER; break;
1426 case D3DCMP_LESS: glParm = GL_LESS; break;
1427 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
1428 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
1429 case D3DCMP_GREATER: glParm = GL_GREATER; break;
1430 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
1431 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
1432 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
1434 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1436 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1437 glAlphaFunc(glParm, ref);
1438 This->alphafunc = glParm;
1439 checkGLcall("glAlphaFunc");
1443 case D3DRS_ALPHAREF :
1445 int glParm = This->alphafunc;
1448 ref = ((float) Value) / 255.0f;
1449 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1450 glAlphaFunc(glParm, ref);
1451 checkGLcall("glAlphaFunc");
1455 case D3DRS_CLIPPLANEENABLE :
1456 case D3DRS_CLIPPING :
1458 /* Ensure we only do the changed clip planes */
1459 DWORD enable = 0xFFFFFFFF;
1460 DWORD disable = 0x00000000;
1462 /* If enabling / disabling all */
1463 if (State == D3DRS_CLIPPING) {
1465 enable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1468 disable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1472 enable = Value & ~OldValue;
1473 disable = ~Value & OldValue;
1476 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
1477 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
1478 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
1479 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
1480 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
1481 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
1483 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
1484 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
1485 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
1486 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
1487 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
1488 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
1490 /** update clipping status */
1492 This->stateBlock->clip_status.ClipUnion = 0;
1493 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
1495 This->stateBlock->clip_status.ClipUnion = 0;
1496 This->stateBlock->clip_status.ClipIntersection = 0;
1501 case D3DRS_BLENDOP :
1503 int glParm = GL_FUNC_ADD;
1505 switch ((D3DBLENDOP) Value) {
1506 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
1507 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
1508 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
1509 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
1510 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
1512 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
1514 TRACE("glBlendEquation(%x)\n", glParm);
1515 glBlendEquation(glParm);
1516 checkGLcall("glBlendEquation");
1520 case D3DRS_TEXTUREFACTOR :
1524 /* Note the texture color applies to all textures whereas
1525 GL_TEXTURE_ENV_COLOR applies to active only */
1527 D3DCOLORTOGLFLOAT4(Value, col);
1528 /* Set the default alpha blend color */
1529 glBlendColor(col[0], col[1], col[2], col[3]);
1530 checkGLcall("glBlendColor");
1532 /* And now the default texture color as well */
1533 for (i = 0; i < GL_LIMITS(textures); i++) {
1535 /* Note the D3DRS value applies to all textures, but GL has one
1536 per texture, so apply it now ready to be used! */
1537 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1540 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1543 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1544 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1549 case D3DRS_SPECULARENABLE :
1551 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
1552 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
1553 specular color. This is wrong:
1554 Separate specular color means the specular colour is maintained separately, whereas
1555 single color means it is merged in. However in both cases they are being used to
1557 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
1558 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
1562 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1563 checkGLcall("glMaterialfv");
1564 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1565 glEnable(GL_COLOR_SUM_EXT);
1567 TRACE("Specular colors cannot be enabled in this version of opengl\n");
1569 checkGLcall("glEnable(GL_COLOR_SUM)");
1571 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1573 /* for the case of enabled lighting: */
1574 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1575 checkGLcall("glMaterialfv");
1577 /* for the case of disabled lighting: */
1578 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1579 glDisable(GL_COLOR_SUM_EXT);
1581 TRACE("Specular colors cannot be disabled in this version of opengl\n");
1583 checkGLcall("glDisable(GL_COLOR_SUM)");
1588 case D3DRS_STENCILENABLE :
1590 glEnable(GL_STENCIL_TEST);
1591 checkGLcall("glEnable GL_STENCIL_TEST");
1593 glDisable(GL_STENCIL_TEST);
1594 checkGLcall("glDisable GL_STENCIL_TEST");
1598 case D3DRS_STENCILFUNC :
1600 int glParm = GL_ALWAYS;
1601 int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
1602 GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
1604 switch ((D3DCMPFUNC) Value) {
1605 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1606 case D3DCMP_LESS: glParm=GL_LESS; break;
1607 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1608 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1609 case D3DCMP_GREATER: glParm=GL_GREATER; break;
1610 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
1611 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
1612 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
1614 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1616 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
1617 This->stencilfunc = glParm;
1618 glStencilFunc(glParm, ref, mask);
1619 checkGLcall("glStencilFunc");
1623 case D3DRS_STENCILREF :
1625 int glParm = This->stencilfunc;
1627 GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
1630 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
1631 glStencilFunc(glParm, ref, mask);
1632 checkGLcall("glStencilFunc");
1636 case D3DRS_STENCILMASK :
1638 int glParm = This->stencilfunc;
1639 int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
1640 GLuint mask = Value;
1642 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
1643 glStencilFunc(glParm, ref, mask);
1644 checkGLcall("glStencilFunc");
1648 case D3DRS_STENCILFAIL :
1654 fail = StencilOp(Value);
1655 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
1656 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
1657 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
1658 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
1660 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
1661 glStencilOp(fail, zfail, zpass);
1662 checkGLcall("glStencilOp(fail, zfail, zpass);");
1665 case D3DRS_STENCILZFAIL :
1671 glGetIntegerv(GL_STENCIL_FAIL, &fail);
1672 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
1673 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
1674 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
1675 zfail = StencilOp(Value);
1677 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
1678 glStencilOp(fail, zfail, zpass);
1679 checkGLcall("glStencilOp(fail, zfail, zpass);");
1682 case D3DRS_STENCILPASS :
1688 glGetIntegerv(GL_STENCIL_FAIL, &fail);
1689 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
1690 zpass = StencilOp(Value);
1691 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
1692 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
1694 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
1695 glStencilOp(fail, zfail, zpass);
1696 checkGLcall("glStencilOp(fail, zfail, zpass);");
1700 case D3DRS_STENCILWRITEMASK :
1702 glStencilMask(Value);
1703 TRACE("glStencilMask(%lu)\n", Value);
1704 checkGLcall("glStencilMask");
1708 case D3DRS_FOGENABLE :
1710 if (Value/* && This->stateBlock->renderState[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
1712 checkGLcall("glEnable GL_FOG");
1715 checkGLcall("glDisable GL_FOG");
1720 case D3DRS_RANGEFOGENABLE :
1723 TRACE("Enabled RANGEFOG");
1725 TRACE("Disabled RANGEFOG");
1730 case D3DRS_FOGCOLOR :
1733 D3DCOLORTOGLFLOAT4(Value, col);
1734 /* Set the default alpha blend color */
1735 glFogfv(GL_FOG_COLOR, &col[0]);
1736 checkGLcall("glFog GL_FOG_COLOR");
1740 case D3DRS_FOGTABLEMODE :
1742 glHint(GL_FOG_HINT, GL_NICEST);
1744 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
1745 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
1746 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
1747 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
1749 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
1751 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1752 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1757 case D3DRS_FOGVERTEXMODE :
1759 glHint(GL_FOG_HINT, GL_FASTEST);
1761 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
1762 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
1763 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
1764 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
1766 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
1768 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1769 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
1774 case D3DRS_FOGSTART :
1777 glFogfv(GL_FOG_START, &tmpvalue.f);
1778 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
1779 TRACE("Fog Start == %f\n", tmpvalue.f);
1786 glFogfv(GL_FOG_END, &tmpvalue.f);
1787 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
1788 TRACE("Fog End == %f\n", tmpvalue.f);
1792 case D3DRS_FOGDENSITY :
1795 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1796 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1800 case D3DRS_VERTEXBLEND :
1802 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
1803 TRACE("Vertex Blending state to %ld\n", Value);
1807 case D3DRS_TWEENFACTOR :
1810 This->updateStateBlock->tween_factor = tmpvalue.f;
1811 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
1815 case D3DRS_INDEXEDVERTEXBLENDENABLE :
1817 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
1821 case D3DRS_COLORVERTEX :
1822 case D3DRS_DIFFUSEMATERIALSOURCE :
1823 case D3DRS_SPECULARMATERIALSOURCE :
1824 case D3DRS_AMBIENTMATERIALSOURCE :
1825 case D3DRS_EMISSIVEMATERIALSOURCE :
1827 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
1829 if (This->stateBlock->renderState[D3DRS_COLORVERTEX]) {
1830 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
1831 This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE],
1832 This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE],
1833 This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE],
1834 This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE]);
1836 if (This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
1837 if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
1838 Parm = GL_AMBIENT_AND_DIFFUSE;
1842 } else if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
1844 } else if (This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
1846 } else if (This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
1853 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
1855 This->tracking_color = NEEDS_TRACKING;
1856 This->tracking_parm = Parm;
1860 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
1865 case D3DRS_LINEPATTERN :
1871 tmppattern.d = Value;
1873 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1875 if (tmppattern.lp.wRepeatFactor) {
1876 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1877 checkGLcall("glLineStipple(repeat, linepattern)");
1878 glEnable(GL_LINE_STIPPLE);
1879 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1881 glDisable(GL_LINE_STIPPLE);
1882 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1891 TRACE("ZBias value %f\n", tmpvalue.f);
1892 glPolygonOffset(0, -tmpvalue.f);
1893 checkGLcall("glPolygonOffset(0, -Value)");
1894 glEnable(GL_POLYGON_OFFSET_FILL);
1895 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1896 glEnable(GL_POLYGON_OFFSET_LINE);
1897 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1898 glEnable(GL_POLYGON_OFFSET_POINT);
1899 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1901 glDisable(GL_POLYGON_OFFSET_FILL);
1902 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1903 glDisable(GL_POLYGON_OFFSET_LINE);
1904 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1905 glDisable(GL_POLYGON_OFFSET_POINT);
1906 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1911 case D3DRS_NORMALIZENORMALS :
1913 glEnable(GL_NORMALIZE);
1914 checkGLcall("glEnable(GL_NORMALIZE);");
1916 glDisable(GL_NORMALIZE);
1917 checkGLcall("glDisable(GL_NORMALIZE);");
1921 case D3DRS_POINTSIZE :
1923 TRACE("Set point size to %f\n", tmpvalue.f);
1924 glPointSize(tmpvalue.f);
1925 checkGLcall("glPointSize(...);");
1928 case D3DRS_POINTSIZE_MIN :
1929 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1931 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1932 checkGLcall("glPointParameterfEXT(...);");
1934 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
1938 case D3DRS_POINTSIZE_MAX :
1939 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1941 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1942 checkGLcall("glPointParameterfEXT(...);");
1944 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
1948 case D3DRS_POINTSCALE_A :
1949 case D3DRS_POINTSCALE_B :
1950 case D3DRS_POINTSCALE_C :
1951 case D3DRS_POINTSCALEENABLE :
1953 /* If enabled, supply the parameters, otherwise fall back to defaults */
1954 if (This->stateBlock->renderState[D3DRS_POINTSCALEENABLE]) {
1955 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1956 att[0] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_A]);
1957 att[1] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_B]);
1958 att[2] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_C]);
1960 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1961 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1962 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
1964 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
1967 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1968 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1969 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1970 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
1972 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
1978 case D3DRS_COLORWRITEENABLE :
1980 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1981 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
1982 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1983 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1984 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1985 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1986 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1987 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1988 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1989 checkGLcall("glColorMask(...)");
1993 case D3DRS_LOCALVIEWER :
1995 GLint state = (Value) ? 1 : 0;
1996 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
1997 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2001 case D3DRS_LASTPIXEL :
2004 TRACE("Last Pixel Drawing Enabled\n");
2006 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
2011 case D3DRS_SOFTWAREVERTEXPROCESSING :
2014 TRACE("Software Processing Enabled\n");
2016 TRACE("Software Processing Disabled\n");
2021 /** not supported */
2022 case D3DRS_ZVISIBLE :
2025 return D3DERR_INVALIDCALL;
2028 /* Unhandled yet...! */
2029 case D3DRS_EDGEANTIALIAS :
2038 case D3DRS_POINTSPRITEENABLE :
2039 case D3DRS_MULTISAMPLEANTIALIAS :
2040 case D3DRS_MULTISAMPLEMASK :
2041 case D3DRS_PATCHEDGESTYLE :
2042 case D3DRS_PATCHSEGMENTS :
2043 case D3DRS_DEBUGMONITORTOKEN :
2044 case D3DRS_POSITIONORDER :
2045 case D3DRS_NORMALORDER :
2046 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2047 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2050 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2058 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
2059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2060 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
2061 *pValue = This->stateBlock->renderState[State];
2067 * Get / Set Texture Stage States
2068 * TODO: Verify against dx9 definitions
2070 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2077 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2079 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2081 /* Reject invalid texture units */
2082 if (Stage >= GL_LIMITS(textures)) {
2083 TRACE("Attempt to access invalid texture rejected\n");
2084 return D3DERR_INVALIDCALL;
2087 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
2088 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
2089 This->updateStateBlock->textureState[Stage][Type] = Value;
2091 /* Handle recording of state blocks */
2092 if (This->isRecordingState) {
2093 TRACE("Recording... not performing anything\n");
2099 /* Make appropriate texture active */
2100 VTRACE(("Activating appropriate texture state %ld\n", Stage));
2101 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2102 GLACTIVETEXTURE(Stage);
2103 } else if (Stage > 0) {
2104 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2109 case D3DTSS_MINFILTER :
2110 case D3DTSS_MIPFILTER :
2112 DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
2113 DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
2114 GLint realVal = GL_LINEAR;
2116 if (ValueMIN == D3DTEXF_NONE) {
2117 /* Doesn't really make sense - Windows just seems to disable
2118 mipmapping when this occurs */
2119 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2120 realVal = GL_LINEAR;
2121 } else if (ValueMIN == D3DTEXF_POINT) {
2123 if (ValueMIP == D3DTEXF_NONE) {
2124 realVal = GL_NEAREST;
2125 } else if (ValueMIP == D3DTEXF_POINT) {
2126 realVal = GL_NEAREST_MIPMAP_NEAREST;
2127 } else if (ValueMIP == D3DTEXF_LINEAR) {
2128 realVal = GL_NEAREST_MIPMAP_LINEAR;
2130 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2131 realVal = GL_NEAREST;
2133 } else if (ValueMIN == D3DTEXF_LINEAR) {
2135 if (ValueMIP == D3DTEXF_NONE) {
2136 realVal = GL_LINEAR;
2137 } else if (ValueMIP == D3DTEXF_POINT) {
2138 realVal = GL_LINEAR_MIPMAP_NEAREST;
2139 } else if (ValueMIP == D3DTEXF_LINEAR) {
2140 realVal = GL_LINEAR_MIPMAP_LINEAR;
2142 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2143 realVal = GL_LINEAR;
2145 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
2146 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2147 if (ValueMIP == D3DTEXF_NONE) {
2148 realVal = GL_LINEAR_MIPMAP_LINEAR;
2149 } else if (ValueMIP == D3DTEXF_POINT) {
2150 realVal = GL_LINEAR_MIPMAP_NEAREST;
2151 } else if (ValueMIP == D3DTEXF_LINEAR) {
2152 realVal = GL_LINEAR_MIPMAP_LINEAR;
2154 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2155 realVal = GL_LINEAR;
2158 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
2159 realVal = GL_LINEAR;
2162 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
2163 realVal = GL_LINEAR_MIPMAP_LINEAR;
2166 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
2167 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
2168 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
2170 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2172 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
2173 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2174 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2175 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2176 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2181 case D3DTSS_MAGFILTER :
2183 DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
2184 GLint realVal = GL_NEAREST;
2186 if (ValueMAG == D3DTEXF_POINT) {
2187 realVal = GL_NEAREST;
2188 } else if (ValueMAG == D3DTEXF_LINEAR) {
2189 realVal = GL_LINEAR;
2190 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
2191 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2192 realVal = GL_LINEAR;
2194 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
2195 realVal = GL_NEAREST;
2198 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
2199 realVal = GL_NEAREST;
2201 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
2202 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
2203 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
2205 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2207 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
2208 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2209 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2210 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2211 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2216 case D3DTSS_MAXMIPLEVEL :
2219 * Not really the same, but the more apprioprate than nothing
2221 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2222 GL_TEXTURE_BASE_LEVEL,
2223 This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
2224 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
2228 case D3DTSS_MAXANISOTROPY :
2230 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2231 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2232 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2233 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2234 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
2239 case D3DTSS_MIPMAPLODBIAS :
2241 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2243 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2244 GL_TEXTURE_LOD_BIAS_EXT,
2246 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2251 case D3DTSS_ALPHAOP :
2252 case D3DTSS_COLOROP :
2255 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
2256 /* TODO: Disable by making this and all later levels disabled */
2257 glDisable(GL_TEXTURE_1D);
2258 checkGLcall("Disable GL_TEXTURE_1D");
2259 glDisable(GL_TEXTURE_2D);
2260 checkGLcall("Disable GL_TEXTURE_2D");
2261 glDisable(GL_TEXTURE_3D);
2262 checkGLcall("Disable GL_TEXTURE_3D");
2263 break; /* Don't bother setting the texture operations */
2265 /* Enable only the appropriate texture dimension */
2266 if (Type == D3DTSS_COLOROP) {
2267 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2268 glEnable(GL_TEXTURE_1D);
2269 checkGLcall("Enable GL_TEXTURE_1D");
2271 glDisable(GL_TEXTURE_1D);
2272 checkGLcall("Disable GL_TEXTURE_1D");
2274 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
2275 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
2276 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2277 checkGLcall("Enable GL_TEXTURE_2D");
2279 glEnable(GL_TEXTURE_2D);
2280 checkGLcall("Enable GL_TEXTURE_2D");
2283 glDisable(GL_TEXTURE_2D);
2284 checkGLcall("Disable GL_TEXTURE_2D");
2286 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
2287 glEnable(GL_TEXTURE_3D);
2288 checkGLcall("Enable GL_TEXTURE_3D");
2290 glDisable(GL_TEXTURE_3D);
2291 checkGLcall("Disable GL_TEXTURE_3D");
2293 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
2294 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
2295 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
2297 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2298 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
2302 /* Drop through... (Except disable case) */
2303 case D3DTSS_COLORARG0 :
2304 case D3DTSS_COLORARG1 :
2305 case D3DTSS_COLORARG2 :
2306 case D3DTSS_ALPHAARG0 :
2307 case D3DTSS_ALPHAARG1 :
2308 case D3DTSS_ALPHAARG2 :
2310 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
2311 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
2313 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
2314 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1],
2315 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2],
2316 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
2318 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
2319 This->stateBlock->textureState[Stage][D3DTSS_COLORARG1],
2320 This->stateBlock->textureState[Stage][D3DTSS_COLORARG2],
2321 This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
2327 case D3DTSS_ADDRESSU :
2328 case D3DTSS_ADDRESSV :
2329 case D3DTSS_ADDRESSW :
2331 GLint wrapParm = GL_REPEAT;
2334 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
2335 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
2336 case D3DTADDRESS_BORDER:
2338 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2339 wrapParm = GL_CLAMP_TO_BORDER_ARB;
2341 /* FIXME: Not right, but better */
2342 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2343 wrapParm = GL_REPEAT;
2347 case D3DTADDRESS_MIRROR:
2349 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2350 wrapParm = GL_MIRRORED_REPEAT_ARB;
2352 /* Unsupported in OpenGL pre-1.4 */
2353 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
2354 wrapParm = GL_REPEAT;
2358 case D3DTADDRESS_MIRRORONCE:
2360 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2361 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
2363 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
2364 wrapParm = GL_REPEAT;
2370 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2371 wrapParm = GL_REPEAT;
2375 case D3DTSS_ADDRESSU:
2376 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2377 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
2378 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
2380 case D3DTSS_ADDRESSV:
2381 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2382 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
2383 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
2385 case D3DTSS_ADDRESSW:
2386 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2387 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
2388 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
2391 break; /** stupic compilator */
2396 case D3DTSS_BORDERCOLOR :
2399 D3DCOLORTOGLFLOAT4(Value, col);
2400 TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value);
2401 glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
2402 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
2406 case D3DTSS_TEXCOORDINDEX :
2408 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
2410 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
2411 one flag, you can still specify an index value, which the system uses to
2412 determine the texture wrapping mode.
2413 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2414 means use the vertex position (camera-space) as the input texture coordinates
2415 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
2416 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
2417 to the TEXCOORDINDEX value */
2420 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2422 switch (Value & 0xFFFF0000) {
2423 case D3DTSS_TCI_PASSTHRU:
2424 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2425 glDisable(GL_TEXTURE_GEN_S);
2426 glDisable(GL_TEXTURE_GEN_T);
2427 glDisable(GL_TEXTURE_GEN_R);
2428 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
2431 case D3DTSS_TCI_CAMERASPACEPOSITION:
2432 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2433 as the input texture coordinates for this stage's texture transformation. This
2434 equates roughly to EYE_LINEAR */
2436 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2437 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2438 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2439 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2440 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2442 glMatrixMode(GL_MODELVIEW);
2445 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2446 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2447 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2448 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2451 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2452 glEnable(GL_TEXTURE_GEN_S);
2453 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2454 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2455 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2456 glEnable(GL_TEXTURE_GEN_T);
2457 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2458 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2459 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2460 glEnable(GL_TEXTURE_GEN_R);
2461 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2462 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2463 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2467 case D3DTSS_TCI_CAMERASPACENORMAL:
2469 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2470 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2471 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2472 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2473 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2474 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2476 glMatrixMode(GL_MODELVIEW);
2479 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2480 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2481 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2482 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2485 glEnable(GL_TEXTURE_GEN_S);
2486 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2487 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2488 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2489 glEnable(GL_TEXTURE_GEN_T);
2490 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2491 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2492 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2493 glEnable(GL_TEXTURE_GEN_R);
2494 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2495 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2496 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2501 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2503 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2504 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2505 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2506 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2507 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2508 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2510 glMatrixMode(GL_MODELVIEW);
2513 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2514 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2515 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2516 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2519 glEnable(GL_TEXTURE_GEN_S);
2520 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2521 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2522 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2523 glEnable(GL_TEXTURE_GEN_T);
2524 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2525 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2526 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2527 glEnable(GL_TEXTURE_GEN_R);
2528 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2529 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2530 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2535 /* Unhandled types: */
2538 /* ? disable GL_TEXTURE_GEN_n ? */
2539 glDisable(GL_TEXTURE_GEN_S);
2540 glDisable(GL_TEXTURE_GEN_T);
2541 glDisable(GL_TEXTURE_GEN_R);
2542 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
2549 case D3DTSS_TEXTURETRANSFORMFLAGS :
2550 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
2553 case D3DTSS_BUMPENVMAT00 :
2554 case D3DTSS_BUMPENVMAT01 :
2555 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
2557 case D3DTSS_BUMPENVMAT10 :
2558 case D3DTSS_BUMPENVMAT11 :
2559 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
2562 case D3DTSS_BUMPENVLSCALE :
2563 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2566 case D3DTSS_BUMPENVLOFFSET :
2567 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2570 case D3DTSS_RESULTARG :
2571 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2575 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
2576 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2584 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
2585 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2586 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
2587 *pValue = This->updateStateBlock->textureState[Stage][Type];
2592 * Scene related functions
2594 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
2595 /* At the moment we have no need for any functionality at the beginning
2597 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2598 TRACE("(%p) : stub\n", This);
2602 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
2603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2604 TRACE("(%p)\n", This);
2609 checkGLcall("glFlush");
2611 #if 0 /* TODO: render targer support */
2612 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
2614 IWineD3DBaseTexture *cont = NULL;
2617 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
2618 if (SUCCEEDED(hr) && NULL != cont) {
2619 /** always dirtify for now. we must find a better way to see that surface have been modified */
2620 This->renderTarget->inPBuffer = TRUE;
2621 This->renderTarget->inTexture = FALSE;
2622 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
2623 IDirect3DBaseTexture8_PreLoad(cont);
2624 This->renderTarget->inPBuffer = FALSE;
2625 IDirect3DBaseTexture8Impl_Release(cont);
2629 #endif /* TODO: render targer support */
2635 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
2636 CONST RECT* pSourceRect, CONST RECT* pDestRect,
2637 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
2638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2639 TRACE("(%p) Presenting the frame\n", This);
2643 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
2645 glXSwapBuffers(This->display, This->drawable);
2646 /* Don't call checkGLcall, as glGetError is not applicable here */
2648 TRACE("glXSwapBuffers called, Starting new frame\n");
2651 if (TRACE_ON(d3d_fps))
2653 static long prev_time, frames;
2655 DWORD time = GetTickCount();
2657 /* every 1.5 seconds */
2658 if (time - prev_time > 1500) {
2659 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
2665 #if defined(FRAME_DEBUGGING)
2667 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
2670 FIXME("Enabling D3D Trace\n");
2671 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
2672 #if defined(SHOW_FRAME_MAKEUP)
2673 FIXME("Singe Frame snapshots Starting\n");
2674 isDumpingFrames = TRUE;
2675 glClear(GL_COLOR_BUFFER_BIT);
2678 #if defined(SINGLE_FRAME_DEBUGGING)
2680 #if defined(SHOW_FRAME_MAKEUP)
2681 FIXME("Singe Frame snapshots Finishing\n");
2682 isDumpingFrames = FALSE;
2684 FIXME("Singe Frame trace complete\n");
2685 DeleteFileA("C:\\D3DTRACE");
2686 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
2692 #if defined(SHOW_FRAME_MAKEUP)
2693 FIXME("Singe Frame snapshots Finishing\n");
2694 isDumpingFrames = FALSE;
2696 FIXME("Disabling D3D Trace\n");
2697 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
2704 /* Although this is not strictly required, a simple demo showed this does occur
2705 on (at least non-debug) d3d */
2706 if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
2707 IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
2713 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
2714 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
2715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2717 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
2718 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
2719 when the depth-buffer format does not contain stencil buffer information, this method fails. */
2720 GLbitfield glMask = 0;
2721 GLboolean old_ztest;
2722 GLfloat old_z_clear_value;
2723 GLint old_stencil_clear_value;
2724 GLfloat old_color_clear_value[4];
2726 CONST D3DRECT* curRect;
2728 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
2729 Count, pRects, Flags, Z, Stencil);
2733 glEnable(GL_SCISSOR_TEST);
2734 checkGLcall("glEnable GL_SCISSOR_TEST");
2736 if (Count > 0 && pRects) {
2742 /* Only set the values up once, as they are not changing */
2743 if (Flags & D3DCLEAR_STENCIL) {
2744 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2745 glClearStencil(Stencil);
2746 checkGLcall("glClearStencil");
2747 glMask = glMask | GL_STENCIL_BUFFER_BIT;
2748 glStencilMask(0xFFFFFFFF);
2751 if (Flags & D3DCLEAR_ZBUFFER) {
2752 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
2753 glDepthMask(GL_TRUE);
2754 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2756 checkGLcall("glClearDepth");
2757 glMask = glMask | GL_DEPTH_BUFFER_BIT;
2760 if (Flags & D3DCLEAR_TARGET) {
2761 TRACE("Clearing screen with glClear to color %lx\n", Color);
2762 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2763 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
2764 ((Color >> 8) & 0xFF) / 255.0f,
2765 ((Color >> 0) & 0xFF) / 255.0f,
2766 ((Color >> 24) & 0xFF) / 255.0f);
2767 checkGLcall("glClearColor");
2769 /* Clear ALL colors! */
2770 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2771 glMask = glMask | GL_COLOR_BUFFER_BIT;
2774 /* Now process each rect in turn */
2775 for (i = 0; i < Count || i == 0; i++) {
2777 #if 0 /* TODO: renderTarget support */
2779 /* Note gl uses lower left, width/height */
2780 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
2781 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
2782 curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
2783 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
2784 glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
2785 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
2786 checkGLcall("glScissor");
2788 glScissor(This->stateBlock->viewport.X,
2789 (This->renderTarget->myDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
2790 This->stateBlock->viewport.Width,
2791 This->stateBlock->viewport.Height);
2792 checkGLcall("glScissor");
2796 /* Clear the selected rectangle (or full screen) */
2798 checkGLcall("glClear");
2800 /* Step to the next rectangle */
2801 if (curRect) curRect = curRect + sizeof(D3DRECT);
2804 /* Restore the old values (why..?) */
2805 if (Flags & D3DCLEAR_STENCIL) {
2806 glClearStencil(old_stencil_clear_value);
2807 glStencilMask(This->stateBlock->renderState[D3DRS_STENCILWRITEMASK]);
2809 if (Flags & D3DCLEAR_ZBUFFER) {
2810 glDepthMask(old_ztest);
2811 glClearDepth(old_z_clear_value);
2813 if (Flags & D3DCLEAR_TARGET) {
2814 glClearColor(old_color_clear_value[0],
2815 old_color_clear_value[1],
2816 old_color_clear_value[2],
2817 old_color_clear_value[3]);
2818 glColorMask(This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2819 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2820 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2821 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2824 glDisable(GL_SCISSOR_TEST);
2825 checkGLcall("glDisable");
2834 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
2835 UINT PrimitiveCount) {
2837 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2838 This->stateBlock->streamIsUP = FALSE;
2840 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
2841 debug_d3dprimitivetype(PrimitiveType),
2842 StartVertex, PrimitiveCount);
2843 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
2848 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
2849 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
2850 D3DPRIMITIVETYPE PrimitiveType,
2851 INT baseVIndex, UINT minIndex,
2852 UINT NumVertices,UINT startIndex,UINT primCount) {
2854 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2856 IWineD3DIndexBuffer *pIB;
2857 D3DINDEXBUFFER_DESC IdxBufDsc;
2859 pIB = This->stateBlock->pIndexData;
2860 This->stateBlock->streamIsUP = FALSE;
2862 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
2863 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
2864 minIndex, NumVertices, startIndex, baseVIndex, primCount);
2866 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
2867 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
2873 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
2874 startIndex, idxStride,
2875 ((IWineD3DIndexBufferImpl *) pIB)->allocatedMemory,
2881 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
2882 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
2883 UINT VertexStreamZeroStride) {
2884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2886 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
2887 debug_d3dprimitivetype(PrimitiveType),
2888 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
2890 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
2892 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
2893 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
2894 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
2895 This->stateBlock->streamIsUP = TRUE;
2896 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
2897 This->stateBlock->stream_stride[0] = 0;
2898 This->stateBlock->stream_source[0] = NULL;
2900 /*stream zero settings set to null at end, as per the msdn */
2904 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
2905 UINT MinVertexIndex,
2906 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
2907 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
2908 UINT VertexStreamZeroStride) {
2910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2912 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
2913 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
2914 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
2915 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
2917 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
2919 if (IndexDataFormat == D3DFMT_INDEX16) {
2925 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
2926 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
2927 This->stateBlock->streamIsUP = TRUE;
2928 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
2930 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
2932 /* stream zero settings set to null at end as per the msdn */
2933 This->stateBlock->stream_source[0] = NULL;
2934 This->stateBlock->stream_stride[0] = 0;
2935 IWineD3DDevice_SetIndices(iface, NULL, 0);
2940 /**********************************************************
2941 * IUnknown parts follows
2942 **********************************************************/
2944 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
2946 return E_NOINTERFACE;
2949 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
2950 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2951 TRACE("(%p) : AddRef increasing from %ld\n", This, This->ref);
2952 return InterlockedIncrement(&This->ref);
2955 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
2956 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2958 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
2959 ref = InterlockedDecrement(&This->ref);
2961 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
2962 IWineD3D_Release(This->wineD3D);
2963 HeapFree(GetProcessHeap(), 0, This);
2968 /**********************************************************
2969 * IWineD3DDevice VTbl follows
2970 **********************************************************/
2972 IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
2974 IWineD3DDeviceImpl_QueryInterface,
2975 IWineD3DDeviceImpl_AddRef,
2976 IWineD3DDeviceImpl_Release,
2977 IWineD3DDeviceImpl_GetParent,
2978 IWineD3DDeviceImpl_CreateVertexBuffer,
2979 IWineD3DDeviceImpl_CreateIndexBuffer,
2980 IWineD3DDeviceImpl_CreateStateBlock,
2982 IWineD3DDeviceImpl_SetFVF,
2983 IWineD3DDeviceImpl_GetFVF,
2984 IWineD3DDeviceImpl_SetStreamSource,
2985 IWineD3DDeviceImpl_GetStreamSource,
2986 IWineD3DDeviceImpl_SetTransform,
2987 IWineD3DDeviceImpl_GetTransform,
2988 IWineD3DDeviceImpl_MultiplyTransform,
2989 IWineD3DDeviceImpl_SetLight,
2990 IWineD3DDeviceImpl_GetLight,
2991 IWineD3DDeviceImpl_SetLightEnable,
2992 IWineD3DDeviceImpl_GetLightEnable,
2993 IWineD3DDeviceImpl_SetClipPlane,
2994 IWineD3DDeviceImpl_GetClipPlane,
2995 IWineD3DDeviceImpl_SetClipStatus,
2996 IWineD3DDeviceImpl_GetClipStatus,
2997 IWineD3DDeviceImpl_SetMaterial,
2998 IWineD3DDeviceImpl_GetMaterial,
2999 IWineD3DDeviceImpl_SetIndices,
3000 IWineD3DDeviceImpl_GetIndices,
3001 IWineD3DDeviceImpl_SetViewport,
3002 IWineD3DDeviceImpl_GetViewport,
3003 IWineD3DDeviceImpl_SetRenderState,
3004 IWineD3DDeviceImpl_GetRenderState,
3005 IWineD3DDeviceImpl_SetTextureStageState,
3006 IWineD3DDeviceImpl_GetTextureStageState,
3008 IWineD3DDeviceImpl_BeginScene,
3009 IWineD3DDeviceImpl_EndScene,
3010 IWineD3DDeviceImpl_Present,
3011 IWineD3DDeviceImpl_Clear,
3013 IWineD3DDeviceImpl_DrawPrimitive,
3014 IWineD3DDeviceImpl_DrawIndexedPrimitive,
3015 IWineD3DDeviceImpl_DrawPrimitiveUP,
3016 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
3018 IWineD3DDeviceImpl_SetupTextureStates