Implement render targets using either textures, swapchains or
[wine.git] / dlls / wined3d / device.c
blob5c226f3801e20127cf7b3f0cdb2f512ba120b10f
1 /*
2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "config.h"
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
45 Display *display;
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
50 return display;
53 /* helper macros */
54 #define D3DMEMCHECK(object, ppResult) if(NULL == object){ *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
56 #define D3DCREATEOBJECTINSTANCE(object, type){ \
57 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
58 D3DMEMCHECK(object, pp##type); \
59 object->lpVtbl = &IWineD3D##type##_Vtbl; \
60 object->wineD3DDevice = This; \
61 object->parent = parent; \
62 object->ref = 1; \
63 *pp##type = (IWineD3D##type *) object; \
66 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype){ \
67 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
68 D3DMEMCHECK(object, pp##type); \
69 object->lpVtbl = &IWineD3D##type##_Vtbl; \
70 object->resource.wineD3DDevice = This; \
71 object->resource.parent = parent; \
72 object->resource.resourceType = d3dtype; \
73 object->resource.ref = 1; \
74 object->resource.pool = Pool; \
75 object->resource.format = Format; \
76 object->resource.usage = Usage; \
77 object->resource.size = 0; \
78 object->resource.allocatedMemory = 0; \
79 *pp##type = (IWineD3D##type *) object; \
82 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
83 _basetexture.levels = Levels; \
84 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
85 _basetexture.LOD = 0; \
86 _basetexture.dirty = TRUE; \
89 /**********************************************************
90 * Global variable / Constants follow
91 **********************************************************/
92 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
94 /**********************************************************
95 * Utility functions follow
96 **********************************************************/
97 /* Convert the D3DLIGHT properties into equivalent gl lights */
98 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
100 float quad_att;
101 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
102 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
104 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
105 glMatrixMode(GL_MODELVIEW);
106 glPushMatrix();
107 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
109 /* Diffuse: */
110 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
111 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
112 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
113 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
114 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
115 checkGLcall("glLightfv");
117 /* Specular */
118 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
119 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
120 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
121 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
122 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
123 checkGLcall("glLightfv");
125 /* Ambient */
126 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
127 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
128 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
129 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
130 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
131 checkGLcall("glLightfv");
133 /* Attenuation - Are these right? guessing... */
134 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
135 checkGLcall("glLightf");
136 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
137 checkGLcall("glLightf");
139 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
140 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
141 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
142 checkGLcall("glLightf");
144 switch (lightInfo->OriginalParms.Type) {
145 case D3DLIGHT_POINT:
146 /* Position */
147 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
148 checkGLcall("glLightfv");
149 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
150 checkGLcall("glLightf");
151 /* FIXME: Range */
152 break;
154 case D3DLIGHT_SPOT:
155 /* Position */
156 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
157 checkGLcall("glLightfv");
158 /* Direction */
159 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
160 checkGLcall("glLightfv");
161 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
162 checkGLcall("glLightf");
163 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
164 checkGLcall("glLightf");
165 /* FIXME: Range */
166 break;
168 case D3DLIGHT_DIRECTIONAL:
169 /* Direction */
170 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
171 checkGLcall("glLightfv");
172 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
173 checkGLcall("glLightf");
174 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
175 checkGLcall("glLightf");
176 break;
178 default:
179 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
182 /* Restore the modelview matrix */
183 glPopMatrix();
186 /* Apply the current values to the specified texture stage */
187 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
189 int i = 0;
190 float col[4];
191 BOOL changeTexture = TRUE;
193 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
194 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
196 BOOL skip = FALSE;
198 switch (i) {
199 /* Performance: For texture states where multiples effect the outcome, only bother
200 applying the last one as it will pick up all the other values */
201 case WINED3DTSS_COLORARG0: /* Will be picked up when setting color op */
202 case WINED3DTSS_COLORARG1: /* Will be picked up when setting color op */
203 case WINED3DTSS_COLORARG2: /* Will be picked up when setting color op */
204 case WINED3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
205 case WINED3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
206 case WINED3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
207 skip = TRUE;
208 break;
210 /* Performance: If the texture states only impact settings for the texture unit
211 (compared to the texture object) then there is no need to reapply them. The
212 only time they need applying is the first time, since we cheat and put the
213 values into the stateblock without applying.
214 Per-texture unit: texture function (eg. combine), ops and args
215 texture env color
216 texture generation settings
217 Note: Due to some special conditions there may be a need to do particular ones
218 of these, which is what the Flags allows */
219 case WINED3DTSS_COLOROP:
220 case WINED3DTSS_TEXCOORDINDEX:
221 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
222 break;
224 case WINED3DTSS_ALPHAOP:
225 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
226 break;
228 default:
229 skip = FALSE;
232 if (skip == FALSE) {
233 /* Performance: Only change to this texture if we have to */
234 if (changeTexture) {
235 /* Make appropriate texture active */
236 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
237 GLACTIVETEXTURE(Stage);
238 } else if (Stage > 0) {
239 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
241 changeTexture = FALSE;
244 /* Now apply the change */
245 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
249 /* apply the sampler states to the texture */
250 for (i = 1; i <= HIGHEST_SAMPLER_STATE;i++) {
251 IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]);
254 /* Note the D3DRS value applies to all textures, but GL has one
255 * per texture, so apply it now ready to be used!
257 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
258 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
259 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
261 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
264 /**********************************************************
265 * IUnknown parts follows
266 **********************************************************/
268 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
270 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
271 /* FIXME: This needs to extend an IWineD3DBaseObject */
273 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
274 if (IsEqualGUID(riid, &IID_IUnknown)
275 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
276 IUnknown_AddRef(iface);
277 *ppobj = This;
278 return D3D_OK;
281 return E_NOINTERFACE;
284 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
285 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
286 ULONG refCount = InterlockedIncrement(&This->ref);
288 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
289 return refCount;
292 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
293 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
294 ULONG refCount = InterlockedDecrement(&This->ref);
296 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
298 if (!refCount) {
299 /* TODO: Clean up all the surfaces and textures! */
300 /* FIXME: Create targets and state blocks in d3d8 */
301 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
302 /* NOTE: You must release the parent if the objects was created via a callback
303 ** ***************************/
304 int i;
305 IUnknown* swapChainParent;
307 /* Release all of the swapchains, except the implicite swapchain (#0) */
308 for(i = 1; i < This->numberOfSwapChains; i++){
309 /* TODO: don't access swapchains[x] directly! */
310 IWineD3DSwapChain_Release(This->swapchains[i]);
313 if (This->stateBlock != NULL) {
314 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
317 if (This->swapchains[0] != NULL) {
318 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */
319 /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */
320 IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent);
321 IUnknown_Release(swapChainParent); /* once for the get parent */
322 if (IUnknown_Release(swapChainParent) > 0){ /* the second time for when it was created */
323 FIXME("(%p) Something's still holding the implicite swapchain\n",This);
328 IWineD3D_Release(This->wineD3D);
329 HeapFree(GetProcessHeap(), 0, This);
331 return refCount;
334 /**********************************************************
335 * IWineD3DDevice implementation follows
336 **********************************************************/
337 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
339 *pParent = This->parent;
340 IUnknown_AddRef(This->parent);
341 return D3D_OK;
344 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
345 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
346 IUnknown *parent) {
347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
348 IWineD3DVertexBufferImpl *object;
349 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
350 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER)
352 object->resource.size = Size;
353 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
354 object->FVF = FVF;
356 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
357 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
359 return D3D_OK;
362 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
363 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
364 HANDLE *sharedHandle, IUnknown *parent) {
365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
366 IWineD3DIndexBufferImpl *object;
367 TRACE("(%p) Creating index buffer\n", This);
369 /* Allocate the storage for the device */
370 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER)
372 object->resource.size = Length;
373 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
375 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
376 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
377 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
379 return D3D_OK;
382 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
384 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
385 IWineD3DStateBlockImpl *object;
386 int i,j;
388 D3DCREATEOBJECTINSTANCE(object, StateBlock)
389 object->blockType = Type;
391 /* Special case - Used during initialization to produce a placeholder stateblock
392 so other functions called can update a state block */
393 if (Type == (D3DSTATEBLOCKTYPE) 0) {
394 /* Don't bother increasing the reference count otherwise a device will never
395 be freed due to circular dependencies */
396 return D3D_OK;
399 /* Otherwise, might as well set the whole state block to the appropriate values */
400 IWineD3DDevice_AddRef(iface);
401 /* Otherwise, might as well set the whole state block to the appropriate values */
402 if ( This->stateBlock != NULL){
403 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
404 } else {
405 memset(object->streamFreq, 1, sizeof(object->streamFreq));
408 /* Reset the ref and type after kluging it */
409 object->wineD3DDevice = This;
410 object->ref = 1;
411 object->blockType = Type;
413 TRACE("Updating changed flags appropriate for type %d\n", Type);
415 if (Type == D3DSBT_ALL) {
416 TRACE("ALL => Pretend everything has changed\n");
417 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
418 } else if (Type == D3DSBT_PIXELSTATE) {
420 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
421 /* TODO: Pixel Shader Constants */
422 object->changed.pixelShader = TRUE;
423 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
424 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
426 for (j = 0; j < GL_LIMITS(textures); i++) {
427 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
428 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
431 /* Setting sampler block changes states */
432 for (j = 0 ; j < GL_LIMITS(samplers); j++){
433 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++){
435 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
438 } else if (Type == D3DSBT_VERTEXSTATE) {
440 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
442 /* TODO: Vertex Shader Constants */
443 object->changed.vertexShader = TRUE;
444 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
445 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
447 for (j = 0; j < GL_LIMITS(textures); i++) {
448 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
449 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
452 /* Setting sampler block changes states */
453 for (j = 0 ; j < GL_LIMITS(samplers); j++){
454 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++){
455 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
459 /* Duplicate light chain */
461 PLIGHTINFOEL *src = NULL;
462 PLIGHTINFOEL *dst = NULL;
463 PLIGHTINFOEL *newEl = NULL;
464 src = This->stateBlock->lights;
465 object->lights = NULL;
468 while (src) {
469 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
470 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
471 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
472 newEl->prev = dst;
473 newEl->changed = TRUE;
474 newEl->enabledChanged = TRUE;
475 if (dst == NULL) {
476 object->lights = newEl;
477 } else {
478 dst->next = newEl;
480 dst = newEl;
481 src = src->next;
486 } else {
487 FIXME("Unrecognized state block type %d\n", Type);
490 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
491 return D3D_OK;
495 /* ************************************
496 MSDN:
497 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
499 Discard
500 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
502 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
504 ******************************** */
506 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
507 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
508 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
509 unsigned int pow2Width, pow2Height;
511 TRACE("(%p) Create surface\n",This);
513 /** FIXME: Check ranges on the inputs are valid
514 * MSDN
515 * MultisampleQuality
516 * [in] Quality level. The valid range is between zero and one less than the level
517 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
518 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
519 * values of paired render targets, depth stencil surfaces, and the MultiSample type
520 * must all match.
521 *******************************/
525 * TODO: Discard MSDN
526 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
528 * If this flag is set, the contents of the depth stencil buffer will be
529 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
530 * with a different depth surface.
532 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
533 ***************************/
535 if(MultisampleQuality < 0) {
536 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
537 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
540 if(MultisampleQuality > 0){
541 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
542 MultisampleQuality=0;
545 /* Non-power2 support */
547 /* Find the nearest pow2 match */
548 pow2Width = pow2Height = 1;
549 while (pow2Width < Width) pow2Width <<= 1;
550 while (pow2Height < Height) pow2Height <<= 1;
552 if((pow2Width > Width || pow2Height > Height) && !Usage & D3DUSAGE_RENDERTARGET) {
553 /** TODO: add support for non power two textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
554 FIXME("non-power-two textures unsupported\n");
555 return D3DERR_NOTAVAILABLE;
558 /** TODO: Check against the maximum texture sizes supported by the video card **/
560 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE)
561 object->container = (IUnknown*) This;
563 object->currentDesc.Width = Width;
564 object->currentDesc.Height = Height;
565 object->currentDesc.Level = Level;
566 object->currentDesc.MultiSampleType = MultiSample;
567 object->currentDesc.MultiSampleQuality = MultisampleQuality;
568 object->discard = Discard;
569 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
571 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
572 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
573 * space!
574 *********************************/
575 if (Format == WINED3DFMT_DXT1) {
576 /* DXT1 is half byte per pixel */
577 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2;
579 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
580 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
581 object->resource.size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
582 } else {
583 object->resource.size = (Width * object->bytesPerPixel) * Height;
586 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
588 #if 0
589 /* TODO: Check that we have enough video ram left */
590 if(Pool == D3DPOOL_DEFAULT && IWineD3DDevice_GetAvailableTextureMem(iface) <= object->currentDesc.Size){
591 TRACE("Out of 'bogus' video memory\n");
592 HeapFree(GetProcessHeap(),0,object);
593 *ppSurface = NULL;
594 return D3DERR_OUTOFVIDEOMEMORY;
596 #endif
598 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
599 * this function is too deap to need to care about things like this.
600 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
601 * ****************************************/
602 switch(Pool) {
603 case D3DPOOL_SCRATCH:
604 if(Lockable == FALSE)
605 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
606 which are mutually exclusive, setting lockable to true\n");
607 Lockable = TRUE;
608 break;
609 case D3DPOOL_SYSTEMMEM:
610 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
611 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
612 case D3DPOOL_MANAGED:
613 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
614 Usage of DYNAMIC which are mutually exclusive, not doing \
615 anything just telling you.\n");
616 break;
617 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
618 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
619 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
620 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
621 break;
622 default:
623 FIXME("(%p) Unknown pool %d\n", This, Pool);
624 break;
627 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT){
628 FIXME("Trying to create a render target that isn't in the default pool\n");
632 object->locked = FALSE;
633 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
634 /* TODO: memory management */
635 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
636 if(object->resource.allocatedMemory == NULL ) {
637 FIXME("Out of memory!\n");
638 HeapFree(GetProcessHeap(),0,object);
639 *ppSurface = NULL;
640 return D3DERR_OUTOFVIDEOMEMORY;
644 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
645 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
646 This, Width, Height, Format, debug_d3dformat(Format),
647 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
648 return D3D_OK;
652 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
653 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
654 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
655 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
658 IWineD3DTextureImpl *object;
659 unsigned int i;
660 UINT tmpW;
661 UINT tmpH;
662 HRESULT hr;
664 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
666 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE);
667 D3DINITILIZEBASETEXTURE(object->baseTexture);
668 object->width = Width;
669 object->height = Height;
671 /* Calculate levels for mip mapping */
672 if (Levels == 0) {
673 TRACE("calculating levels %d\n", object->baseTexture.levels);
674 object->baseTexture.levels++;
675 tmpW = Width;
676 tmpH = Height;
677 while (tmpW > 1 && tmpH > 1) {
678 tmpW = max(1, tmpW >> 1);
679 tmpH = max(1, tmpH >> 1);
680 object->baseTexture.levels++;
682 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
685 /* Generate all the surfaces */
686 tmpW = Width;
687 tmpH = Height;
688 for (i = 0; i < object->baseTexture.levels; i++)
690 /* use the callback to create the texture surface */
691 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
692 if(hr!= D3D_OK){
693 int j;
694 FIXME("Failed to create surface %p \n",object);
695 /* clean up */
696 for(j=0;j<i;j++){
697 IWineD3DSurface_Release(object->surfaces[j]);
699 /* heap free object */
700 HeapFree(GetProcessHeap(),0,object);
702 *ppTexture = NULL;
703 return hr;
706 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
707 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
708 /* calculate the next mipmap level */
709 tmpW = max(1, tmpW >> 1);
710 tmpH = max(1, tmpH >> 1);
713 TRACE("(%p) : Created texture %p\n", This, object);
714 return D3D_OK;
717 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
718 UINT Width, UINT Height, UINT Depth,
719 UINT Levels, DWORD Usage,
720 WINED3DFORMAT Format, D3DPOOL Pool,
721 IWineD3DVolumeTexture** ppVolumeTexture,
722 HANDLE* pSharedHandle, IUnknown *parent,
723 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
725 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
726 IWineD3DVolumeTextureImpl *object;
727 unsigned int i;
728 UINT tmpW;
729 UINT tmpH;
730 UINT tmpD;
732 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE);
733 D3DINITILIZEBASETEXTURE(object->baseTexture);
735 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
736 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
738 object->width = Width;
739 object->height = Height;
740 object->depth = Depth;
742 /* Calculate levels for mip mapping */
743 if (Levels == 0) {
744 object->baseTexture.levels++;
745 tmpW = Width;
746 tmpH = Height;
747 tmpD = Depth;
748 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
749 tmpW = max(1, tmpW >> 1);
750 tmpH = max(1, tmpH >> 1);
751 tmpD = max(1, tmpD >> 1);
752 object->baseTexture.levels++;
754 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
757 /* Generate all the surfaces */
758 tmpW = Width;
759 tmpH = Height;
760 tmpD = Depth;
762 for (i = 0; i < object->baseTexture.levels; i++)
764 /* Create the volume */
765 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
766 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
767 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
769 tmpW = max(1, tmpW >> 1);
770 tmpH = max(1, tmpH >> 1);
771 tmpD = max(1, tmpD >> 1);
774 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
775 TRACE("(%p) : Created volume texture %p\n", This, object);
776 return D3D_OK;
779 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
780 UINT Width, UINT Height, UINT Depth,
781 DWORD Usage,
782 WINED3DFORMAT Format, D3DPOOL Pool,
783 IWineD3DVolume** ppVolume,
784 HANDLE* pSharedHandle, IUnknown *parent) {
786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
787 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
789 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME)
791 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
792 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
794 object->currentDesc.Width = Width;
795 object->currentDesc.Height = Height;
796 object->currentDesc.Depth = Depth;
797 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
799 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
800 object->resource.size = (Width * object->bytesPerPixel) * Height * Depth;
801 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
802 object->lockable = TRUE;
803 object->locked = FALSE;
804 memset(&object->lockedBox, 0, sizeof(D3DBOX));
805 object->dirty = FALSE;
806 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
809 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
810 UINT Levels, DWORD Usage,
811 WINED3DFORMAT Format, D3DPOOL Pool,
812 IWineD3DCubeTexture** ppCubeTexture,
813 HANDLE* pSharedHandle, IUnknown *parent,
814 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
817 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
818 unsigned int i,j;
819 UINT tmpW;
820 HRESULT hr;
822 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE);
823 D3DINITILIZEBASETEXTURE(object->baseTexture);
825 TRACE("(%p) Create Cube Texture \n", This);
827 object->edgeLength = EdgeLength;
829 /* Calculate levels for mip mapping */
830 if (Levels == 0) {
831 object->baseTexture.levels++;
832 tmpW = EdgeLength;
833 while (tmpW > 1) {
834 tmpW = max(1, tmpW / 2);
835 object->baseTexture.levels++;
837 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
840 /* Generate all the surfaces */
841 tmpW = EdgeLength;
842 for (i = 0; i < object->baseTexture.levels; i++) {
844 /* Create the 6 faces */
845 for (j = 0; j < 6; j++) {
847 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
848 i /* Level */, &object->surfaces[j][i],pSharedHandle);
850 if(hr!= D3D_OK){
851 /* clean up */
852 int k;
853 int l;
854 for (l=0;l<j;l++) {
855 IWineD3DSurface_Release(object->surfaces[j][i]);
857 for (k=0;k<i;k++) {
858 for (l=0;l<6;l++) {
859 IWineD3DSurface_Release(object->surfaces[l][j]);
863 FIXME("(%p) Failed to create surface\n",object);
864 HeapFree(GetProcessHeap(),0,object);
865 *ppCubeTexture = NULL;
866 return hr;
868 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
869 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
871 tmpW = max(1, tmpW >> 1);
874 TRACE("(%p) : Created Cube Texture %p\n", This, object);
875 *ppCubeTexture = (IWineD3DCubeTexture *) object;
876 return D3D_OK;
879 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent){
880 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
881 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
883 if(NULL == ppQuery){
884 /* Just a check to see if we support this type of query */
885 HRESULT hr = D3DERR_NOTAVAILABLE;
886 /* Lie and say everything is good (we can return ok fake data from a stub) */
887 switch(Type){
888 case WINED3DQUERYTYPE_VCACHE:
889 case WINED3DQUERYTYPE_RESOURCEMANAGER:
890 case WINED3DQUERYTYPE_VERTEXSTATS:
891 case WINED3DQUERYTYPE_EVENT:
892 case WINED3DQUERYTYPE_OCCLUSION:
893 case WINED3DQUERYTYPE_TIMESTAMP:
894 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
895 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
896 case WINED3DQUERYTYPE_PIPELINETIMINGS:
897 case WINED3DQUERYTYPE_INTERFACETIMINGS:
898 case WINED3DQUERYTYPE_VERTEXTIMINGS:
899 case WINED3DQUERYTYPE_PIXELTIMINGS:
900 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
901 case WINED3DQUERYTYPE_CACHEUTILIZATION:
902 hr = D3D_OK;
903 break;
904 default:
905 FIXME("(%p) Unhandled query type %d\n",This , Type);
907 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
908 return hr;
911 D3DCREATEOBJECTINSTANCE(object, Query)
912 object->type = Type;
913 object->extendedData = 0;
914 TRACE("(%p) : Created Query %p\n", This, object);
915 return D3D_OK;
918 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
919 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
920 IUnknown* parent,
921 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
922 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil){
923 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
925 HDC hDc;
926 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
927 int num;
928 XVisualInfo template;
929 GLXContext oldContext;
930 Drawable oldDrawable;
931 HRESULT hr = D3D_OK;
933 TRACE("(%p) : Created Aditional Swap Chain\n", This);
935 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
936 * does a device hold a reference to a swap chain giving them a lifetime of the device
937 * or does the swap chain notify the device of it'd destruction.
938 *******************************/
940 D3DCREATEOBJECTINSTANCE(object, SwapChain)
942 /* Initialize other useful values */
943 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
945 /*********************
946 * Lookup the window Handle and the relating X window handle
947 ********************/
949 /* Setup hwnd we are using, plus which display this equates to */
950 object->win_handle = *(pPresentationParameters->hDeviceWindow);
951 if (!object->win_handle) {
952 object->win_handle = This->createParms.hFocusWindow;
955 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
956 hDc = GetDC(object->win_handle);
957 object->display = get_display(hDc);
958 ReleaseDC(object->win_handle, hDc);
959 TRACE("Using a display of %p %p \n", object->display, hDc);
961 if (NULL == object->display || NULL == hDc) {
962 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
963 return D3DERR_NOTAVAILABLE;
966 if (object->win == 0) {
967 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
968 return D3DERR_NOTAVAILABLE;
971 * Create an opengl context for the display visual
972 * NOTE: the visual is chosen as the window is created and the glcontext cannot
973 * use different properties after that point in time. FIXME: How to handle when requested format
974 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
975 * it chooses is identical to the one already being used!
976 **********************************/
978 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
979 ENTER_GL();
981 /* Create a new context for this swapchain */
982 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
983 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
984 (or the best possible if none is requested) */
985 TRACE("Found x visual ID : %ld\n", template.visualid);
987 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
988 if (NULL == object->visInfo) {
989 ERR("cannot really get XVisual\n");
990 LEAVE_GL();
991 return D3DERR_NOTAVAILABLE;
992 } else {
993 int n, value;
994 /* Write out some debug info about the visual/s */
995 TRACE("Using x visual ID : %ld\n", template.visualid);
996 TRACE(" visual info: %p\n", object->visInfo);
997 TRACE(" num items : %d\n", num);
998 for(n = 0;n < num; n++){
999 TRACE("=====item=====: %d\n", n + 1);
1000 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1001 TRACE(" screen : %d\n", object->visInfo[n].screen);
1002 TRACE(" depth : %u\n", object->visInfo[n].depth);
1003 TRACE(" class : %d\n", object->visInfo[n].class);
1004 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1005 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1006 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1007 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1008 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1009 /* log some extra glx info */
1010 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1011 TRACE(" gl_aux_buffers : %d\n", value);
1012 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1013 TRACE(" gl_buffer_size : %d\n", value);
1014 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1015 TRACE(" gl_red_size : %d\n", value);
1016 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1017 TRACE(" gl_green_size : %d\n", value);
1018 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1019 TRACE(" gl_blue_size : %d\n", value);
1020 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1021 TRACE(" gl_alpha_size : %d\n", value);
1022 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1023 TRACE(" gl_depth_size : %d\n", value);
1024 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1025 TRACE(" gl_stencil_size : %d\n", value);
1027 /* Now choose a simila visual ID*/
1029 #ifdef USE_CONTEXT_MANAGER
1031 /** TODO: use a context mamager **/
1032 #endif
1035 IWineD3DSwapChain *implSwapChain;
1036 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1037 /* The first time around we create the context that is shared with all other swapchians and render targets */
1038 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1039 TRACE("Creating implicite context for vis %p, hwnd %p\n", object->display, object->visInfo);
1040 } else {
1042 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1043 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1044 /* and create a new context with the implicit swapchains context as the shared context */
1045 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1046 IWineD3DSwapChain_Release(implSwapChain);
1050 /* Cleanup */
1051 XFree(object->visInfo);
1052 object->visInfo = NULL;
1054 if (NULL == object->glCtx) {
1055 ERR("cannot create glxContext\n");
1056 LEAVE_GL();
1057 return D3DERR_NOTAVAILABLE;
1060 LEAVE_GL();
1061 if (object->glCtx == NULL) {
1062 ERR("Error in context creation !\n");
1063 return D3DERR_INVALIDCALL;
1064 } else {
1065 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1066 object->win_handle, object->glCtx, object->win, object->visInfo);
1069 /*********************
1070 * Windowed / Fullscreen
1071 *******************/
1074 * TODO: MSDNsays that we are only allowed one fullscreen swapchain per device,
1075 * so we should really check to see if their is a fullscreen swapchain already
1076 * I think Windows and X have differnt ideas about fullscreen, does a single head count as full screen?
1077 **************************************/
1079 if (!*(pPresentationParameters->Windowed)) {
1081 DEVMODEW devmode;
1082 HDC hdc;
1083 int bpp = 0;
1085 /* Get info on the current display setup */
1086 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1087 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1088 DeleteDC(hdc);
1090 /* Change the display settings */
1091 memset(&devmode, 0, sizeof(DEVMODEW));
1092 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1093 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1094 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1095 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1096 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1097 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1099 /* Make popup window */
1100 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1101 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1102 *(pPresentationParameters->BackBufferWidth),
1103 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1109 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1110 * then the corresponding dimension of the client area of the hDeviceWindow
1111 * (or the focus window, if hDeviceWindow is NULL) is taken.
1112 **********************/
1114 if (*(pPresentationParameters->Windowed) &&
1115 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1116 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1118 RECT Rect;
1119 GetClientRect(object->win_handle, &Rect);
1121 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1122 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1123 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1125 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1126 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1127 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1131 /*********************
1132 * finish off parameter initialization
1133 *******************/
1135 /* Put the correct figures in the presentation parameters */
1136 TRACE("Coppying accross presentaion paraneters\n");
1137 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1138 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1139 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1140 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1141 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1142 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1143 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1144 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1145 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1146 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1147 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1148 object->presentParms.Flags = *(pPresentationParameters->Flags);
1149 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1150 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1153 /* FIXME: check for any failures */
1154 /*********************
1155 * Create the back, front and stencil buffers
1156 *******************/
1157 TRACE("calling rendertarget CB\n");
1158 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1159 object->presentParms.BackBufferWidth,
1160 object->presentParms.BackBufferHeight,
1161 object->presentParms.BackBufferFormat,
1162 object->presentParms.MultiSampleType,
1163 object->presentParms.MultiSampleQuality,
1164 TRUE /* Lockable */,
1165 &object->frontBuffer,
1166 NULL /* pShared (always null)*/);
1167 if (object->frontBuffer != NULL)
1168 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1169 TRACE("calling rendertarget CB\n");
1170 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1171 object->presentParms.BackBufferWidth,
1172 object->presentParms.BackBufferHeight,
1173 object->presentParms.BackBufferFormat,
1174 object->presentParms.MultiSampleType,
1175 object->presentParms.MultiSampleQuality,
1176 TRUE /* Lockable */,
1177 &object->backBuffer,
1178 NULL /* pShared (always null)*/);
1179 if (object->backBuffer != NULL)
1180 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1182 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1183 if (pPresentationParameters->EnableAutoDepthStencil) {
1184 TRACE("Creating depth stencil buffer\n");
1185 if (This->depthStencilBuffer == NULL ) {
1186 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1187 object->presentParms.BackBufferWidth,
1188 object->presentParms.BackBufferHeight,
1189 object->presentParms.AutoDepthStencilFormat,
1190 object->presentParms.MultiSampleType,
1191 object->presentParms.MultiSampleQuality,
1192 FALSE /* FIXME: Discard */,
1193 &This->depthStencilBuffer,
1194 NULL /* pShared (always null)*/ );
1195 if (This->depthStencilBuffer != NULL)
1196 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1199 /** TODO: A check on width, height and multisample types
1200 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1201 ****************************/
1202 object->wantsDepthStencilBuffer = TRUE;
1203 } else {
1204 object->wantsDepthStencilBuffer = FALSE;
1207 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1210 /*********************
1211 * init the default renderTarget management
1212 *******************/
1213 object->drawable = object->win;
1214 object->render_ctx = object->glCtx;
1216 if(hr == D3D_OK){
1217 /*********************
1218 * Setup some defaults and clear down the buffers
1219 *******************/
1220 ENTER_GL();
1221 /** save current context and drawable **/
1222 oldContext = glXGetCurrentContext();
1223 oldDrawable = glXGetCurrentDrawable();
1225 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1226 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1227 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1229 checkGLcall("glXMakeCurrent");
1231 TRACE("Setting up the screen\n");
1232 /* Clear the screen */
1233 glClearColor(0.0, 0.0, 0.0, 0.0);
1234 checkGLcall("glClearColor");
1235 glClearIndex(0);
1236 glClearDepth(1);
1237 glClearStencil(0xffff);
1239 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1240 checkGLcall("glClear");
1242 glColor3f(1.0, 1.0, 1.0);
1243 checkGLcall("glColor3f");
1245 glEnable(GL_LIGHTING);
1246 checkGLcall("glEnable");
1248 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1249 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1251 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1252 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1254 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1255 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1257 /* switch back to the original context (unless it was zero)*/
1258 if (This->numberOfSwapChains != 0) {
1259 /** TODO: restore the context and drawable **/
1260 glXMakeCurrent(object->display, oldDrawable, oldContext);
1263 LEAVE_GL();
1265 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1266 #if 0
1267 IListOperator *listOperator;
1268 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1269 IListOperator_Append(listOperator, (void *)object);
1270 IListOperator_Release(listOperator);
1271 #endif
1273 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1274 TRACE("Set swapchain to %p\n", object);
1275 } else { /* something went wrong so clean up */
1276 IUnknown* bufferParent;
1277 if (object->frontBuffer) {
1278 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1279 IUnknown_Release(bufferParent); /* once for the get parent */
1280 if(IUnknown_Release(bufferParent) > 0){
1281 FIXME("(%p) Something's still holding the front buffer\n",This);
1284 if (object->backBuffer) {
1285 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1286 IUnknown_Release(bufferParent); /* once for the get parent */
1287 if(IUnknown_Release(bufferParent) > 0){
1288 FIXME("(%p) Something's still holding the back buffer\n",This);
1291 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1292 /* Clean up the context */
1293 /* check that we are the current context first (we shouldn't be though!) */
1294 if (object->glCtx != 0) {
1295 if(glXGetCurrentContext() == object->glCtx){
1296 glXMakeCurrent(object->display, None, NULL);
1298 glXDestroyContext(object->display, object->glCtx);
1300 HeapFree(GetProcessHeap(), 0, object);
1303 return hr;
1306 /** NOTE: These are ahead of the other getters and setters to save using a forward declartion **/
1307 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1310 /* TODO: move over to using a linked list. */
1311 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1312 return This->numberOfSwapChains;
1315 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1317 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1319 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0){
1320 *pSwapChain = NULL;
1321 return D3DERR_INVALIDCALL;
1322 }else{
1323 /** TODO: move off to a linked list implementation **/
1324 *pSwapChain = This->swapchains[iSwapChain];
1327 /* TODO: move over to using stores and linked lists. */
1329 IWineD3DSwapChain_AddRef(*pSwapChain);
1330 TRACE("(%p) returning %p\n", This, *pSwapChain);
1331 return D3D_OK;
1334 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters){
1335 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1337 FIXME("(%p) : Stub\n",This);
1338 return D3D_OK;
1342 /*****
1343 * Vertex Declaration
1344 *****/
1345 /* TODO: Get ridd of thease and put the functions in the IWineD3DVertexDeclaration interface */
1346 #if 1
1347 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration8(IWineD3DDeviceImpl * This, const DWORD* pDecl, IWineD3DVertexDeclarationImpl * object);
1348 extern HRESULT IWineD3DVertexDeclarationImpl_ParseDeclaration9(IWineD3DDeviceImpl * This, const D3DVERTEXELEMENT9* pDecl, IWineD3DVertexDeclarationImpl * object);
1351 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1353 IWineD3DVertexDeclarationImpl *object = NULL;
1354 HRESULT hr = D3D_OK;
1356 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1357 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1358 object->allFVF = 0;
1360 if (8 == ((IWineD3DImpl *)This->wineD3D)->dxVersion) {
1361 /** @TODO */
1362 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, (const DWORD*) pDeclaration, object);
1363 } else {
1364 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, (const D3DVERTEXELEMENT9*) pDeclaration, object);
1367 return hr;
1371 #else
1372 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration8(IWineD3DDevice* iface, const DWORD* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1373 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1374 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1375 HRESULT hr = D3D_OK;
1376 /* TODO: replace impl usage with a call to Version*/
1377 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1378 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1379 object->allFVF = 0;
1380 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1381 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration8(This, pDeclaration, object);
1383 return hr;
1386 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration9(IWineD3DDevice* iface, const D3DVERTEXELEMENT9* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent){
1387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1388 IWineD3DVertexDeclarationImpl *object = NULL; /* NOTE: impl allowed, this is a create */
1389 HRESULT hr = D3D_OK;
1390 /* TODO: replace impl usage with a call to Version*/
1391 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1392 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1393 object->allFVF = 0;
1394 /* TODO: get ridd of the impl usage, we should only be using interfaces */
1395 hr = IWineD3DVertexDeclarationImpl_ParseDeclaration9(This, pDeclaration, object);
1397 return hr;
1399 #endif
1401 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1402 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent){
1403 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1404 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1405 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1406 object->function = pFunction;
1407 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1408 return D3D_OK;
1412 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent){
1413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1414 FIXME("(%p) : Stub\n", This);
1415 return D3D_OK;
1418 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D){
1419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1420 *ppD3D= This->wineD3D;
1421 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1422 IWineD3D_AddRef(*ppD3D);
1423 return D3D_OK;
1427 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1428 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1429 FIXME("Stub :(%p) returning 64Mib\n", This);
1430 return 64*1024*1024;
1434 /*****
1435 * Get / Set FVF
1436 *****/
1437 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1438 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1440 /* Update the current state block */
1441 This->updateStateBlock->fvf = fvf;
1442 This->updateStateBlock->changed.fvf = TRUE;
1443 This->updateStateBlock->set.fvf = TRUE;
1445 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1447 /* No difference if recording or not */
1448 return D3D_OK;
1450 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1451 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1452 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1453 *pfvf = This->stateBlock->fvf;
1454 return D3D_OK;
1457 /*****
1458 * Get / Set Stream Source
1459 *****/
1460 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1462 IWineD3DVertexBuffer *oldSrc;
1464 oldSrc = This->stateBlock->streamSource[StreamNumber];
1465 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1467 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1468 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1469 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1470 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1471 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1473 /* Handle recording of state blocks */
1474 if (This->isRecordingState) {
1475 TRACE("Recording... not performing anything\n");
1476 return D3D_OK;
1479 /* Not recording... */
1480 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1481 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1483 return D3D_OK;
1486 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1487 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1489 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1490 *pStream = This->stateBlock->streamSource[StreamNumber];
1491 *pStride = This->stateBlock->streamStride[StreamNumber];
1492 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1493 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1494 return D3D_OK;
1497 /*Should be quite easy, just an extension of vertexdata
1498 ref...
1499 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1501 The divider is a bit odd though
1503 VertexOffset = StartVertex / Divider * StreamStride +
1504 VertexIndex / Divider * StreamStride + StreamOffset
1507 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider){
1508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1510 FIXME("(%p) : stub\n", This);
1511 return D3D_OK;
1514 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider){
1515 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1517 FIXME("(%p) : stub\n", This);
1518 return D3D_OK;
1522 /*****
1523 * Get / Set & Multipy Transform
1524 *****/
1525 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1526 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1528 /* Most of this routine, comments included copied from ddraw tree initially: */
1529 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1531 /* Handle recording of state blocks */
1532 if (This->isRecordingState) {
1533 TRACE("Recording... not performing anything\n");
1534 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1535 This->updateStateBlock->set.transform[d3dts] = TRUE;
1536 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1537 return D3D_OK;
1541 * If the new matrix is the same as the current one,
1542 * we cut off any further processing. this seems to be a reasonable
1543 * optimization because as was noticed, some apps (warcraft3 for example)
1544 * tend towards setting the same matrix repeatedly for some reason.
1546 * From here on we assume that the new matrix is different, wherever it matters.
1548 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1549 TRACE("The app is setting the same matrix over again\n");
1550 return D3D_OK;
1551 } else {
1552 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1556 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1557 where ViewMat = Camera space, WorldMat = world space.
1559 In OpenGL, camera and world space is combined into GL_MODELVIEW
1560 matrix. The Projection matrix stay projection matrix.
1563 /* Capture the times we can just ignore the change for now */
1564 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1565 This->modelview_valid = FALSE;
1566 return D3D_OK;
1568 } else if (d3dts == D3DTS_PROJECTION) {
1569 This->proj_valid = FALSE;
1570 return D3D_OK;
1572 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1573 /* Indexed Vertex Blending Matrices 256 -> 511 */
1574 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1575 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1576 return D3D_OK;
1579 /* Now we really are going to have to change a matrix */
1580 ENTER_GL();
1582 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1583 if (d3dts < GL_LIMITS(textures)) {
1584 int tex = d3dts - D3DTS_TEXTURE0;
1585 GLACTIVETEXTURE(tex);
1586 set_texture_matrix((float *)lpmatrix,
1587 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS]);
1590 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1591 unsigned int k;
1593 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1594 * NOTE: We have to reset the positions even if the light/plane is not currently
1595 * enabled, since the call to enable it will not reset the position.
1596 * NOTE2: Apparently texture transforms do NOT need reapplying
1599 PLIGHTINFOEL *lightChain = NULL;
1600 This->modelview_valid = FALSE;
1601 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1603 glMatrixMode(GL_MODELVIEW);
1604 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1605 glPushMatrix();
1606 glLoadMatrixf((float *)lpmatrix);
1607 checkGLcall("glLoadMatrixf(...)");
1609 /* Reset lights */
1610 lightChain = This->stateBlock->lights;
1611 while (lightChain && lightChain->glIndex != -1) {
1612 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1613 checkGLcall("glLightfv posn");
1614 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1615 checkGLcall("glLightfv dirn");
1616 lightChain = lightChain->next;
1619 /* Reset Clipping Planes if clipping is enabled */
1620 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1621 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1622 checkGLcall("glClipPlane");
1624 glPopMatrix();
1626 } else { /* What was requested!?? */
1627 WARN("invalid matrix specified: %i\n", d3dts);
1630 /* Release lock, all done */
1631 LEAVE_GL();
1632 return D3D_OK;
1635 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1637 TRACE("(%p) : for Transform State %d\n", This, State);
1638 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1639 return D3D_OK;
1642 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1643 D3DMATRIX *mat = NULL;
1644 D3DMATRIX temp;
1646 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1647 * below means it will be recorded in a state block change, but it
1648 * works regardless where it is recorded.
1649 * If this is found to be wrong, change to StateBlock.
1651 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1652 TRACE("(%p) : For state %u\n", This, State);
1654 if (State < HIGHEST_TRANSFORMSTATE)
1656 mat = &This->updateStateBlock->transforms[State];
1657 } else {
1658 FIXME("Unhandled transform state!!\n");
1661 /* Copied from ddraw code: */
1662 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);
1663 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);
1664 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);
1665 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);
1667 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);
1668 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);
1669 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);
1670 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);
1672 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);
1673 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);
1674 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);
1675 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);
1677 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);
1678 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);
1679 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);
1680 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);
1682 /* Apply change via set transform - will reapply to eg. lights this way */
1683 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1684 return D3D_OK;
1687 /*****
1688 * Get / Set Light
1689 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1690 *****/
1691 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1692 you can reference any indexes you want as long as that number max are enabled at any
1693 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1694 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1695 but when recording, just build a chain pretty much of commands to be replayed. */
1697 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1698 float rho;
1699 PLIGHTINFOEL *object, *temp;
1701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1702 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1704 /* If recording state block, just add to end of lights chain */
1705 if (This->isRecordingState) {
1706 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1707 if (NULL == object) {
1708 return D3DERR_OUTOFVIDEOMEMORY;
1710 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1711 object->OriginalIndex = Index;
1712 object->glIndex = -1;
1713 object->changed = TRUE;
1715 /* Add to the END of the chain of lights changes to be replayed */
1716 if (This->updateStateBlock->lights == NULL) {
1717 This->updateStateBlock->lights = object;
1718 } else {
1719 temp = This->updateStateBlock->lights;
1720 while (temp->next != NULL) temp=temp->next;
1721 temp->next = object;
1723 TRACE("Recording... not performing anything more\n");
1724 return D3D_OK;
1727 /* Ok, not recording any longer so do real work */
1728 object = This->stateBlock->lights;
1729 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1731 /* If we didn't find it in the list of lights, time to add it */
1732 if (object == NULL) {
1733 PLIGHTINFOEL *insertAt,*prevPos;
1735 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1736 if (NULL == object) {
1737 return D3DERR_OUTOFVIDEOMEMORY;
1739 object->OriginalIndex = Index;
1740 object->glIndex = -1;
1742 /* Add it to the front of list with the idea that lights will be changed as needed
1743 BUT after any lights currently assigned GL indexes */
1744 insertAt = This->stateBlock->lights;
1745 prevPos = NULL;
1746 while (insertAt != NULL && insertAt->glIndex != -1) {
1747 prevPos = insertAt;
1748 insertAt = insertAt->next;
1751 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1752 This->stateBlock->lights = object;
1753 } else if (insertAt == NULL) { /* End of list */
1754 prevPos->next = object;
1755 object->prev = prevPos;
1756 } else { /* Middle of chain */
1757 if (prevPos == NULL) {
1758 This->stateBlock->lights = object;
1759 } else {
1760 prevPos->next = object;
1762 object->prev = prevPos;
1763 object->next = insertAt;
1764 insertAt->prev = object;
1768 /* Initialze the object */
1769 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,
1770 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1771 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1772 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1773 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1774 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1775 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1777 /* Save away the information */
1778 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1780 switch (pLight->Type) {
1781 case D3DLIGHT_POINT:
1782 /* Position */
1783 object->lightPosn[0] = pLight->Position.x;
1784 object->lightPosn[1] = pLight->Position.y;
1785 object->lightPosn[2] = pLight->Position.z;
1786 object->lightPosn[3] = 1.0f;
1787 object->cutoff = 180.0f;
1788 /* FIXME: Range */
1789 break;
1791 case D3DLIGHT_DIRECTIONAL:
1792 /* Direction */
1793 object->lightPosn[0] = -pLight->Direction.x;
1794 object->lightPosn[1] = -pLight->Direction.y;
1795 object->lightPosn[2] = -pLight->Direction.z;
1796 object->lightPosn[3] = 0.0;
1797 object->exponent = 0.0f;
1798 object->cutoff = 180.0f;
1799 break;
1801 case D3DLIGHT_SPOT:
1802 /* Position */
1803 object->lightPosn[0] = pLight->Position.x;
1804 object->lightPosn[1] = pLight->Position.y;
1805 object->lightPosn[2] = pLight->Position.z;
1806 object->lightPosn[3] = 1.0;
1808 /* Direction */
1809 object->lightDirn[0] = pLight->Direction.x;
1810 object->lightDirn[1] = pLight->Direction.y;
1811 object->lightDirn[2] = pLight->Direction.z;
1812 object->lightDirn[3] = 1.0;
1815 * opengl-ish and d3d-ish spot lights use too different models for the
1816 * light "intensity" as a function of the angle towards the main light direction,
1817 * so we only can approximate very roughly.
1818 * however spot lights are rather rarely used in games (if ever used at all).
1819 * furthermore if still used, probably nobody pays attention to such details.
1821 if (pLight->Falloff == 0) {
1822 rho = 6.28f;
1823 } else {
1824 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1826 if (rho < 0.0001) rho = 0.0001f;
1827 object->exponent = -0.3/log(cos(rho/2));
1828 object->cutoff = pLight->Phi*90/M_PI;
1830 /* FIXME: Range */
1831 break;
1833 default:
1834 FIXME("Unrecognized light type %d\n", pLight->Type);
1837 /* Update the live definitions if the light is currently assigned a glIndex */
1838 if (object->glIndex != -1) {
1839 setup_light(iface, object->glIndex, object);
1841 return D3D_OK;
1844 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1845 PLIGHTINFOEL *lightInfo = NULL;
1846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1847 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1849 /* Locate the light in the live lights */
1850 lightInfo = This->stateBlock->lights;
1851 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1853 if (lightInfo == NULL) {
1854 TRACE("Light information requested but light not defined\n");
1855 return D3DERR_INVALIDCALL;
1858 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1859 return D3D_OK;
1862 /*****
1863 * Get / Set Light Enable
1864 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1865 *****/
1866 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1867 PLIGHTINFOEL *lightInfo = NULL;
1868 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1869 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1871 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1872 if (This->isRecordingState) {
1873 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1874 if (NULL == lightInfo) {
1875 return D3DERR_OUTOFVIDEOMEMORY;
1877 lightInfo->OriginalIndex = Index;
1878 lightInfo->glIndex = -1;
1879 lightInfo->enabledChanged = TRUE;
1881 /* Add to the END of the chain of lights changes to be replayed */
1882 if (This->updateStateBlock->lights == NULL) {
1883 This->updateStateBlock->lights = lightInfo;
1884 } else {
1885 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1886 while (temp->next != NULL) temp=temp->next;
1887 temp->next = lightInfo;
1889 TRACE("Recording... not performing anything more\n");
1890 return D3D_OK;
1893 /* Not recording... So, locate the light in the live lights */
1894 lightInfo = This->stateBlock->lights;
1895 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1897 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1898 if (lightInfo == NULL) {
1899 D3DLIGHT9 lightParms;
1900 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1901 wait until someone confirms it seems to work! */
1902 TRACE("Light enabled requested but light not defined, so defining one!\n");
1903 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1904 lightParms.Diffuse.r = 1.0;
1905 lightParms.Diffuse.g = 1.0;
1906 lightParms.Diffuse.b = 1.0;
1907 lightParms.Diffuse.a = 0.0;
1908 lightParms.Specular.r = 0.0;
1909 lightParms.Specular.g = 0.0;
1910 lightParms.Specular.b = 0.0;
1911 lightParms.Specular.a = 0.0;
1912 lightParms.Ambient.r = 0.0;
1913 lightParms.Ambient.g = 0.0;
1914 lightParms.Ambient.b = 0.0;
1915 lightParms.Ambient.a = 0.0;
1916 lightParms.Position.x = 0.0;
1917 lightParms.Position.y = 0.0;
1918 lightParms.Position.z = 0.0;
1919 lightParms.Direction.x = 0.0;
1920 lightParms.Direction.y = 0.0;
1921 lightParms.Direction.z = 1.0;
1922 lightParms.Range = 0.0;
1923 lightParms.Falloff = 0.0;
1924 lightParms.Attenuation0 = 0.0;
1925 lightParms.Attenuation1 = 0.0;
1926 lightParms.Attenuation2 = 0.0;
1927 lightParms.Theta = 0.0;
1928 lightParms.Phi = 0.0;
1929 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1931 /* Search for it again! Should be fairly quick as near head of list */
1932 lightInfo = This->stateBlock->lights;
1933 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1934 if (lightInfo == NULL) {
1935 FIXME("Adding default lights has failed dismally\n");
1936 return D3DERR_INVALIDCALL;
1940 /* OK, we now have a light... */
1941 if (Enable == FALSE) {
1943 /* If we are disabling it, check it was enabled, and
1944 still only do something if it has assigned a glIndex (which it should have!) */
1945 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1946 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1947 ENTER_GL();
1948 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1949 checkGLcall("glDisable GL_LIGHT0+Index");
1950 LEAVE_GL();
1951 } else {
1952 TRACE("Nothing to do as light was not enabled\n");
1954 lightInfo->lightEnabled = FALSE;
1955 } else {
1957 /* We are enabling it. If it is enabled, it's really simple */
1958 if (lightInfo->lightEnabled) {
1959 /* nop */
1960 TRACE("Nothing to do as light was enabled\n");
1962 /* If it already has a glIndex, it's still simple */
1963 } else if (lightInfo->glIndex != -1) {
1964 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1965 lightInfo->lightEnabled = TRUE;
1966 ENTER_GL();
1967 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1968 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1969 LEAVE_GL();
1971 /* Otherwise got to find space - lights are ordered gl indexes first */
1972 } else {
1973 PLIGHTINFOEL *bsf = NULL;
1974 PLIGHTINFOEL *pos = This->stateBlock->lights;
1975 PLIGHTINFOEL *prev = NULL;
1976 int Index= 0;
1977 int glIndex = -1;
1979 /* Try to minimize changes as much as possible */
1980 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1982 /* Try to remember which index can be replaced if necessary */
1983 if (bsf==NULL && pos->lightEnabled == FALSE) {
1984 /* Found a light we can replace, save as best replacement */
1985 bsf = pos;
1988 /* Step to next space */
1989 prev = pos;
1990 pos = pos->next;
1991 Index ++;
1994 /* If we have too many active lights, fail the call */
1995 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1996 FIXME("Program requests too many concurrent lights\n");
1997 return D3DERR_INVALIDCALL;
1999 /* If we have allocated all lights, but not all are enabled,
2000 reuse one which is not enabled */
2001 } else if (Index == This->maxConcurrentLights) {
2002 /* use bsf - Simply swap the new light and the BSF one */
2003 PLIGHTINFOEL *bsfNext = bsf->next;
2004 PLIGHTINFOEL *bsfPrev = bsf->prev;
2006 /* Sort out ends */
2007 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2008 if (bsf->prev != NULL) {
2009 bsf->prev->next = lightInfo;
2010 } else {
2011 This->stateBlock->lights = lightInfo;
2014 /* If not side by side, lots of chains to update */
2015 if (bsf->next != lightInfo) {
2016 lightInfo->prev->next = bsf;
2017 bsf->next->prev = lightInfo;
2018 bsf->next = lightInfo->next;
2019 bsf->prev = lightInfo->prev;
2020 lightInfo->next = bsfNext;
2021 lightInfo->prev = bsfPrev;
2023 } else {
2024 /* Simple swaps */
2025 bsf->prev = lightInfo;
2026 bsf->next = lightInfo->next;
2027 lightInfo->next = bsf;
2028 lightInfo->prev = bsfPrev;
2032 /* Update states */
2033 glIndex = bsf->glIndex;
2034 bsf->glIndex = -1;
2035 lightInfo->glIndex = glIndex;
2036 lightInfo->lightEnabled = TRUE;
2038 /* Finally set up the light in gl itself */
2039 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2040 ENTER_GL();
2041 setup_light(iface, glIndex, lightInfo);
2042 glEnable(GL_LIGHT0 + glIndex);
2043 checkGLcall("glEnable GL_LIGHT0 new setup");
2044 LEAVE_GL();
2046 /* If we reached the end of the allocated lights, with space in the
2047 gl lights, setup a new light */
2048 } else if (pos->glIndex == -1) {
2050 /* We reached the end of the allocated gl lights, so already
2051 know the index of the next one! */
2052 glIndex = Index;
2053 lightInfo->glIndex = glIndex;
2054 lightInfo->lightEnabled = TRUE;
2056 /* In an ideal world, it's already in the right place */
2057 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2058 /* No need to move it */
2059 } else {
2060 /* Remove this light from the list */
2061 lightInfo->prev->next = lightInfo->next;
2062 if (lightInfo->next != NULL) {
2063 lightInfo->next->prev = lightInfo->prev;
2066 /* Add in at appropriate place (inbetween prev and pos) */
2067 lightInfo->prev = prev;
2068 lightInfo->next = pos;
2069 if (prev == NULL) {
2070 This->stateBlock->lights = lightInfo;
2071 } else {
2072 prev->next = lightInfo;
2074 if (pos != NULL) {
2075 pos->prev = lightInfo;
2079 /* Finally set up the light in gl itself */
2080 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2081 ENTER_GL();
2082 setup_light(iface, glIndex, lightInfo);
2083 glEnable(GL_LIGHT0 + glIndex);
2084 checkGLcall("glEnable GL_LIGHT0 new setup");
2085 LEAVE_GL();
2090 return D3D_OK;
2093 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2095 PLIGHTINFOEL *lightInfo = NULL;
2096 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2097 TRACE("(%p) : for idx(%ld)\n", This, Index);
2099 /* Locate the light in the live lights */
2100 lightInfo = This->stateBlock->lights;
2101 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2103 if (lightInfo == NULL) {
2104 TRACE("Light enabled state requested but light not defined\n");
2105 return D3DERR_INVALIDCALL;
2107 *pEnable = lightInfo->lightEnabled;
2108 return D3D_OK;
2111 /*****
2112 * Get / Set Clip Planes
2113 *****/
2114 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2115 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2116 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2118 /* Validate Index */
2119 if (Index >= GL_LIMITS(clipplanes)) {
2120 TRACE("Application has requested clipplane this device doesn't support\n");
2121 return D3DERR_INVALIDCALL;
2124 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2125 This->updateStateBlock->set.clipplane[Index] = TRUE;
2126 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2127 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2128 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2129 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2131 /* Handle recording of state blocks */
2132 if (This->isRecordingState) {
2133 TRACE("Recording... not performing anything\n");
2134 return D3D_OK;
2137 /* Apply it */
2139 ENTER_GL();
2141 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2142 glMatrixMode(GL_MODELVIEW);
2143 glPushMatrix();
2144 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2146 TRACE("Clipplane [%f,%f,%f,%f]\n",
2147 This->updateStateBlock->clipplane[Index][0],
2148 This->updateStateBlock->clipplane[Index][1],
2149 This->updateStateBlock->clipplane[Index][2],
2150 This->updateStateBlock->clipplane[Index][3]);
2151 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2152 checkGLcall("glClipPlane");
2154 glPopMatrix();
2155 LEAVE_GL();
2157 return D3D_OK;
2160 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2162 TRACE("(%p) : for idx %ld\n", This, Index);
2164 /* Validate Index */
2165 if (Index >= GL_LIMITS(clipplanes)) {
2166 TRACE("Application has requested clipplane this device doesn't support\n");
2167 return D3DERR_INVALIDCALL;
2170 pPlane[0] = This->stateBlock->clipplane[Index][0];
2171 pPlane[1] = This->stateBlock->clipplane[Index][1];
2172 pPlane[2] = This->stateBlock->clipplane[Index][2];
2173 pPlane[3] = This->stateBlock->clipplane[Index][3];
2174 return D3D_OK;
2177 /*****
2178 * Get / Set Clip Plane Status
2179 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2180 *****/
2181 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2182 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2183 FIXME("(%p) : stub\n", This);
2184 if (NULL == pClipStatus) {
2185 return D3DERR_INVALIDCALL;
2187 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2188 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2189 return D3D_OK;
2192 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2194 FIXME("(%p) : stub\n", This);
2195 if (NULL == pClipStatus) {
2196 return D3DERR_INVALIDCALL;
2198 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2199 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2200 return D3D_OK;
2203 /*****
2204 * Get / Set Material
2205 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2206 *****/
2207 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2210 This->updateStateBlock->changed.material = TRUE;
2211 This->updateStateBlock->set.material = TRUE;
2212 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2214 /* Handle recording of state blocks */
2215 if (This->isRecordingState) {
2216 TRACE("Recording... not performing anything\n");
2217 return D3D_OK;
2220 ENTER_GL();
2221 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2222 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2223 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2224 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2225 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2227 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2228 checkGLcall("glMaterialfv");
2229 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2230 checkGLcall("glMaterialfv");
2232 /* Only change material color if specular is enabled, otherwise it is set to black */
2233 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2234 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2235 checkGLcall("glMaterialfv");
2236 } else {
2237 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2238 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2239 checkGLcall("glMaterialfv");
2241 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2242 checkGLcall("glMaterialfv");
2243 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2244 checkGLcall("glMaterialf");
2246 LEAVE_GL();
2247 return D3D_OK;
2250 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2251 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2252 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2253 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2254 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2255 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2256 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2257 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2258 return D3D_OK;
2261 /*****
2262 * Get / Set Indices
2263 *****/
2264 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2265 UINT BaseVertexIndex) {
2266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2267 IWineD3DIndexBuffer *oldIdxs;
2269 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2270 oldIdxs = This->updateStateBlock->pIndexData;
2272 This->updateStateBlock->changed.indices = TRUE;
2273 This->updateStateBlock->set.indices = TRUE;
2274 This->updateStateBlock->pIndexData = pIndexData;
2275 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2277 /* Handle recording of state blocks */
2278 if (This->isRecordingState) {
2279 TRACE("Recording... not performing anything\n");
2280 return D3D_OK;
2283 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2284 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2285 return D3D_OK;
2288 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2289 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2291 *ppIndexData = This->stateBlock->pIndexData;
2293 /* up ref count on ppindexdata */
2294 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2295 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2297 return D3D_OK;
2300 /*****
2301 * Get / Set Viewports
2302 *****/
2303 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2306 TRACE("(%p)\n", This);
2307 This->updateStateBlock->changed.viewport = TRUE;
2308 This->updateStateBlock->set.viewport = TRUE;
2309 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2311 /* Handle recording of state blocks */
2312 if (This->isRecordingState) {
2313 TRACE("Recording... not performing anything\n");
2314 return D3D_OK;
2317 ENTER_GL();
2319 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2320 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2322 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2323 checkGLcall("glDepthRange");
2324 /* Note: GL requires lower left, DirectX supplies upper left */
2325 /* TODO: replace usage of renderTarget with context management */
2326 glViewport(pViewport->X, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2327 pViewport->Width, pViewport->Height);
2328 checkGLcall("glViewport");
2330 LEAVE_GL();
2332 return D3D_OK;
2336 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2338 TRACE("(%p)\n", This);
2339 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2340 return D3D_OK;
2343 /*****
2344 * Get / Set Render States
2345 * TODO: Verify against dx9 definitions
2346 *****/
2347 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2350 DWORD OldValue = This->stateBlock->renderState[State];
2352 /* Simple way of referring to either a DWORD or a 4 byte float */
2353 union {
2354 DWORD d;
2355 float f;
2356 } tmpvalue;
2358 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2359 This->updateStateBlock->changed.renderState[State] = TRUE;
2360 This->updateStateBlock->set.renderState[State] = TRUE;
2361 This->updateStateBlock->renderState[State] = Value;
2363 /* Handle recording of state blocks */
2364 if (This->isRecordingState) {
2365 TRACE("Recording... not performing anything\n");
2366 return D3D_OK;
2369 ENTER_GL();
2371 switch (State) {
2372 case WINED3DRS_FILLMODE :
2373 switch ((D3DFILLMODE) Value) {
2374 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2375 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2376 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2377 default:
2378 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2380 checkGLcall("glPolygonMode (fillmode)");
2381 break;
2383 case WINED3DRS_LIGHTING :
2384 if (Value) {
2385 glEnable(GL_LIGHTING);
2386 checkGLcall("glEnable GL_LIGHTING");
2387 } else {
2388 glDisable(GL_LIGHTING);
2389 checkGLcall("glDisable GL_LIGHTING");
2391 break;
2393 case WINED3DRS_ZENABLE :
2394 switch ((D3DZBUFFERTYPE) Value) {
2395 case D3DZB_FALSE:
2396 glDisable(GL_DEPTH_TEST);
2397 checkGLcall("glDisable GL_DEPTH_TEST");
2398 break;
2399 case D3DZB_TRUE:
2400 glEnable(GL_DEPTH_TEST);
2401 checkGLcall("glEnable GL_DEPTH_TEST");
2402 break;
2403 case D3DZB_USEW:
2404 glEnable(GL_DEPTH_TEST);
2405 checkGLcall("glEnable GL_DEPTH_TEST");
2406 FIXME("W buffer is not well handled\n");
2407 break;
2408 default:
2409 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2411 break;
2413 case WINED3DRS_CULLMODE :
2415 /* If we are culling "back faces with clockwise vertices" then
2416 set front faces to be counter clockwise and enable culling
2417 of back faces */
2418 switch ((D3DCULL) Value) {
2419 case D3DCULL_NONE:
2420 glDisable(GL_CULL_FACE);
2421 checkGLcall("glDisable GL_CULL_FACE");
2422 break;
2423 case D3DCULL_CW:
2424 glEnable(GL_CULL_FACE);
2425 checkGLcall("glEnable GL_CULL_FACE");
2426 if (This->renderUpsideDown) {
2427 glFrontFace(GL_CW);
2428 checkGLcall("glFrontFace GL_CW");
2429 } else {
2430 glFrontFace(GL_CCW);
2431 checkGLcall("glFrontFace GL_CCW");
2433 glCullFace(GL_BACK);
2434 break;
2435 case D3DCULL_CCW:
2436 glEnable(GL_CULL_FACE);
2437 checkGLcall("glEnable GL_CULL_FACE");
2438 if (This->renderUpsideDown) {
2439 glFrontFace(GL_CCW);
2440 checkGLcall("glFrontFace GL_CCW");
2441 } else {
2442 glFrontFace(GL_CW);
2443 checkGLcall("glFrontFace GL_CW");
2445 glCullFace(GL_BACK);
2446 break;
2447 default:
2448 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2450 break;
2452 case WINED3DRS_SHADEMODE :
2453 switch ((D3DSHADEMODE) Value) {
2454 case D3DSHADE_FLAT:
2455 glShadeModel(GL_FLAT);
2456 checkGLcall("glShadeModel");
2457 break;
2458 case D3DSHADE_GOURAUD:
2459 glShadeModel(GL_SMOOTH);
2460 checkGLcall("glShadeModel");
2461 break;
2462 case D3DSHADE_PHONG:
2463 FIXME("D3DSHADE_PHONG isn't supported?\n");
2465 LEAVE_GL();
2466 return D3DERR_INVALIDCALL;
2467 default:
2468 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2470 break;
2472 case WINED3DRS_DITHERENABLE :
2473 if (Value) {
2474 glEnable(GL_DITHER);
2475 checkGLcall("glEnable GL_DITHER");
2476 } else {
2477 glDisable(GL_DITHER);
2478 checkGLcall("glDisable GL_DITHER");
2480 break;
2482 case WINED3DRS_ZWRITEENABLE :
2483 if (Value) {
2484 glDepthMask(1);
2485 checkGLcall("glDepthMask");
2486 } else {
2487 glDepthMask(0);
2488 checkGLcall("glDepthMask");
2490 break;
2492 case WINED3DRS_ZFUNC :
2494 int glParm = GL_LESS;
2496 switch ((D3DCMPFUNC) Value) {
2497 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2498 case D3DCMP_LESS: glParm=GL_LESS; break;
2499 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2500 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2501 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2502 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2503 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2504 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2505 default:
2506 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2508 glDepthFunc(glParm);
2509 checkGLcall("glDepthFunc");
2511 break;
2513 case WINED3DRS_AMBIENT :
2515 float col[4];
2516 D3DCOLORTOGLFLOAT4(Value, col);
2517 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2518 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2519 checkGLcall("glLightModel for MODEL_AMBIENT");
2522 break;
2524 case WINED3DRS_ALPHABLENDENABLE :
2525 if (Value) {
2526 glEnable(GL_BLEND);
2527 checkGLcall("glEnable GL_BLEND");
2528 } else {
2529 glDisable(GL_BLEND);
2530 checkGLcall("glDisable GL_BLEND");
2532 break;
2534 case WINED3DRS_SRCBLEND :
2535 case WINED3DRS_DESTBLEND :
2537 int newVal = GL_ZERO;
2538 switch (Value) {
2539 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2540 case D3DBLEND_ONE : newVal = GL_ONE; break;
2541 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2542 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2543 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2544 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2545 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2546 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2547 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2548 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2549 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2551 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2552 This->srcBlend = newVal;
2553 This->dstBlend = newVal;
2554 break;
2556 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2557 This->srcBlend = newVal;
2558 This->dstBlend = newVal;
2559 break;
2560 default:
2561 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2564 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2565 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2566 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2567 glBlendFunc(This->srcBlend, This->dstBlend);
2569 checkGLcall("glBlendFunc");
2571 break;
2573 case WINED3DRS_ALPHATESTENABLE :
2574 if (Value) {
2575 glEnable(GL_ALPHA_TEST);
2576 checkGLcall("glEnable GL_ALPHA_TEST");
2577 } else {
2578 glDisable(GL_ALPHA_TEST);
2579 checkGLcall("glDisable GL_ALPHA_TEST");
2581 break;
2583 case WINED3DRS_ALPHAFUNC :
2585 int glParm = GL_LESS;
2586 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2588 switch ((D3DCMPFUNC) Value) {
2589 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2590 case D3DCMP_LESS: glParm = GL_LESS; break;
2591 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2592 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2593 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2594 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2595 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2596 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2597 default:
2598 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2600 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2601 glAlphaFunc(glParm, ref);
2602 This->alphafunc = glParm;
2603 checkGLcall("glAlphaFunc");
2605 break;
2607 case WINED3DRS_ALPHAREF :
2609 int glParm = This->alphafunc;
2610 float ref = 1.0f;
2612 ref = ((float) Value) / 255.0f;
2613 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2614 glAlphaFunc(glParm, ref);
2615 checkGLcall("glAlphaFunc");
2617 break;
2619 case WINED3DRS_CLIPPLANEENABLE :
2620 case WINED3DRS_CLIPPING :
2622 /* Ensure we only do the changed clip planes */
2623 DWORD enable = 0xFFFFFFFF;
2624 DWORD disable = 0x00000000;
2626 /* If enabling / disabling all */
2627 if (State == WINED3DRS_CLIPPING) {
2628 if (Value) {
2629 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2630 disable = 0x00;
2631 } else {
2632 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2633 enable = 0x00;
2635 } else {
2636 enable = Value & ~OldValue;
2637 disable = ~Value & OldValue;
2640 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2641 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2642 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2643 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2644 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2645 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2647 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2648 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2649 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2650 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2651 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2652 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2654 /** update clipping status */
2655 if (enable) {
2656 This->stateBlock->clip_status.ClipUnion = 0;
2657 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2658 } else {
2659 This->stateBlock->clip_status.ClipUnion = 0;
2660 This->stateBlock->clip_status.ClipIntersection = 0;
2663 break;
2665 case WINED3DRS_BLENDOP :
2667 int glParm = GL_FUNC_ADD;
2669 switch ((D3DBLENDOP) Value) {
2670 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2671 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2672 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2673 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2674 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2675 default:
2676 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2678 TRACE("glBlendEquation(%x)\n", glParm);
2679 glBlendEquation(glParm);
2680 checkGLcall("glBlendEquation");
2682 break;
2684 case WINED3DRS_TEXTUREFACTOR :
2686 unsigned int i;
2688 /* Note the texture color applies to all textures whereas
2689 GL_TEXTURE_ENV_COLOR applies to active only */
2690 float col[4];
2691 D3DCOLORTOGLFLOAT4(Value, col);
2692 /* Set the default alpha blend color */
2693 glBlendColor(col[0], col[1], col[2], col[3]);
2694 checkGLcall("glBlendColor");
2696 /* And now the default texture color as well */
2697 for (i = 0; i < GL_LIMITS(textures); i++) {
2699 /* Note the D3DRS value applies to all textures, but GL has one
2700 per texture, so apply it now ready to be used! */
2701 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2702 GLACTIVETEXTURE(i);
2703 } else if (i>0) {
2704 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2707 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2708 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2711 break;
2713 case WINED3DRS_SPECULARENABLE :
2715 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2716 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2717 specular color. This is wrong:
2718 Separate specular color means the specular colour is maintained separately, whereas
2719 single color means it is merged in. However in both cases they are being used to
2720 some extent.
2721 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2722 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2723 running 1.4 yet!
2725 if (Value) {
2726 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2727 checkGLcall("glMaterialfv");
2728 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2729 glEnable(GL_COLOR_SUM_EXT);
2730 } else {
2731 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2733 checkGLcall("glEnable(GL_COLOR_SUM)");
2734 } else {
2735 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2737 /* for the case of enabled lighting: */
2738 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2739 checkGLcall("glMaterialfv");
2741 /* for the case of disabled lighting: */
2742 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2743 glDisable(GL_COLOR_SUM_EXT);
2744 } else {
2745 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2747 checkGLcall("glDisable(GL_COLOR_SUM)");
2750 break;
2752 case WINED3DRS_STENCILENABLE :
2753 if (Value) {
2754 glEnable(GL_STENCIL_TEST);
2755 checkGLcall("glEnable GL_STENCIL_TEST");
2756 } else {
2757 glDisable(GL_STENCIL_TEST);
2758 checkGLcall("glDisable GL_STENCIL_TEST");
2760 break;
2762 case WINED3DRS_STENCILFUNC :
2764 int glParm = GL_ALWAYS;
2765 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2766 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2768 switch ((D3DCMPFUNC) Value) {
2769 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2770 case D3DCMP_LESS: glParm=GL_LESS; break;
2771 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2772 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2773 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2774 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2775 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2776 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2777 default:
2778 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2780 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2781 This->stencilfunc = glParm;
2782 glStencilFunc(glParm, ref, mask);
2783 checkGLcall("glStencilFunc");
2785 break;
2787 case WINED3DRS_STENCILREF :
2789 int glParm = This->stencilfunc;
2790 int ref = 0;
2791 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2793 ref = Value;
2794 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2795 glStencilFunc(glParm, ref, mask);
2796 checkGLcall("glStencilFunc");
2798 break;
2800 case WINED3DRS_STENCILMASK :
2802 int glParm = This->stencilfunc;
2803 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2804 GLuint mask = Value;
2806 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2807 glStencilFunc(glParm, ref, mask);
2808 checkGLcall("glStencilFunc");
2810 break;
2812 case WINED3DRS_STENCILFAIL :
2814 GLenum fail ;
2815 GLenum zpass ;
2816 GLenum zfail ;
2818 fail = StencilOp(Value);
2819 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2820 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2821 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2822 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2824 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2825 glStencilOp(fail, zfail, zpass);
2826 checkGLcall("glStencilOp(fail, zfail, zpass);");
2828 break;
2829 case WINED3DRS_STENCILZFAIL :
2831 GLenum fail ;
2832 GLenum zpass ;
2833 GLenum zfail ;
2835 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2836 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2837 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2838 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2839 zfail = StencilOp(Value);
2841 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2842 glStencilOp(fail, zfail, zpass);
2843 checkGLcall("glStencilOp(fail, zfail, zpass);");
2845 break;
2846 case WINED3DRS_STENCILPASS :
2848 GLenum fail ;
2849 GLenum zpass ;
2850 GLenum zfail ;
2852 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2853 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2854 zpass = StencilOp(Value);
2855 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2856 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2858 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2859 glStencilOp(fail, zfail, zpass);
2860 checkGLcall("glStencilOp(fail, zfail, zpass);");
2862 break;
2864 case WINED3DRS_STENCILWRITEMASK :
2866 glStencilMask(Value);
2867 TRACE("glStencilMask(%lu)\n", Value);
2868 checkGLcall("glStencilMask");
2870 break;
2872 case WINED3DRS_FOGENABLE :
2874 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2875 glEnable(GL_FOG);
2876 checkGLcall("glEnable GL_FOG");
2877 } else {
2878 glDisable(GL_FOG);
2879 checkGLcall("glDisable GL_FOG");
2882 break;
2884 case WINED3DRS_RANGEFOGENABLE :
2886 if (Value) {
2887 TRACE("Enabled RANGEFOG");
2888 } else {
2889 TRACE("Disabled RANGEFOG");
2892 break;
2894 case WINED3DRS_FOGCOLOR :
2896 float col[4];
2897 D3DCOLORTOGLFLOAT4(Value, col);
2898 /* Set the default alpha blend color */
2899 glFogfv(GL_FOG_COLOR, &col[0]);
2900 checkGLcall("glFog GL_FOG_COLOR");
2902 break;
2904 case WINED3DRS_FOGTABLEMODE :
2906 glHint(GL_FOG_HINT, GL_NICEST);
2907 switch (Value) {
2908 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2909 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2910 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2911 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2912 default:
2913 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2915 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2916 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2919 break;
2921 case WINED3DRS_FOGVERTEXMODE :
2923 glHint(GL_FOG_HINT, GL_FASTEST);
2924 switch (Value) {
2925 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2926 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2927 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2928 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2929 default:
2930 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2932 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2933 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2936 break;
2938 case WINED3DRS_FOGSTART :
2940 tmpvalue.d = Value;
2941 glFogfv(GL_FOG_START, &tmpvalue.f);
2942 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2943 TRACE("Fog Start == %f\n", tmpvalue.f);
2945 break;
2947 case WINED3DRS_FOGEND :
2949 tmpvalue.d = Value;
2950 glFogfv(GL_FOG_END, &tmpvalue.f);
2951 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2952 TRACE("Fog End == %f\n", tmpvalue.f);
2954 break;
2956 case WINED3DRS_FOGDENSITY :
2958 tmpvalue.d = Value;
2959 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2960 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2962 break;
2964 case WINED3DRS_VERTEXBLEND :
2966 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2967 TRACE("Vertex Blending state to %ld\n", Value);
2969 break;
2971 case WINED3DRS_TWEENFACTOR :
2973 tmpvalue.d = Value;
2974 This->updateStateBlock->tween_factor = tmpvalue.f;
2975 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2977 break;
2979 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2981 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2983 break;
2985 case WINED3DRS_COLORVERTEX :
2986 case WINED3DRS_DIFFUSEMATERIALSOURCE :
2987 case WINED3DRS_SPECULARMATERIALSOURCE :
2988 case WINED3DRS_AMBIENTMATERIALSOURCE :
2989 case WINED3DRS_EMISSIVEMATERIALSOURCE :
2991 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2993 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
2994 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2995 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
2996 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
2997 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
2998 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3000 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3001 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3002 Parm = GL_AMBIENT_AND_DIFFUSE;
3003 } else {
3004 Parm = GL_DIFFUSE;
3006 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3007 Parm = GL_AMBIENT;
3008 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3009 Parm = GL_EMISSION;
3010 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3011 Parm = GL_SPECULAR;
3012 } else {
3013 Parm = -1;
3016 if (Parm == -1) {
3017 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3018 } else {
3019 This->tracking_color = NEEDS_TRACKING;
3020 This->tracking_parm = Parm;
3023 } else {
3024 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3027 break;
3029 case WINED3DRS_LINEPATTERN :
3031 union {
3032 DWORD d;
3033 D3DLINEPATTERN lp;
3034 } tmppattern;
3035 tmppattern.d = Value;
3037 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3039 if (tmppattern.lp.wRepeatFactor) {
3040 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3041 checkGLcall("glLineStipple(repeat, linepattern)");
3042 glEnable(GL_LINE_STIPPLE);
3043 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3044 } else {
3045 glDisable(GL_LINE_STIPPLE);
3046 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3049 break;
3051 case WINED3DRS_ZBIAS :
3053 if (Value) {
3054 tmpvalue.d = Value;
3055 TRACE("ZBias value %f\n", tmpvalue.f);
3056 glPolygonOffset(0, -tmpvalue.f);
3057 checkGLcall("glPolygonOffset(0, -Value)");
3058 glEnable(GL_POLYGON_OFFSET_FILL);
3059 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3060 glEnable(GL_POLYGON_OFFSET_LINE);
3061 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3062 glEnable(GL_POLYGON_OFFSET_POINT);
3063 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3064 } else {
3065 glDisable(GL_POLYGON_OFFSET_FILL);
3066 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3067 glDisable(GL_POLYGON_OFFSET_LINE);
3068 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3069 glDisable(GL_POLYGON_OFFSET_POINT);
3070 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3073 break;
3075 case WINED3DRS_NORMALIZENORMALS :
3076 if (Value) {
3077 glEnable(GL_NORMALIZE);
3078 checkGLcall("glEnable(GL_NORMALIZE);");
3079 } else {
3080 glDisable(GL_NORMALIZE);
3081 checkGLcall("glDisable(GL_NORMALIZE);");
3083 break;
3085 case WINED3DRS_POINTSIZE :
3086 tmpvalue.d = Value;
3087 TRACE("Set point size to %f\n", tmpvalue.f);
3088 glPointSize(tmpvalue.f);
3089 checkGLcall("glPointSize(...);");
3090 break;
3092 case WINED3DRS_POINTSIZE_MIN :
3093 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3094 tmpvalue.d = Value;
3095 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3096 checkGLcall("glPointParameterfEXT(...);");
3097 } else {
3098 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3100 break;
3102 case WINED3DRS_POINTSIZE_MAX :
3103 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3104 tmpvalue.d = Value;
3105 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3106 checkGLcall("glPointParameterfEXT(...);");
3107 } else {
3108 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3110 break;
3112 case WINED3DRS_POINTSCALE_A :
3113 case WINED3DRS_POINTSCALE_B :
3114 case WINED3DRS_POINTSCALE_C :
3115 case WINED3DRS_POINTSCALEENABLE :
3117 /* If enabled, supply the parameters, otherwise fall back to defaults */
3118 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3119 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3120 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3121 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3122 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3124 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3125 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3126 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3127 } else {
3128 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3130 } else {
3131 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3132 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3133 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3134 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3135 } else {
3136 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3139 break;
3142 case WINED3DRS_COLORWRITEENABLE :
3144 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3145 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3146 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3147 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3148 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3149 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3150 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3151 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3152 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3153 checkGLcall("glColorMask(...)");
3155 break;
3157 case WINED3DRS_LOCALVIEWER :
3159 GLint state = (Value) ? 1 : 0;
3160 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3161 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3163 break;
3165 case WINED3DRS_LASTPIXEL :
3167 if (Value) {
3168 TRACE("Last Pixel Drawing Enabled\n");
3169 } else {
3170 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3173 break;
3175 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3177 if (Value) {
3178 TRACE("Software Processing Enabled\n");
3179 } else {
3180 TRACE("Software Processing Disabled\n");
3183 break;
3185 /** not supported */
3186 case WINED3DRS_ZVISIBLE :
3188 LEAVE_GL();
3189 return D3DERR_INVALIDCALL;
3192 /* Unhandled yet...! */
3193 case WINED3DRS_EDGEANTIALIAS :
3194 case WINED3DRS_WRAP0 :
3195 case WINED3DRS_WRAP1 :
3196 case WINED3DRS_WRAP2 :
3197 case WINED3DRS_WRAP3 :
3198 case WINED3DRS_WRAP4 :
3199 case WINED3DRS_WRAP5 :
3200 case WINED3DRS_WRAP6 :
3201 case WINED3DRS_WRAP7 :
3202 case WINED3DRS_POINTSPRITEENABLE :
3203 case WINED3DRS_MULTISAMPLEANTIALIAS :
3204 case WINED3DRS_MULTISAMPLEMASK :
3205 case WINED3DRS_PATCHEDGESTYLE :
3206 case WINED3DRS_PATCHSEGMENTS :
3207 case WINED3DRS_DEBUGMONITORTOKEN :
3208 case WINED3DRS_POSITIONORDER :
3209 case WINED3DRS_NORMALORDER :
3210 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3211 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3212 break;
3213 default:
3214 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3217 LEAVE_GL();
3219 return D3D_OK;
3222 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3223 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3224 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3225 *pValue = This->stateBlock->renderState[State];
3226 return D3D_OK;
3229 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value){
3230 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3232 * SetSampler is designed to allow for more than the standard up to 8 textures
3233 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3234 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3236 * http://developer.nvidia.com/object/General_FAQ.html#t6
3238 * There are two new settings for GForce
3239 * the sampler one:
3240 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3241 * and the texture one:
3242 * GL_MAX_TEXTURE_COORDS_ARB.
3243 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3244 ******************/
3245 union {
3246 float f;
3247 DWORD d;
3248 } tmpvalue;
3250 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3252 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > HIGHEST_SAMPLER_STATE || Type < 0){
3253 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), HIGHEST_SAMPLER_STATE, Sampler, Type);
3254 return D3DERR_INVALIDCALL;
3257 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3258 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3259 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3260 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3262 /* Handle recording of state blocks */
3263 if (This->isRecordingState) {
3264 TRACE("Recording... not performing anything\n");
3265 return D3D_OK;
3268 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3269 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3270 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3272 ENTER_GL();
3273 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3274 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3275 GLACTIVETEXTURE(Sampler);
3276 } else if (Sampler > 0) {
3277 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3281 switch (Type) {
3283 case WINED3DSAMP_ADDRESSU : /* 1 */
3284 case WINED3DSAMP_ADDRESSV : /* 2 */
3285 case WINED3DSAMP_ADDRESSW : /* 3 */
3287 GLint wrapParm = GL_REPEAT;
3288 switch (Value) {
3289 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3290 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3291 case D3DTADDRESS_BORDER:
3293 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3294 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3295 } else {
3296 /* FIXME: Not right, but better */
3297 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3298 wrapParm = GL_REPEAT;
3301 break;
3302 case D3DTADDRESS_MIRROR:
3304 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3305 wrapParm = GL_MIRRORED_REPEAT_ARB;
3306 } else {
3307 /* Unsupported in OpenGL pre-1.4 */
3308 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3309 wrapParm = GL_REPEAT;
3312 break;
3313 case D3DTADDRESS_MIRRORONCE:
3315 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3316 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3317 } else {
3318 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3319 wrapParm = GL_REPEAT;
3322 break;
3324 default:
3325 /* This is for the whole context, not just the sampler,
3326 so we should warn if two states are baing set for any given scene */
3327 if (Type!=0)
3328 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3329 wrapParm = GL_REPEAT;
3331 switch (Type) {
3332 case WINED3DSAMP_ADDRESSU:
3333 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3334 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3335 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3336 break;
3337 case WINED3DSAMP_ADDRESSV:
3338 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3339 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3340 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3341 break;
3343 case WINED3DSAMP_ADDRESSW:
3344 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3345 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3346 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3347 break;
3348 default: /* nop */
3349 break; /** stupic compilator */
3352 break;
3354 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3356 float col[4];
3357 D3DCOLORTOGLFLOAT4(Value, col);
3358 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3359 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3360 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3362 break;
3364 case WINED3DSAMP_MAGFILTER : /* 5 */
3366 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3367 GLint realVal = GL_NEAREST;
3369 if (ValueMAG == D3DTEXF_POINT) {
3370 realVal = GL_NEAREST;
3371 } else if (ValueMAG == D3DTEXF_LINEAR) {
3372 realVal = GL_LINEAR;
3373 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3374 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3375 realVal = GL_LINEAR;
3376 } else {
3377 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3378 realVal = GL_NEAREST;
3380 } else {
3381 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3382 realVal = GL_NEAREST;
3384 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3385 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3386 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3388 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3390 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3391 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3392 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3393 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3394 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3397 break;
3399 case WINED3DSAMP_MINFILTER: /* 6 */
3400 case WINED3DSAMP_MIPFILTER: /* 7 */
3402 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3403 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3404 GLint realVal = GL_LINEAR;
3406 if (ValueMIN == D3DTEXF_NONE) {
3407 /* Doesn't really make sense - Windows just seems to disable
3408 mipmapping when this occurs */
3409 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3410 realVal = GL_LINEAR;
3411 } else if (ValueMIN == D3DTEXF_POINT) {
3412 /* GL_NEAREST_* */
3413 if (ValueMIP == D3DTEXF_NONE) {
3414 realVal = GL_NEAREST;
3415 } else if (ValueMIP == D3DTEXF_POINT) {
3416 realVal = GL_NEAREST_MIPMAP_NEAREST;
3417 } else if (ValueMIP == D3DTEXF_LINEAR) {
3418 realVal = GL_NEAREST_MIPMAP_LINEAR;
3419 } else {
3420 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3421 realVal = GL_NEAREST;
3423 } else if (ValueMIN == D3DTEXF_LINEAR) {
3424 /* GL_LINEAR_* */
3425 if (ValueMIP == D3DTEXF_NONE) {
3426 realVal = GL_LINEAR;
3427 } else if (ValueMIP == D3DTEXF_POINT) {
3428 realVal = GL_LINEAR_MIPMAP_NEAREST;
3429 } else if (ValueMIP == D3DTEXF_LINEAR) {
3430 realVal = GL_LINEAR_MIPMAP_LINEAR;
3431 } else {
3432 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3433 realVal = GL_LINEAR;
3435 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3436 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3437 if (ValueMIP == D3DTEXF_NONE) {
3438 realVal = GL_LINEAR_MIPMAP_LINEAR;
3439 } else if (ValueMIP == D3DTEXF_POINT) {
3440 realVal = GL_LINEAR_MIPMAP_NEAREST;
3441 } else if (ValueMIP == D3DTEXF_LINEAR) {
3442 realVal = GL_LINEAR_MIPMAP_LINEAR;
3443 } else {
3444 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3445 realVal = GL_LINEAR;
3447 } else {
3448 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3449 realVal = GL_LINEAR;
3451 } else {
3452 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3453 realVal = GL_LINEAR_MIPMAP_LINEAR;
3456 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3457 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3458 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3460 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3462 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3463 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3464 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3465 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3468 break;
3470 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3472 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3473 tmpvalue.d = Value;
3474 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3475 GL_TEXTURE_LOD_BIAS_EXT,
3476 tmpvalue.f);
3477 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3480 break;
3482 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3485 * Not really the same, but the more apprioprate than nothing
3487 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3488 GL_TEXTURE_BASE_LEVEL,
3489 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3490 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3492 break;
3494 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3496 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3497 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3498 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3499 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3500 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3503 break;
3504 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3505 /* Per texture gamma correction, default 0 */
3506 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3507 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3508 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3509 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3510 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3511 break;
3512 default:
3514 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3516 LEAVE_GL();
3517 return D3D_OK;
3520 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value){
3521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3522 /** TODO: check that sampler is in range **/
3523 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3524 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3525 return D3D_OK;
3529 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect){
3530 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3531 ENTER_GL();
3533 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3534 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3535 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3536 LEAVE_GL();
3537 return D3D_OK;
3540 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect){
3541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3542 GLint scissorBox[4];
3544 ENTER_GL();
3545 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3546 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3547 pRect->left = scissorBox[1];
3548 pRect->top = scissorBox[2];
3549 pRect->right = scissorBox[1] + scissorBox[3];
3550 pRect->bottom = scissorBox[2] + scissorBox[4];
3551 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3552 LEAVE_GL();
3553 return D3D_OK;
3556 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3557 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3559 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3561 IWineD3DVertexDeclaration_AddRef(pDecl);
3562 if (NULL != This->updateStateBlock->vertexDecl) {
3563 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3565 This->updateStateBlock->vertexDecl = pDecl;
3566 This->updateStateBlock->changed.vertexDecl = TRUE;
3567 This->updateStateBlock->set.vertexDecl = TRUE;
3568 return D3D_OK;
3571 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3574 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3576 *ppDecl = This->updateStateBlock->vertexDecl;
3577 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3578 return D3D_OK;
3581 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader){
3582 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3584 static BOOL showFixmes = TRUE;
3586 This->updateStateBlock->vertexShader = pShader;
3587 This->updateStateBlock->changed.vertexShader = TRUE;
3588 This->updateStateBlock->set.vertexShader = TRUE;
3590 if(pShader == NULL){
3591 /* clear down the shader */
3592 TRACE("Clear down the shader\n");
3593 }else{
3594 if(showFixmes){
3595 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3596 showFixmes = FALSE;
3600 return D3D_OK;
3602 /** FIXME: refernece counting? **/
3603 if (pShader == NULL) { /* only valid with non FVF shaders */
3604 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3605 This->updateStateBlock->vertexShader = NULL;
3606 } else {
3607 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3608 This->updateStateBlock->vertexShader = pShader;
3611 This->updateStateBlock->changed.vertexShader = TRUE;
3612 This->updateStateBlock->set.vertexShader = TRUE;
3614 /* Handle recording of state blocks */
3615 if (This->isRecordingState) {
3616 TRACE("Recording... not performing anything\n");
3617 return D3D_OK;
3620 * TODO: merge HAL shaders context switching from prototype
3622 return D3D_OK;
3626 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader){
3627 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3628 *ppShader = This->stateBlock->vertexShader;
3629 if(*ppShader != NULL)
3630 IWineD3DVertexShader_AddRef(*ppShader);
3631 TRACE("(%p) : returning %p\n", This, *ppShader);
3632 return D3D_OK;
3635 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3636 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3638 TRACE("(%p) : stub\n", This);
3639 return D3D_OK;
3642 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3644 TRACE("(%p) : stub\n", This);
3645 return D3D_OK;
3648 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3650 TRACE("(%p) : stub\n", This);
3651 return D3D_OK;
3654 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3656 TRACE("(%p) : stub\n", This);
3657 return D3D_OK;
3660 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3661 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3662 TRACE("(%p) : stub\n", This);
3663 return D3D_OK;
3666 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3668 TRACE("(%p) : stub\n", This);
3669 return D3D_OK;
3672 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader){
3673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3674 TRACE("(%p) : stub\n", This);
3675 return D3D_OK;
3678 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader){
3679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3680 TRACE("(%p) : stub\n", This);
3681 return D3D_OK;
3685 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount){
3686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3687 TRACE("(%p) : stub\n", This);
3688 return D3D_OK;
3691 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount){
3692 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3693 TRACE("(%p) : stub\n", This);
3694 return D3D_OK;
3697 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount){
3698 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3699 TRACE("(%p) : stub\n", This);
3700 return D3D_OK;
3703 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount){
3704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3705 TRACE("(%p) : stub\n", This);
3706 return D3D_OK;
3709 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount){
3710 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3711 TRACE("(%p) : stub\n", This);
3712 return D3D_OK;
3715 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount){
3716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3717 TRACE("(%p) : stub\n", This);
3718 return D3D_OK;
3721 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags){
3722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3723 FIXME("(%p) : stub\n", This);
3724 return D3D_OK;
3727 /*****
3728 * Get / Set Texture Stage States
3729 * TODO: Verify against dx9 definitions
3730 *****/
3731 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3734 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3736 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3738 /* Reject invalid texture units */
3739 if (Stage >= GL_LIMITS(textures)) {
3740 TRACE("Attempt to access invalid texture rejected\n");
3741 return D3DERR_INVALIDCALL;
3744 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3745 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3746 This->updateStateBlock->textureState[Stage][Type] = Value;
3748 /* Handle recording of state blocks */
3749 if (This->isRecordingState) {
3750 TRACE("Recording... not performing anything\n");
3751 return D3D_OK;
3754 ENTER_GL();
3756 /* Make appropriate texture active */
3757 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3758 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3759 GLACTIVETEXTURE(Stage);
3760 } else if (Stage > 0) {
3761 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3764 switch (Type) {
3765 case WINED3DTSS_ALPHAOP :
3766 case WINED3DTSS_COLOROP :
3769 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3770 /* TODO: Disable by making this and all later levels disabled */
3771 glDisable(GL_TEXTURE_1D);
3772 checkGLcall("Disable GL_TEXTURE_1D");
3773 glDisable(GL_TEXTURE_2D);
3774 checkGLcall("Disable GL_TEXTURE_2D");
3775 glDisable(GL_TEXTURE_3D);
3776 checkGLcall("Disable GL_TEXTURE_3D");
3777 break; /* Don't bother setting the texture operations */
3778 } else {
3779 /* Enable only the appropriate texture dimension */
3780 if (Type == WINED3DTSS_COLOROP) {
3781 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3782 glEnable(GL_TEXTURE_1D);
3783 checkGLcall("Enable GL_TEXTURE_1D");
3784 } else {
3785 glDisable(GL_TEXTURE_1D);
3786 checkGLcall("Disable GL_TEXTURE_1D");
3788 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3789 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3790 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3791 checkGLcall("Enable GL_TEXTURE_2D");
3792 } else {
3793 glEnable(GL_TEXTURE_2D);
3794 checkGLcall("Enable GL_TEXTURE_2D");
3796 } else {
3797 glDisable(GL_TEXTURE_2D);
3798 checkGLcall("Disable GL_TEXTURE_2D");
3800 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3801 glEnable(GL_TEXTURE_3D);
3802 checkGLcall("Enable GL_TEXTURE_3D");
3803 } else {
3804 glDisable(GL_TEXTURE_3D);
3805 checkGLcall("Disable GL_TEXTURE_3D");
3807 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3808 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3809 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3810 } else {
3811 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3812 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3816 /* Drop through... (Except disable case) */
3817 case WINED3DTSS_COLORARG0 :
3818 case WINED3DTSS_COLORARG1 :
3819 case WINED3DTSS_COLORARG2 :
3820 case WINED3DTSS_ALPHAARG0 :
3821 case WINED3DTSS_ALPHAARG1 :
3822 case WINED3DTSS_ALPHAARG2 :
3824 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3825 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3826 if (isAlphaArg) {
3827 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3828 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3829 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3830 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3831 } else {
3832 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3833 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3834 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3835 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3838 break;
3841 case WINED3DTSS_ADDRESSW :
3843 GLint wrapParm = GL_REPEAT;
3845 switch (Value) {
3846 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3847 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3848 case D3DTADDRESS_BORDER:
3850 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3851 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3852 } else {
3853 /* FIXME: Not right, but better */
3854 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3855 wrapParm = GL_REPEAT;
3858 break;
3859 case D3DTADDRESS_MIRROR:
3861 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3862 wrapParm = GL_MIRRORED_REPEAT_ARB;
3863 } else {
3864 /* Unsupported in OpenGL pre-1.4 */
3865 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3866 wrapParm = GL_REPEAT;
3869 break;
3870 case D3DTADDRESS_MIRRORONCE:
3872 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3873 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3874 } else {
3875 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3876 wrapParm = GL_REPEAT;
3879 break;
3881 default:
3882 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3883 wrapParm = GL_REPEAT;
3886 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3887 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3888 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3890 break;
3892 case WINED3DTSS_TEXCOORDINDEX :
3894 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3896 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3897 one flag, you can still specify an index value, which the system uses to
3898 determine the texture wrapping mode.
3899 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3900 means use the vertex position (camera-space) as the input texture coordinates
3901 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3902 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3903 to the TEXCOORDINDEX value */
3905 /**
3906 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3908 switch (Value & 0xFFFF0000) {
3909 case D3DTSS_TCI_PASSTHRU:
3910 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3911 glDisable(GL_TEXTURE_GEN_S);
3912 glDisable(GL_TEXTURE_GEN_T);
3913 glDisable(GL_TEXTURE_GEN_R);
3914 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3915 break;
3917 case D3DTSS_TCI_CAMERASPACEPOSITION:
3918 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3919 as the input texture coordinates for this stage's texture transformation. This
3920 equates roughly to EYE_LINEAR */
3922 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3923 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3924 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3925 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3926 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3928 glMatrixMode(GL_MODELVIEW);
3929 glPushMatrix();
3930 glLoadIdentity();
3931 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3932 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3933 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3934 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3935 glPopMatrix();
3937 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3938 glEnable(GL_TEXTURE_GEN_S);
3939 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3940 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3941 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3942 glEnable(GL_TEXTURE_GEN_T);
3943 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3944 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3945 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3946 glEnable(GL_TEXTURE_GEN_R);
3947 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3948 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3949 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3951 break;
3953 case D3DTSS_TCI_CAMERASPACENORMAL:
3955 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3956 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3957 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3958 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3959 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3960 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3962 glMatrixMode(GL_MODELVIEW);
3963 glPushMatrix();
3964 glLoadIdentity();
3965 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3966 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3967 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3968 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3969 glPopMatrix();
3971 glEnable(GL_TEXTURE_GEN_S);
3972 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3973 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3974 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3975 glEnable(GL_TEXTURE_GEN_T);
3976 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3977 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3978 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3979 glEnable(GL_TEXTURE_GEN_R);
3980 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3981 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3982 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3985 break;
3987 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3989 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3990 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3991 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3992 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3993 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3994 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3996 glMatrixMode(GL_MODELVIEW);
3997 glPushMatrix();
3998 glLoadIdentity();
3999 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4000 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4001 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4002 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4003 glPopMatrix();
4005 glEnable(GL_TEXTURE_GEN_S);
4006 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4007 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4008 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4009 glEnable(GL_TEXTURE_GEN_T);
4010 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4011 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4012 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4013 glEnable(GL_TEXTURE_GEN_R);
4014 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4015 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4016 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4019 break;
4021 /* Unhandled types: */
4022 default:
4023 /* Todo: */
4024 /* ? disable GL_TEXTURE_GEN_n ? */
4025 glDisable(GL_TEXTURE_GEN_S);
4026 glDisable(GL_TEXTURE_GEN_T);
4027 glDisable(GL_TEXTURE_GEN_R);
4028 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4029 break;
4032 break;
4034 /* Unhandled */
4035 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4036 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
4037 break;
4039 case WINED3DTSS_BUMPENVMAT00 :
4040 case WINED3DTSS_BUMPENVMAT01 :
4041 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4042 break;
4043 case WINED3DTSS_BUMPENVMAT10 :
4044 case WINED3DTSS_BUMPENVMAT11 :
4045 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4046 break;
4048 case WINED3DTSS_BUMPENVLSCALE :
4049 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4050 break;
4052 case WINED3DTSS_BUMPENVLOFFSET :
4053 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4054 break;
4056 case WINED3DTSS_RESULTARG :
4057 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4058 break;
4060 default:
4061 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4062 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4065 LEAVE_GL();
4067 return D3D_OK;
4070 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4072 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4073 *pValue = This->updateStateBlock->textureState[Stage][Type];
4074 return D3D_OK;
4077 /*****
4078 * Get / Set Texture
4079 *****/
4080 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4082 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4083 IWineD3DBaseTexture *oldTexture;
4084 BOOL reapplyStates = TRUE;
4085 DWORD reapplyFlags = 0;
4086 INT oldTextureDimensions = -1;
4087 D3DRESOURCETYPE textureType;
4089 oldTexture = This->updateStateBlock->textures[Stage];
4090 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4092 /* Reject invalid texture units */
4093 if (Stage >= GL_LIMITS(textures)) {
4094 TRACE("Attempt to access invalid texture rejected\n");
4095 return D3DERR_INVALIDCALL;
4098 This->updateStateBlock->set.textures[Stage] = TRUE;
4099 This->updateStateBlock->changed.textures[Stage] = TRUE;
4100 This->updateStateBlock->textures[Stage] = pTexture;
4102 /* Handle recording of state blocks */
4103 if (This->isRecordingState) {
4104 TRACE("Recording... not performing anything\n");
4105 return D3D_OK;
4108 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4110 ENTER_GL();
4112 /* Make appropriate texture active */
4113 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4114 GLACTIVETEXTURE(Stage);
4116 } else if (Stage>0) {
4117 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4120 /** NOTE: MSDN says that setTexture increases the reference count,
4121 * and the the application nust set the texture back to null (or have a leaky application),
4122 * This means we should pass the refcount upto the parent
4123 *******************************/
4124 if (NULL != oldTexture) {
4126 IUnknown *textureParent;
4127 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4128 IUnknown_Release(textureParent);
4129 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4130 oldTexture = NULL;
4134 if (NULL != pTexture) {
4135 IUnknown *textureParent;
4136 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4137 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4139 /* Now setup the texture appropraitly */
4140 textureType = IWineD3DBaseTexture_GetType(pTexture);
4142 if (textureType == D3DRTYPE_TEXTURE) {
4144 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4145 TRACE("Skipping setting texture as old == new\n");
4146 reapplyStates = FALSE;
4148 } else {
4150 /* Standard 2D texture */
4151 TRACE("Standard 2d texture\n");
4152 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4154 /* Load up the texture now */
4155 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4158 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4160 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4161 TRACE("Skipping setting texture as old == new\n");
4162 reapplyStates = FALSE;
4164 } else {
4166 /* Standard 3D (volume) texture */
4167 TRACE("Standard 3d texture\n");
4168 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4170 /* Load up the texture now */
4171 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4174 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4176 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4177 TRACE("Skipping setting texture as old == new\n");
4178 reapplyStates = FALSE;
4180 } else {
4182 /* Standard Cube texture */
4183 TRACE("Standard Cube texture\n");
4184 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4186 /* Load up the texture now */
4187 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4190 } else {
4191 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4194 } else {
4196 TRACE("Setting to no texture (ie default texture)\n");
4197 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4198 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4199 checkGLcall("glBindTexture");
4200 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4203 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4204 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4206 glDisable(oldTextureDimensions);
4207 checkGLcall("Disable oldTextureDimensions");
4209 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4210 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4211 checkGLcall("glEnable new texture dimensions");
4214 /* If Alpha arg1 is texture then handle the special case when there changes between a
4215 texture and no texture - See comments in set_tex_op */
4216 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4217 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4219 reapplyFlags |= REAPPLY_ALPHAOP;
4224 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4225 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4226 if (reapplyStates) {
4227 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4230 LEAVE_GL();
4231 TRACE("Texture now fully setup\n");
4233 return D3D_OK;
4236 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4237 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4238 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4239 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4240 if (*ppTexture)
4241 IWineD3DBaseTexture_AddRef(*ppTexture);
4242 return D3D_OK;
4245 /*****
4246 * Get Back Buffer
4247 *****/
4248 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4249 IWineD3DSurface** ppBackBuffer) {
4250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4251 IWineD3DSwapChain *swapChain;
4252 HRESULT hr;
4254 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4256 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4257 if(hr == D3D_OK){
4258 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4259 IWineD3DSwapChain_Release(swapChain);
4260 }else{
4261 *ppBackBuffer = NULL;
4263 return hr;
4266 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4267 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4268 WARN("(%p) : stub, calling idirect3d for now\n", This);
4269 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4272 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4273 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4274 IWineD3DSwapChain *swapChain;
4275 HRESULT hr;
4277 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4278 if (hr == D3D_OK) {
4279 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4280 IWineD3DSwapChain_Release(swapChain);
4281 }else{
4282 FIXME("(%p) Error getting display mode\n", This);
4284 return hr;
4286 /*****
4287 * Stateblock related functions
4288 *****/
4290 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4291 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4292 IWineD3DStateBlockImpl *object;
4293 TRACE("(%p)", This);
4294 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4295 if(NULL == object ){
4296 FIXME("(%p)Error allocating memory for stateblock\n", This);
4297 return E_OUTOFMEMORY;
4299 TRACE("(%p) creted object %p\n", This, object);
4300 object->wineD3DDevice= This;
4301 /** FIXME: object->parent = parent; **/
4302 object->parent = NULL;
4303 object->blockType = D3DSBT_ALL;
4304 object->ref = 1;
4305 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4307 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4308 This->updateStateBlock = object;
4309 This->isRecordingState = TRUE;
4311 TRACE("(%p) recording stateblock %p\n",This , object);
4312 return D3D_OK;
4315 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4318 if (!This->isRecordingState) {
4319 FIXME("(%p) not recording! returning error\n", This);
4320 *ppStateBlock = NULL;
4321 return D3DERR_INVALIDCALL;
4324 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4325 This->isRecordingState = FALSE;
4326 This->updateStateBlock = This->stateBlock;
4327 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4328 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4329 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4330 return D3D_OK;
4333 /*****
4334 * Scene related functions
4335 *****/
4336 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4337 /* At the moment we have no need for any functionality at the beginning
4338 of a scene */
4339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340 TRACE("(%p) : stub\n", This);
4341 return D3D_OK;
4344 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4345 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4346 TRACE("(%p)\n", This);
4347 ENTER_GL();
4348 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4349 glFlush();
4350 checkGLcall("glFlush");
4352 TRACE("End Scene\n");
4353 if(This->renderTarget != NULL){
4355 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4356 IUnknown *targetContainer = NULL;
4357 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
4358 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4359 /** always dirtify for now. we must find a better way to see that surface have been modified
4360 (Modifications should will only occur via draw-primitive, but we do need better locking
4361 switching to render-to-texture should remove the overhead though.
4363 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4364 IWineD3DBaseTexture_SetDirty((IWineD3DBaseTexture *)targetContainer, TRUE);
4365 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *)targetContainer);
4366 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4367 IUnknown_Release(targetContainer);
4368 } else
4369 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)){
4370 /* The surface is stand-alone, so doesn't currently have a context of it's own */
4371 TRACE("(%p) : standalone rendertarget %p\n", This, This->renderTarget);
4372 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4373 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4374 IWineD3DSurface_PreLoad(This->renderTarget);
4375 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4376 IUnknown_Release(targetContainer);
4381 LEAVE_GL();
4382 return D3D_OK;
4385 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4386 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4387 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4388 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4389 IWineD3DSwapChain *swapChain = NULL;
4390 int i;
4391 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4393 TRACE("(%p) Presenting the frame\n", This);
4395 for(i = 0 ; i < swapchains ; i ++){
4397 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4398 TRACE("presentinng chain %d, %p\n", i, swapChain);
4399 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4400 IWineD3DSwapChain_Release(swapChain);
4403 return D3D_OK;
4406 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4407 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4410 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4411 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4412 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4413 GLbitfield glMask = 0;
4414 GLboolean old_ztest;
4415 GLfloat old_z_clear_value;
4416 GLint old_stencil_clear_value;
4417 GLfloat old_color_clear_value[4];
4418 unsigned int i;
4419 CONST D3DRECT* curRect;
4421 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4422 Count, pRects, Flags, Z, Stencil);
4424 ENTER_GL();
4426 glEnable(GL_SCISSOR_TEST);
4427 checkGLcall("glEnable GL_SCISSOR_TEST");
4429 if (Count > 0 && pRects) {
4430 curRect = pRects;
4431 } else {
4432 curRect = NULL;
4435 /* Only set the values up once, as they are not changing */
4436 if (Flags & D3DCLEAR_STENCIL) {
4437 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4438 glClearStencil(Stencil);
4439 checkGLcall("glClearStencil");
4440 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4441 glStencilMask(0xFFFFFFFF);
4444 if (Flags & D3DCLEAR_ZBUFFER) {
4445 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4446 glDepthMask(GL_TRUE);
4447 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4448 glClearDepth(Z);
4449 checkGLcall("glClearDepth");
4450 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4453 if (Flags & D3DCLEAR_TARGET) {
4454 TRACE("Clearing screen with glClear to color %lx\n", Color);
4455 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4456 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4457 ((Color >> 8) & 0xFF) / 255.0f,
4458 ((Color >> 0) & 0xFF) / 255.0f,
4459 ((Color >> 24) & 0xFF) / 255.0f);
4460 checkGLcall("glClearColor");
4462 /* Clear ALL colors! */
4463 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4464 glMask = glMask | GL_COLOR_BUFFER_BIT;
4467 /* Now process each rect in turn */
4468 for (i = 0; i < Count || i == 0; i++) {
4470 if (curRect) {
4471 /* Note gl uses lower left, width/height */
4472 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4473 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4474 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4475 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4476 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4477 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4478 checkGLcall("glScissor");
4479 } else {
4480 glScissor(This->stateBlock->viewport.X,
4481 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4482 This->stateBlock->viewport.Width,
4483 This->stateBlock->viewport.Height);
4484 checkGLcall("glScissor");
4487 /* Clear the selected rectangle (or full screen) */
4488 glClear(glMask);
4489 checkGLcall("glClear");
4491 /* Step to the next rectangle */
4492 if (curRect) curRect = curRect + sizeof(D3DRECT);
4495 /* Restore the old values (why..?) */
4496 if (Flags & D3DCLEAR_STENCIL) {
4497 glClearStencil(old_stencil_clear_value);
4498 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4500 if (Flags & D3DCLEAR_ZBUFFER) {
4501 glDepthMask(old_ztest);
4502 glClearDepth(old_z_clear_value);
4504 if (Flags & D3DCLEAR_TARGET) {
4505 glClearColor(old_color_clear_value[0],
4506 old_color_clear_value[1],
4507 old_color_clear_value[2],
4508 old_color_clear_value[3]);
4509 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4510 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4511 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4512 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4515 glDisable(GL_SCISSOR_TEST);
4516 checkGLcall("glDisable");
4517 LEAVE_GL();
4519 return D3D_OK;
4522 /*****
4523 * Drawing functions
4524 *****/
4525 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4526 UINT PrimitiveCount) {
4528 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4529 This->stateBlock->streamIsUP = FALSE;
4531 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4532 debug_d3dprimitivetype(PrimitiveType),
4533 StartVertex, PrimitiveCount);
4534 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4536 return D3D_OK;
4539 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4540 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4541 D3DPRIMITIVETYPE PrimitiveType,
4542 INT baseVIndex, UINT minIndex,
4543 UINT NumVertices,UINT startIndex,UINT primCount) {
4545 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4546 UINT idxStride = 2;
4547 IWineD3DIndexBuffer *pIB;
4548 D3DINDEXBUFFER_DESC IdxBufDsc;
4550 pIB = This->stateBlock->pIndexData;
4551 This->stateBlock->streamIsUP = FALSE;
4553 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4554 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4555 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4557 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4558 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4559 idxStride = 2;
4560 } else {
4561 idxStride = 4;
4564 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4565 startIndex, idxStride,
4566 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4567 minIndex);
4569 return D3D_OK;
4572 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4573 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4574 UINT VertexStreamZeroStride) {
4575 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4577 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4578 debug_d3dprimitivetype(PrimitiveType),
4579 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4581 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4583 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4584 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4585 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4586 This->stateBlock->streamIsUP = TRUE;
4587 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4588 This->stateBlock->streamStride[0] = 0;
4589 This->stateBlock->streamSource[0] = NULL;
4591 /*stream zero settings set to null at end, as per the msdn */
4592 return D3D_OK;
4595 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4596 UINT MinVertexIndex,
4597 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4598 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4599 UINT VertexStreamZeroStride) {
4600 int idxStride;
4601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4603 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4604 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4605 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4606 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4608 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4610 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4611 idxStride = 2;
4612 } else {
4613 idxStride = 4;
4616 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4617 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4618 This->stateBlock->streamIsUP = TRUE;
4619 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4621 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4623 /* stream zero settings set to null at end as per the msdn */
4624 This->stateBlock->streamSource[0] = NULL;
4625 This->stateBlock->streamStride[0] = 0;
4626 IWineD3DDevice_SetIndices(iface, NULL, 0);
4628 return D3D_OK;
4631 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4632 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4634 TRACE("(%p) : stub\n", This);
4635 return D3D_OK;
4638 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4639 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4640 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4641 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4643 TRACE("(%p) : stub\n", This);
4644 return D3D_OK;
4646 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface){
4647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4649 TRACE("(%p) : stub\n", This);
4650 return D3D_OK;
4653 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface){
4654 IWineD3DSwapChain *swapChain;
4655 HRESULT hr;
4656 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4657 if(hr == D3D_OK){
4658 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4659 IWineD3DSwapChain_Release(swapChain);
4661 return hr;
4664 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4666 /* return a sensible default */
4667 *pNumPasses = 1;
4668 FIXME("(%p) : stub\n", This);
4669 return D3D_OK;
4672 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4673 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4674 FIXME("(%p) : stub\n", This);
4675 return D3D_OK;
4678 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4680 FIXME("(%p) : stub\n", This);
4681 return D3D_OK;
4684 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4685 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4686 FIXME("(%p) : stub\n", This);
4687 return D3D_OK;
4690 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4691 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4692 FIXME("(%p) : stub\n", This);
4693 return D3D_OK;
4696 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4698 FIXME("(%p) : stub\n", This);
4699 return D3D_OK;
4703 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4705 FIXME("(%p) : stub\n", This);
4706 return FALSE;
4710 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4713 pRasterStatus->InVBlank = TRUE;
4714 pRasterStatus->ScanLine = 0;
4715 FIXME("(%p) : stub\n", This);
4716 return D3D_OK;
4720 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4721 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4722 static BOOL showfixmes = TRUE;
4723 if(nSegments != 0.0f){
4724 if( showfixmes){
4725 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4726 showfixmes = FALSE;
4729 return D3D_OK;
4732 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4733 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4734 static BOOL showfixmes = TRUE;
4735 if( showfixmes){
4736 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4737 showfixmes = FALSE;
4739 return 0.0f;
4743 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4745 FIXME("(%p) : stub\n", This);
4746 return D3D_OK;
4750 /* Implementation details at http://developer.nvidia.com/attach/6494
4752 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4753 hmm.. no longer supported use
4754 OpenGL evaluators or tessellate surfaces within your application.
4757 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4758 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo){
4759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4760 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4761 FIXME("(%p) : Stub\n", This);
4762 return D3D_OK;
4766 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4767 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo){
4768 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4769 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4770 FIXME("(%p) : Stub\n", This);
4771 return D3D_OK;
4774 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle){
4775 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4776 TRACE("(%p) Handle(%d)\n", This, Handle);
4777 FIXME("(%p) : Stub\n", This);
4778 return D3D_OK;
4781 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color){
4782 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4784 FIXME("(%p) : stub\n", This);
4785 return D3D_OK;
4788 /* rendertarget and deptth stencil functions */
4789 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget){
4790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4792 /* FIXME: Implelent RenderTargetIndex >0 */
4793 if(RenderTargetIndex > 0)
4794 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
4796 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
4797 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4798 /* Note inc ref on returned surface */
4799 if(*ppRenderTarget != NULL)
4800 IWineD3DSurface_AddRef(*ppRenderTarget);
4801 return D3D_OK;
4804 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface){
4805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4806 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
4807 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4809 if(*ppZStencilSurface != NULL){
4810 /* Note inc ref on returned surface */
4811 IWineD3DSurface_AddRef(*ppZStencilSurface);
4813 return D3D_OK;
4816 /* internal static helper functions */
4817 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4818 IWineD3DSurface *RenderSurface);
4820 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
4822 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget){
4823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4824 HRESULT hr = D3D_OK;
4825 WINED3DVIEWPORT viewport;
4827 TRACE("(%p) Swapping rendertarget\n",This);
4828 if (RenderTargetIndex>0) {
4829 FIXME("(%p) Render targets other than the first are not supported\n",This);
4830 RenderTargetIndex=0;
4833 /* MSDN says that null disables the render target
4834 but a device must always be associatated with a render target
4835 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
4837 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
4838 for more details
4840 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
4841 FIXME("Trying to set render target 0 to NULL\n");
4842 return D3DERR_INVALIDCALL;
4844 /* TODO: raplce Impl* usage with interface usage */
4845 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
4846 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
4847 return D3DERR_INVALIDCALL;
4849 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
4850 * builds, but I think wine counts as a 'debug' build for now.
4851 ******************************/
4852 /* If we are trying to set what we already have, don't bother */
4853 if (pRenderTarget == This->renderTarget) {
4854 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4855 } else {
4856 /* Otherwise, set the render target up */
4857 TRACE("clearing renderer\n");
4858 /* IWineD3DDeviceImpl_CleanRender(iface); */
4859 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4860 depending on the renter target implemenattion being used.
4861 A shared context implementation will share all buffers between all rendertargets (including swapchains),
4862 implemenations that use serperate pbuffers for different swapchains or rendertargets will have to duplicate the
4863 stencil buffer and incure an extra memory overhead */
4864 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
4867 if (SUCCEEDED(hr)) {
4868 /* Finally, reset the viewport as the MSDN states. */
4869 /* TODO: Repalace impl usage */
4870 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
4871 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
4872 viewport.X = 0;
4873 viewport.Y = 0;
4874 viewport.MaxZ = 1.0f;
4875 viewport.MinZ = 0.0f;
4876 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
4877 }else{
4878 FIXME("Unknown error setting the render target\n");
4880 return hr;
4883 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil){
4884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4885 HRESULT hr = D3D_OK;
4886 WINED3DVIEWPORT viewport;
4887 IWineD3DSurface *tmp;
4889 TRACE("(%p) Swapping z-buffer\n",This);
4891 if (pNewZStencil == This->stencilBufferTarget){
4892 TRACE("Trying to do a NOP SetRenderTarget operation\n");
4893 }else{
4894 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
4895 * depending on the renter target implemenattion being used.
4896 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
4897 * implemenations that use serperate pbuffers for different swapchains or rendertargets will have to duplicate the
4898 * stencil buffer and incure an extra memory overhead
4899 ******************************************************/
4902 tmp = This->stencilBufferTarget;
4903 This->stencilBufferTarget = pNewZStencil;
4904 /* should we be calling the parent or the wined3d surface? */
4905 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
4906 if (NULL != tmp) IWineD3DSurface_Release(tmp);
4907 hr = D3D_OK;
4908 /** TODO: glEnable/glDisable on depth/stencil depending on
4909 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
4910 **********************************************************/
4913 if (SUCCEEDED(hr)) {
4914 /* Finally, reset the viewport as the MSDN states.*/
4915 /* TODO: get ridd of Impl usage */
4916 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
4917 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
4918 viewport.X = 0;
4919 viewport.Y = 0;
4920 viewport.MaxZ = 1.0f;
4921 viewport.MinZ = 0.0f;
4922 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
4925 return hr;
4929 /* Internal functions not in DirectX */
4930 /** TODO: move this off to the opengl context manager
4931 *(the swapchain doesn't need to know anything about offscreen rendering!)
4932 ****************************************************/
4934 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
4936 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4937 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4939 TRACE("(%p), %p\n", This, swapchain);
4941 if (swapchain->win != swapchain->drawable) {
4942 ENTER_GL();
4943 if (swapchain->glCtx != swapchain->render_ctx) {
4944 FIXME("Destroying context %p \n", swapchain->render_ctx);
4945 glXDestroyContext(swapchain->display, swapchain->render_ctx);
4948 FIXME("glXDestroyPbuffer %ld \n", swapchain->drawable);
4949 glXDestroyPbuffer(swapchain->display, swapchain->drawable);
4950 #endif
4951 LEAVE_GL();
4952 /* Set everything back to the way that it ws */
4953 swapchain->render_ctx = swapchain->glCtx;
4954 swapchain->drawable = swapchain->win;
4956 return D3D_OK;
4959 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
4960 * the functiolaity needs splitting up so that we don't do more than we should do.
4961 * this only seems to affect performance a little.
4962 ******************************/
4963 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
4964 IWineD3DSurface *RenderSurface) {
4965 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4966 #ifndef USE_RENDER_MANAGER
4968 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
4969 HRESULT ret = D3DERR_INVALIDCALL;
4971 * Currently only active for GLX >= 1.3
4972 * for others versions we'll have to use GLXPixmaps
4974 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4975 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4976 * so only check OpenGL version
4977 * ..........................
4978 * I don't belive that it is a problem with NVidia headers,
4979 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
4980 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
4981 * ATI Note:
4982 * Your application will report GLX version 1.2 on glXQueryVersion.
4983 * However, it is safe to call the GLX 1.3 functions as described below.
4985 #if defined(GL_VERSION_1_3)
4987 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
4988 GLXFBConfig* cfgs = NULL;
4989 int nCfgs = 0;
4990 int attribs[256];
4991 int nAttribs = 0;
4992 IWineD3DSwapChain *currentSwapchain;
4993 IWineD3DSwapChainImpl *swapchain;
4994 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if pussible,
4995 * but switch them off if the StencilSurface is set to NULL
4996 ** *********************************************************/
4997 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
4998 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
4999 #if 0
5000 UINT Width = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Width;
5001 UINT Height = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Height;
5002 #endif
5003 IWineD3DSurface *tmp;
5005 /**TODO:
5006 if StencilSurface == NULL && zBufferTarget != NULL then swtich the zbuffer off,
5007 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5010 #define PUSH1(att) attribs[nAttribs++] = (att);
5011 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5013 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5015 /** TODO: remove the reff to Impl (context manager should fis this!) **/
5016 IWineD3DSwapChainImpl *impSwapChain;
5017 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5018 if (NULL == impSwapChain){ /* NOTE: This should NEVER fail */
5019 ERR("(%p) Failed to get a the implicite swapchain\n", iface);
5022 ENTER_GL();
5024 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5025 PUSH2(GLX_X_RENDERABLE, TRUE);
5026 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5027 TRACE("calling makeglcfg\n");
5028 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5030 PUSH1(None);
5033 TRACE("calling chooseFGConfig\n");
5034 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5035 attribs, &nCfgs);
5037 if (!cfgs){ /* OK we didn't find the exact config, so use any reasonably match */
5038 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5039 why we failed and only show this message once! */
5040 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
5041 nAttribs = 0;
5042 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5043 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5044 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5045 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5046 TRACE("calling makeglcfg\n");
5047 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5048 PUSH1(None);
5049 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5050 attribs, &nCfgs);
5053 #if 0
5054 #ifdef EXTRA_TRACES
5055 int i;
5056 for (i = 0; i < nCfgs; ++i) {
5057 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5058 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5059 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5061 #endif
5062 #endif
5063 if (NULL != This->renderTarget) {
5064 #ifdef EXTRA_TRACES
5065 glFlush();
5066 vcheckGLcall("glFlush");
5067 /** This is only usefuly if the old render target was a swapchain,
5068 * we need to supercede this with a function that displays
5069 * the current buffer on the screen. This is easy to do in glx1.3 but
5070 * we need to do copy-write pixels in glx 1.2.
5071 ************************************************/
5072 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5074 printf("Hit Enter to get next frame ...\n");
5075 getchar();
5076 #endif
5079 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK){
5080 /* the selected render target doesn't belong to a swapchain, so use the devices implicite swapchain */
5081 IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5085 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5086 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5087 **********************************************************************/
5088 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK){
5089 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5090 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5091 TRACE("making swapchain active\n");
5092 if (RenderSurface != This->renderTarget){
5093 if (RenderSurface == swapchain->backBuffer){
5094 } else {
5095 /* This could be flagged so that some operations work directly with the front buffer */
5096 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5098 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5099 == False) {
5100 TRACE("Error in setting current context: context %p drawable %ld !\n",
5101 impSwapChain->glCtx, impSwapChain->win);
5105 #if 0 /* TODO: apply the state block to the 'possibly' new context. */
5106 BOOL oldRecording;
5107 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5108 oldUpdateStateBlock = This->updateStateBlock;
5109 oldRecording= This->isRecordingState;
5110 This->isRecordingState = FALSE;
5111 This->updateStateBlock = This->stateBlock;
5112 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5114 This->isRecordingState = oldRecording;
5115 This->updateStateBlock = oldUpdateStateBlock;
5116 #endif
5118 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5120 checkGLcall("glXMakeContextCurrent");
5122 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5124 #if 0
5125 else
5126 if (NULL != cfgs &&
5127 (((IWineD3DSwapChainImpl *)currentSwapchain)->drawable == ((IWineD3DSwapChainImpl *)currentSwapchain)->win
5128 || BackBufferFormat != ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Format
5129 || (Width > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width
5130 || Height > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height))) {
5132 /** ********************************************************************
5133 * This code is far too leaky to be usefull IWineD3DDeviceImpl_CleanRender
5134 * doesn't seem to work properly and creating a new context Every time is 'extream' overkill.
5135 * The code does however work, and should be moved to a context manager to
5136 * manage caching of pbuffers or render to texture are appropriate.
5138 * There are some real speed vs compatability issues here:
5139 * we should really use a new context for every texture, but that eats ram.
5140 * we should also be restoring the texture to the pbuffer but that eats CPU
5141 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5142 * but if this means reusing the display backbuffer then we need to make sure that
5143 * states are correctly preserved.
5144 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5145 * and gain a good performance increase at the cost of compatability.
5146 * I would suggest that, when this is the case, a user configurable flag be made
5147 * available, alowing the user to choose the best emmulated experiance for them.
5148 *********************************************************************/
5151 * TODO: support for faces of cube textures, possibly volumes
5152 * (this should be easy for ATI as I have examples)
5155 GLXContext newContext;
5156 Drawable newDrawable;
5157 XVisualInfo *visinfo;
5159 TRACE("making new buffer\n");
5160 nAttribs = 0;
5161 PUSH2(GLX_PBUFFER_WIDTH, Width);
5162 PUSH2(GLX_PBUFFER_HEIGHT, Height);
5164 #if 0 /* ATI render to texture support */
5165 PUSH2(GLX_LARGEST_PBUFFER, True);/* This is ignored by ATI */
5166 PUSH2(GLX_TEXTURE_FORMAT_ATI, GLX_TEXTURE_RGBA_ATI);
5167 PUSH2(GLX_TEXTURE_TARGET_ATI, cubemap? GLX_TEXTURE_CUBE_MAP_ATI : GLX_TEXTURE_2D_ATI);
5168 PUSH2(GLX_MIPMAP_TEXTURE_ATI, mipmapped? True : False);
5169 #endif
5171 #if 0
5172 /* TODO: discardable Pbuffer */
5173 PUSH2(GLX_PRESERVED_CONTENTS, FALSE);
5174 #endif
5176 PUSH1(None);
5177 newDrawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5179 /** ****************************************
5180 *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
5181 *they note:
5182 * In future releases, we may provide the calls glXCreateNewContext,
5183 * glXQueryDrawable and glXMakeContextCurrent.
5184 * so until then we have to use glXGetVisualFromFBConfig &co..
5185 ********************************************/
5188 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5189 if (!visinfo) {
5190 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5192 newContext = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5193 XFree(visinfo);
5195 /* Make sure that the sorface exists as a glTexture */
5196 IWineD3DSurface_PreLoad(RenderSurface);
5198 newContext = glXCreateNewContext(impSwapChain->display, cfgs[0], GLX_RGBA_TYPE, impSwapChain->glCtx, TRUE);
5200 if (NULL == newContext) {
5201 ERR("cannot create glxContext\n");
5202 }else{
5203 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5204 FIXME("Created context %p drawable %ld \n", newContext, newDrawable);
5206 if (glXMakeCurrent(impSwapChain->display, newDrawable, newContext) == False) {
5208 TRACE("Error in setting current context: context %p drawable %ld\n", newContext, newDrawable);
5211 /* TODO: find out what of the current context needs to be coppied accross */
5213 checkGLcall("glXMakeContextCurrent");
5215 /* clean renderer should become part of the context manager so I'm not goint to put in in SwapChain just to remove it */
5216 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5217 /** TODO: We may need to copy the bits into the buffer,
5218 * this should !!ONLY!! be done if an operation is performed on the target
5219 * without it being cleared and the buffer is not discardable.
5220 * (basicly only bother preserving the contents if there's a possiblity that it will be reused)
5221 ** *********************************************************************/
5222 impSwapChain->drawable = newDrawable;
5223 impSwapChain->render_ctx = newContext;
5228 #endif
5229 /* clean up the current rendertargets swapchain (if it belonged to one) */
5230 if (currentSwapchain != NULL){
5231 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5234 /* Were done with the opengl context management, setup the rendertargets */
5236 tmp = This->renderTarget;
5237 This->renderTarget = RenderSurface;
5238 IWineD3DSurface_AddRef(This->renderTarget);
5239 IWineD3DSurface_Release(tmp);
5244 DWORD value;
5245 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5246 /* Check that the container is not a swapchain member */
5248 IWineD3DSwapChain *tmpSwapChain;
5249 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)){
5250 This->renderUpsideDown = TRUE;
5251 }else{
5252 This->renderUpsideDown = FALSE;
5253 IWineD3DSwapChain_Release(tmpSwapChain);
5255 /* Force updating the cull mode */
5256 TRACE("setting render state\n");
5257 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5258 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5260 /* Force updating projection matrix */
5261 This->last_was_rhw = FALSE;
5262 This->proj_valid = FALSE;
5265 ret = D3D_OK;
5267 if (cfgs != NULL){
5268 XFree(cfgs);
5269 } else {
5270 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5271 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5274 #undef PUSH1
5275 #undef PUSH2
5276 if ( NULL != impSwapChain) {
5277 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5279 LEAVE_GL();
5281 #endif
5282 #else
5284 IWineD3DSurface *tmp;
5285 /* This should be handled outside of this function */
5286 tmp = This->renderTarget;
5287 This->renderTarget = RenderSurface;
5288 IWineD3DSurface_AddRef(This->renderTarget);
5289 IWineD3DSurface_Release( tmp);
5290 tmp = This->stencilBufferTarget;
5291 This->stencilBufferTarget = StencilSurface;
5293 #endif
5294 return ret;
5298 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5299 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5300 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5301 /* TODO: the use of Impl is deprecated. */
5302 /* some basic validation checks */
5303 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5305 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5307 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5308 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5309 return D3DERR_INVALIDCALL;
5311 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5312 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5313 return D3DERR_INVALIDCALL;
5315 /* TODO: make the cursor 'real' */
5317 This->xHotSpot = XHotSpot;
5318 This->yHotSpot = YHotSpot;
5320 return D3D_OK;
5323 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5325 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5327 This->xScreenSpace = XScreenSpace;
5328 This->yScreenSpace = YScreenSpace;
5330 return;
5334 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5335 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5336 TRACE("(%p) : visible(%d)\n", This, bShow);
5338 This->bCursorVisible = bShow;
5340 return D3D_OK;
5343 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5345 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5346 return D3D_OK;
5350 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5351 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5352 /** FIXME: Resource tracking needs to be done,
5353 * The closes we can do to this is set the priorities of all managed textures low
5354 * and then reset them.
5355 ***********************************************************/
5356 FIXME("(%p) : stub\n", This);
5357 return D3D_OK;
5360 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5362 /** FIXME: Resource trascking needs to be done.
5363 * in effect this pulls all non only default
5364 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5365 * and should clear down the context and set it up according to pPresentationParameters
5366 ***********************************************************/
5367 FIXME("(%p) : stub\n", This);
5368 return D3D_OK;
5371 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs){
5372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5373 /** FIXME: always true at the moment **/
5374 if(bEnableDialogs == FALSE){
5375 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5377 return D3D_OK;
5381 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5382 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5384 FIXME("(%p) : stub\n", This);
5385 /* Setup some reasonable defaults */
5386 pParameters->AdapterOrdinal = 0; /* always for now */
5387 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5388 pParameters->hFocusWindow = 0;
5389 pParameters->BehaviorFlags =0;
5390 return D3D_OK;
5393 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5394 IWineD3DSwapChain *swapchain;
5395 HRESULT hrc = D3D_OK;
5397 TRACE("Relaying to swapchain\n");
5399 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
5400 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5401 IWineD3DSwapChain_Release(swapchain);
5403 return;
5406 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5407 IWineD3DSwapChain *swapchain;
5408 HRESULT hrc = D3D_OK;
5410 TRACE("Relaying to swapchain\n");
5412 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK){
5413 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5414 IWineD3DSwapChain_Release(swapchain);
5416 return;
5419 /**********************************************************
5420 * IWineD3DDevice VTbl follows
5421 **********************************************************/
5423 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5425 /*** IUnknown methods ***/
5426 IWineD3DDeviceImpl_QueryInterface,
5427 IWineD3DDeviceImpl_AddRef,
5428 IWineD3DDeviceImpl_Release,
5429 /*** IWineD3DDevice methods ***/
5430 IWineD3DDeviceImpl_GetParent,
5431 /*** Creation methods**/
5432 IWineD3DDeviceImpl_CreateVertexBuffer,
5433 IWineD3DDeviceImpl_CreateIndexBuffer,
5434 IWineD3DDeviceImpl_CreateStateBlock,
5435 IWineD3DDeviceImpl_CreateSurface,
5436 IWineD3DDeviceImpl_CreateTexture,
5437 IWineD3DDeviceImpl_CreateVolumeTexture,
5438 IWineD3DDeviceImpl_CreateVolume,
5439 IWineD3DDeviceImpl_CreateCubeTexture,
5440 IWineD3DDeviceImpl_CreateQuery,
5441 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5442 IWineD3DDeviceImpl_CreateVertexDeclaration,
5443 IWineD3DDeviceImpl_CreateVertexShader,
5444 IWineD3DDeviceImpl_CreatePixelShader,
5446 /*** Odd functions **/
5447 IWineD3DDeviceImpl_EvictManagedResources,
5448 IWineD3DDeviceImpl_GetAvailableTextureMem,
5449 IWineD3DDeviceImpl_GetBackBuffer,
5450 IWineD3DDeviceImpl_GetCreationParameters,
5451 IWineD3DDeviceImpl_GetDeviceCaps,
5452 IWineD3DDeviceImpl_GetDirect3D,
5453 IWineD3DDeviceImpl_GetDisplayMode,
5454 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5455 IWineD3DDeviceImpl_GetRasterStatus,
5456 IWineD3DDeviceImpl_GetSwapChain,
5457 IWineD3DDeviceImpl_Reset,
5458 IWineD3DDeviceImpl_SetDialogBoxMode,
5459 IWineD3DDeviceImpl_SetCursorProperties,
5460 IWineD3DDeviceImpl_SetCursorPosition,
5461 IWineD3DDeviceImpl_ShowCursor,
5462 IWineD3DDeviceImpl_TestCooperativeLevel,
5463 /*** Getters and setters **/
5464 IWineD3DDeviceImpl_SetClipPlane,
5465 IWineD3DDeviceImpl_GetClipPlane,
5466 IWineD3DDeviceImpl_SetClipStatus,
5467 IWineD3DDeviceImpl_GetClipStatus,
5468 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5469 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5470 IWineD3DDeviceImpl_SetDepthStencilSurface,
5471 IWineD3DDeviceImpl_GetDepthStencilSurface,
5472 IWineD3DDeviceImpl_SetFVF,
5473 IWineD3DDeviceImpl_GetFVF,
5474 IWineD3DDeviceImpl_SetGammaRamp,
5475 IWineD3DDeviceImpl_GetGammaRamp,
5476 IWineD3DDeviceImpl_SetIndices,
5477 IWineD3DDeviceImpl_GetIndices,
5478 IWineD3DDeviceImpl_SetLight,
5479 IWineD3DDeviceImpl_GetLight,
5480 IWineD3DDeviceImpl_SetLightEnable,
5481 IWineD3DDeviceImpl_GetLightEnable,
5482 IWineD3DDeviceImpl_SetMaterial,
5483 IWineD3DDeviceImpl_GetMaterial,
5484 IWineD3DDeviceImpl_SetNPatchMode,
5485 IWineD3DDeviceImpl_GetNPatchMode,
5486 IWineD3DDeviceImpl_SetPaletteEntries,
5487 IWineD3DDeviceImpl_GetPaletteEntries,
5488 IWineD3DDeviceImpl_SetPixelShader,
5489 IWineD3DDeviceImpl_GetPixelShader,
5490 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5491 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5492 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5493 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5494 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5495 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5496 IWineD3DDeviceImpl_SetRenderState,
5497 IWineD3DDeviceImpl_GetRenderState,
5498 IWineD3DDeviceImpl_SetRenderTarget,
5499 IWineD3DDeviceImpl_GetRenderTarget,
5500 IWineD3DDeviceImpl_SetSamplerState,
5501 IWineD3DDeviceImpl_GetSamplerState,
5502 IWineD3DDeviceImpl_SetScissorRect,
5503 IWineD3DDeviceImpl_GetScissorRect,
5504 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5505 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5506 IWineD3DDeviceImpl_SetStreamSource,
5507 IWineD3DDeviceImpl_GetStreamSource,
5508 IWineD3DDeviceImpl_SetStreamSourceFreq,
5509 IWineD3DDeviceImpl_GetStreamSourceFreq,
5510 IWineD3DDeviceImpl_SetTexture,
5511 IWineD3DDeviceImpl_GetTexture,
5512 IWineD3DDeviceImpl_SetTextureStageState,
5513 IWineD3DDeviceImpl_GetTextureStageState,
5514 IWineD3DDeviceImpl_SetTransform,
5515 IWineD3DDeviceImpl_GetTransform,
5516 IWineD3DDeviceImpl_SetVertexDeclaration,
5517 IWineD3DDeviceImpl_GetVertexDeclaration,
5518 IWineD3DDeviceImpl_SetVertexShader,
5519 IWineD3DDeviceImpl_GetVertexShader,
5520 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5521 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5522 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5523 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5524 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5525 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5526 IWineD3DDeviceImpl_SetViewport,
5527 IWineD3DDeviceImpl_GetViewport,
5528 IWineD3DDeviceImpl_MultiplyTransform,
5529 IWineD3DDeviceImpl_ValidateDevice,
5530 IWineD3DDeviceImpl_ProcessVertices,
5531 /*** State block ***/
5532 IWineD3DDeviceImpl_BeginStateBlock,
5533 IWineD3DDeviceImpl_EndStateBlock,
5534 /*** Scene management ***/
5535 IWineD3DDeviceImpl_BeginScene,
5536 IWineD3DDeviceImpl_EndScene,
5537 IWineD3DDeviceImpl_Present,
5538 IWineD3DDeviceImpl_Clear,
5539 /*** Drawing ***/
5540 IWineD3DDeviceImpl_DrawPrimitive,
5541 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5542 IWineD3DDeviceImpl_DrawPrimitiveUP,
5543 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5544 IWineD3DDeviceImpl_DrawRectPatch,
5545 IWineD3DDeviceImpl_DrawTriPatch,
5546 IWineD3DDeviceImpl_DeletePatch,
5547 IWineD3DDeviceImpl_ColorFill,
5548 IWineD3DDeviceImpl_UpdateTexture,
5549 IWineD3DDeviceImpl_UpdateSurface,
5550 IWineD3DDeviceImpl_StretchRect,
5551 IWineD3DDeviceImpl_GetRenderTargetData,
5552 IWineD3DDeviceImpl_GetFrontBufferData,
5553 /*** Internal use IWineD3DDevice methods ***/
5554 IWineD3DDeviceImpl_SetupTextureStates
5558 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5559 WINED3DRS_ALPHABLENDENABLE ,
5560 WINED3DRS_ALPHAFUNC ,
5561 WINED3DRS_ALPHAREF ,
5562 WINED3DRS_ALPHATESTENABLE ,
5563 WINED3DRS_BLENDOP ,
5564 WINED3DRS_COLORWRITEENABLE ,
5565 WINED3DRS_DESTBLEND ,
5566 WINED3DRS_DITHERENABLE ,
5567 WINED3DRS_FILLMODE ,
5568 WINED3DRS_FOGDENSITY ,
5569 WINED3DRS_FOGEND ,
5570 WINED3DRS_FOGSTART ,
5571 WINED3DRS_LASTPIXEL ,
5572 WINED3DRS_SHADEMODE ,
5573 WINED3DRS_SRCBLEND ,
5574 WINED3DRS_STENCILENABLE ,
5575 WINED3DRS_STENCILFAIL ,
5576 WINED3DRS_STENCILFUNC ,
5577 WINED3DRS_STENCILMASK ,
5578 WINED3DRS_STENCILPASS ,
5579 WINED3DRS_STENCILREF ,
5580 WINED3DRS_STENCILWRITEMASK ,
5581 WINED3DRS_STENCILZFAIL ,
5582 WINED3DRS_TEXTUREFACTOR ,
5583 WINED3DRS_WRAP0 ,
5584 WINED3DRS_WRAP1 ,
5585 WINED3DRS_WRAP2 ,
5586 WINED3DRS_WRAP3 ,
5587 WINED3DRS_WRAP4 ,
5588 WINED3DRS_WRAP5 ,
5589 WINED3DRS_WRAP6 ,
5590 WINED3DRS_WRAP7 ,
5591 WINED3DRS_ZENABLE ,
5592 WINED3DRS_ZFUNC ,
5593 WINED3DRS_ZWRITEENABLE
5596 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5597 WINED3DTSS_ADDRESSW ,
5598 WINED3DTSS_ALPHAARG0 ,
5599 WINED3DTSS_ALPHAARG1 ,
5600 WINED3DTSS_ALPHAARG2 ,
5601 WINED3DTSS_ALPHAOP ,
5602 WINED3DTSS_BUMPENVLOFFSET ,
5603 WINED3DTSS_BUMPENVLSCALE ,
5604 WINED3DTSS_BUMPENVMAT00 ,
5605 WINED3DTSS_BUMPENVMAT01 ,
5606 WINED3DTSS_BUMPENVMAT10 ,
5607 WINED3DTSS_BUMPENVMAT11 ,
5608 WINED3DTSS_COLORARG0 ,
5609 WINED3DTSS_COLORARG1 ,
5610 WINED3DTSS_COLORARG2 ,
5611 WINED3DTSS_COLOROP ,
5612 WINED3DTSS_RESULTARG ,
5613 WINED3DTSS_TEXCOORDINDEX ,
5614 WINED3DTSS_TEXTURETRANSFORMFLAGS
5617 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5618 WINED3DSAMP_ADDRESSU ,
5619 WINED3DSAMP_ADDRESSV ,
5620 WINED3DSAMP_ADDRESSW ,
5621 WINED3DSAMP_BORDERCOLOR ,
5622 WINED3DSAMP_MAGFILTER ,
5623 WINED3DSAMP_MINFILTER ,
5624 WINED3DSAMP_MIPFILTER ,
5625 WINED3DSAMP_MIPMAPLODBIAS ,
5626 WINED3DSAMP_MAXMIPLEVEL ,
5627 WINED3DSAMP_MAXANISOTROPY ,
5628 WINED3DSAMP_SRGBTEXTURE ,
5629 WINED3DSAMP_ELEMENTINDEX
5632 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5633 WINED3DRS_AMBIENT ,
5634 WINED3DRS_AMBIENTMATERIALSOURCE ,
5635 WINED3DRS_CLIPPING ,
5636 WINED3DRS_CLIPPLANEENABLE ,
5637 WINED3DRS_COLORVERTEX ,
5638 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5639 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5640 WINED3DRS_FOGDENSITY ,
5641 WINED3DRS_FOGEND ,
5642 WINED3DRS_FOGSTART ,
5643 WINED3DRS_FOGTABLEMODE ,
5644 WINED3DRS_FOGVERTEXMODE ,
5645 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5646 WINED3DRS_LIGHTING ,
5647 WINED3DRS_LOCALVIEWER ,
5648 WINED3DRS_MULTISAMPLEANTIALIAS ,
5649 WINED3DRS_MULTISAMPLEMASK ,
5650 WINED3DRS_NORMALIZENORMALS ,
5651 WINED3DRS_PATCHEDGESTYLE ,
5652 WINED3DRS_POINTSCALE_A ,
5653 WINED3DRS_POINTSCALE_B ,
5654 WINED3DRS_POINTSCALE_C ,
5655 WINED3DRS_POINTSCALEENABLE ,
5656 WINED3DRS_POINTSIZE ,
5657 WINED3DRS_POINTSIZE_MAX ,
5658 WINED3DRS_POINTSIZE_MIN ,
5659 WINED3DRS_POINTSPRITEENABLE ,
5660 WINED3DRS_RANGEFOGENABLE ,
5661 WINED3DRS_SPECULARMATERIALSOURCE ,
5662 WINED3DRS_TWEENFACTOR ,
5663 WINED3DRS_VERTEXBLEND
5666 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5667 WINED3DTSS_TEXCOORDINDEX ,
5668 WINED3DTSS_TEXTURETRANSFORMFLAGS
5671 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5672 WINED3DSAMP_DMAPOFFSET